Plugins dsh : fonctionnement et vérifications avant
Installer un plugin dsh exécute du code tiers avec les droits de votre agent. Découvrez ses accès et les contrôles à effectuer avant de l’ajouter.
Qu’est-ce qu’un plugin dsh et que peut-il faire ?
Les plugins dsh sont des packages Node que DeepSeek Harness charge dans son propre processus. En installer un exécute le code d’un tiers avec les permissions de votre agent, sur la machine que votre agent peut déjà atteindre. Rien ne sépare un plugin chargé du reste du harness. Avant d’en installer un, demandez-vous donc quelles ressources ce code peut toucher et comment limiter cet accès.
dsh (DeepSeek Harness) est le harness open source d’agents de DeepSeek AI, construit sur un framework de plugins appelé Cordis. Le README du projet indique que tout est un plugin. L’adaptateur de modèle est un plugin. L’interface web dans laquelle vous saisissez vos commandes est un plugin. Tout ce que vous installez depuis l’extérieur du projet arrive dans la même arborescence, avec le même niveau de confiance que les composants fournis avec celui-ci. Si vous n’en avez pas encore déployé un, commencez par DeepSeek Harness sur un VPS, puis revenez ici avant d’y ajouter quoi que ce soit.
Les points d’extension auxquels un plugin peut accéder sont listés dans le AGENTS.md du dépôt. En août 2026, ils couvrent :
- LLM (large language model) : le fournisseur payé avec votre clé API
- Shell : la capacité bash, avec les fournisseurs local et pwsh
- Filesystem : l’accès aux fichiers contrôlé par des règles
- Web : les fournisseurs de recherche et de récupération de contenu
- Subprocess : un fournisseur d’arborescence de processus
- Workflow : les threads de travail
- Subagent : la délégation à d’autres agents
- Settings and credentials : votre configuration enregistrée et vos variables d’environnement
Un plugin enregistre également des outils dans ctx.tools, et la documentation précise que le schéma d’un outil enregistré est intégré à l’assemblage du prompt. C’est la seconde partie que beaucoup négligent. Un plugin peut modifier les décisions de votre agent sans que son propre code fasse quoi que ce soit d’inhabituel, car la description qu’il ajoute devient du texte lu par le modèle. Le problème est du même type que l’injection de prompt contre les agents de programmation, avec une différence : ce texte arrive lors de l’installation et reste présent jusqu’à la suppression du plugin.
Comment dsh trouve-t-il et charge-t-il les plugins ?
Il n’existe pas de répertoire global de plugins. Un dsh en cours d’exécution est un arbre de plugins composé au démarrage à partir de couches ordonnées. Le profil contient vos choix. $DSH_HOME est défini par défaut sur ~/.dsh, et chaque profil se trouve dans $DSH_HOME/profiles/<name>. Les profils web et headless sont créés automatiquement lors de leur première utilisation à partir des modèles fournis.
Un répertoire de profil contient deux fichiers qui déterminent toute la configuration :
package.json, qui contient les dépendances de plugins externes ainsi qu’un manifestedsh.profilecontenant la liste ordonnéebundlescordis.patch.yml, votre propre couche de correctifs appliquée par-dessus ces bundles
ls ~/.dsh
ls ~/.dsh/profiles/webAu démarrage, les couches sont appliquées dans cet ordre. Les couches suivantes prennent le dessus :
- une racine vide
- les bundles du profil, dans l’ordre indiqué par le manifeste
- le
cordis.patch.ymldu profil $DSH_HOME/cordis.patch.yml- les éventuelles couches
--patch <path>transmises sur la ligne de commande
Deux flags affichent le résultat de cette composition sans rien démarrer :
dsh --profile web --dump-default-config
dsh --profile web --dump-config--dump-default-config affiche uniquement l’arbre composé. --dump-config ajoute les couches de correctifs du profil et du home. C’est donc ce qui se rapproche le plus d’un inventaire fiable de ce que votre prochain démarrage chargera. Consultez-le avant d’accorder votre confiance à une machine dont vous avez hérité.
Attention aux fichiers de correctifs. Ici, la configuration ne se limite pas à des données inertes, car le format autorise des valeurs marquées !!js dans le bloc config d’un plugin. Un extrait cordis.patch.yml copié depuis un message de forum est du code. Traitez-le comme un script shell provenant de la même source.
Que lance réellement dsh plugin add ?
dsh plugin --profile <name> <args> transmet ses arguments à pnpm dans le répertoire du profil concerné. pnpm doit donc être présent dans le PATH. Les verbes sont ceux de pnpm :
dsh plugin --profile web add '<package-or-git-spec>'
dsh plugin --profile web remove '<package-name>'
dsh plugin --profile web why '<package-name>'
dsh plugin --profile web updateLe modèle de sécurité de l’installation d’un plugin dsh est donc celui de l’installation de toute dépendance de type npm, avec une étape supplémentaire au cours de laquelle le résultat est chargé dans votre agent. Le package apporte son propre arbre de dépendances, et chaque package de cet arbre s’exécute dans le même processus. Tout ce qui est décrit dans le fonctionnement des attaques de la chaîne logistique npm contre un serveur s’applique ici sans modification.
pnpm 10 et les versions ultérieures n’exécutent pas les scripts de build d’une dépendance par défaut. L’autorisation s’effectue package par package avec onlyBuiltDependencies ou pnpm approve-builds. Vérifiez la version de pnpm installée :
pnpm --versionCe comportement par défaut est utile, mais c’est aussi la fonctionnalité de sécurité la plus souvent mal comprise de l’écosystème. Le blocage des scripts de build empêche l’exécution de code pendant l’installation. Il ne protège pas contre le plugin lui-même, car un plugin est précisément conçu pour être importé par le harness, puis appelé au démarrage suivant. Un plugin n’a pas besoin d’un hook postinstall. Il a été explicitement chargé.
À lire avant d’installer un plugin dsh
Téléchargez l’archive tar publiée et lisez-la. Rien ne s’exécute lorsque vous décompressez une archive.
npm pack '<package-name>@<version>'
tar -tzf '<package-name>-<version>.tgz'
tar -xzf '<package-name>-<version>.tgz'
less package/package.jsonQuatre champs de cette package.json vous fournissent l’essentiel des informations nécessaires. Consultez scripts pour connaître les entrées preinstall, install et postinstall. Consultez dependencies pour les noms que vous ne reconnaissez pas ou qui ne diffèrent que d’un caractère de noms connus. Consultez bin pour tout ce que le paquet veut ajouter à votre PATH. Consultez main ou exports pour trouver le fichier d’entrée, puis ouvrez ce fichier et suivez son exécution.
Lisez ensuite le code qui sera réellement chargé. Un plugin qui annonce un outil de notification n’a aucune raison de lire ~/.ssh, d’appeler un hôte dont vous n’avez jamais entendu parler ou de lancer un shell. Si le paquet fournit uniquement du JavaScript inclus ou minifié et qu’aucun code source correspondant n’existe dans un dépôt public, vous avez votre réponse. Préférez les plugins dont le code source est consultable, et privilégiez les plugins de petite taille.
Vous pouvez également interroger le registre sans rien installer :
pnpm view '<package-name>' dependencies
pnpm view '<package-name>' versionsUn paquet publié la semaine dernière, avec une seule version, sans champ de dépôt et dont le nom masque celui d’un paquet populaire : c’est la plus vieille astuce de tous les registres. Vérifier les téléchargements avec des sommes de contrôle est le réflexe complémentaire : sachez exactement ce que vous avez récupéré avant de l’exécuter.
Figez la version et conservez le lockfile
Une plage de versions flottante permet au code exécuté par le processus de votre agent de changer lors d’une installation ou d’une mise à jour, sans que vous ayez rien décidé. Figez la version.
dsh plugin --profile web add --save-exact '<package-name>@<version>'La position des options varie selon les versions de pnpm. Vérifiez donc le résultat au lieu de faire confiance à la commande. Ouvrez ensuite le package.json du profil et vérifiez que la dépendance apparaît sous la forme d’une version seule, sans ^ ni ~ devant. Ce fichier détermine ce qui sera installé.
Conservez ensuite le lockfile. Il fige l’ensemble de l’arbre des dépendances transitives, et pas seulement le nom de la dépendance de premier niveau :
find ~/.dsh -maxdepth 3 -name 'pnpm-lock.yaml'Copiez-le à un emplacement inclus dans vos sauvegardes, avec le package.json du profil. Ces deux fichiers permettent de reconstruire le même arbre sur un nouveau serveur. Exécutez dsh plugin --profile web update lorsque vous avez décidé de changer de version, jamais pour faire du nettoyage courant, puis lisez le diff du lockfile.
Pour un plugin installé depuis git plutôt que depuis un registry, figez le commit au lieu de la branche. Une spécification de la forme github:owner/repo#<full commit sha> fournit un arbre fixe. Un nom de branche récupère ce que cette branche contient au prochain calcul des dépendances par pnpm. Vous confiez alors cette décision à quelqu’un d’autre. Le harness impose la même discipline, car chaque build dsh publié est une release candidate et une installation non figée peut résoudre une version différente n’importe quel jour. C’est l’origine de la plupart des erreurs d’installation et de version de dsh.
La place de marché des plugins, et la valeur réelle de la « curation »
dsh dispose d’une place de marché qui s’installe comme un plugin. Cela révèle un élément de son architecture :
dsh plugin --profile web add dshmarketAprès un redémarrage, elle apparaît dans Settings, puis Plugin Market. Son README présente clairement ses limites. Les installations sont limitées aux sources répertoriées dans un registre sélectionné, et toute autre source est rejetée. Les scripts de build sont bloqués par défaut. Pour en activer un, il faut l’approuver pour chaque package. Les plugins de terminal sont signalés avant leur ajout à un profil web. La phrase la plus importante précise que leur présence dans la liste ne constitue pas une recommandation, car les plugins sont du code tiers.
Une liste sélectionnée relève le niveau minimal de sécurité. Elle ne lit pas le code à votre place et ne peut pas vous dire ce que fera la prochaine version d’un plugin si le compte de son mainteneur change de propriétaire. Traitez une installation en un clic comme vous traiteriez curl | bash du même auteur. Une autre ligne de ce README mérite d’être répétée : une sauvegarde exportée peut contenir des identifiants provenant de la configuration de votre profil. Ne la joignez donc jamais à une issue publique et ne la publiez jamais sur un site de paste. Si vous cherchez une liste de départ plutôt qu’une méthode, les plugins dsh qui valent le détour est l’article complémentaire de celui-ci.
Exécuter dsh avec son propre compte, pas en tant que root
La vérification réduit la fréquence des intrusions. Le principe du moindre privilège limite ce qu’un intrus peut atteindre lorsqu’il parvient à entrer. Sur un VPS, cette seconde mesure est facile à mettre en place.
Créez un compte Unix dédié au harness, avec son propre répertoire personnel, et ne l’exécutez jamais en tant que root :
sudo adduser --disabled-password --gecos "" dshrun
sudo -iu dshrunDans cette session, démarrez le harness afin qu’il utilise le répertoire personnel de ce compte :
npx @deepseek-ai/dsh webL’interface web écoute par défaut sur http://127.0.0.1:3080. Laissez cette configuration telle quelle. Toute personne qui atteint ce port peut piloter un agent disposant d’un shell. Publier le port 3080 revient donc à publier un shell distant sans privilèges root, avec une interface conviviale. Accédez-y depuis votre ordinateur portable au moyen d’un tunnel SSH :
ssh -L 3080:127.0.0.1:3080 you@your-vpsVérifiez ensuite qu’aucun service n’écoute sur une adresse publique :
ss -lnt | grep 3080L’adresse locale doit être 127.0.0.1:3080. Si elle est 0.0.0.0:3080, votre pare-feu est le seul élément qui sépare un inconnu de votre agent. Le raisonnement présenté dans exécuter Claude Code en toute sécurité sur un VPS s’applique également à dsh. Donnez à l’agent un seul répertoire de travail qu’il peut modifier ou supprimer, et conservez hors de cette machine tout ce que vous ne pouvez pas reconstruire. Mieux encore, considérez cette machine comme une VM jetable pour les agents de codage, car reconstruire un VPS prend une heure, tandis que l’auditer prend une semaine.
Emplacement de vos clés et limites des permissions de fichiers
dsh conserve les clés d’API dans $DSH_HOME/.credentials.yaml et les variables d’environnement dans $DSH_HOME/.env. Les paramètres des modèles se trouvent dans $DSH_HOME/settings.yaml et l’historique des sessions dans $DSH_HOME/storages. La configuration des clés d’API, des modèles et des endpoints de dsh explique quelle clé placer dans chaque fichier et quelles données quittent réellement la machine selon le mode utilisé. Il est préférable de régler ce point avant d’ajouter un plugin, car chaque clé que vous configurez devient une donnée supplémentaire qu’un plugin peut lire. Protégez au minimum ces deux fichiers sensibles :
chmod 600 ~/.dsh/.credentials.yaml ~/.dsh/.env
ls -l ~/.dshLe mode 600 autorise le propriétaire à lire et à modifier le fichier, et n’accorde aucun droit aux autres utilisateurs. Cette distinction est utile avec les deux notations (modes chmod numériques et symboliques). Soyez précis sur ce que cela protège. Les permissions de fichiers protègent ces fichiers contre les autres comptes présents sur la machine. Elles ne protègent pas contre un plugin, car le plugin s’exécute avec l’utilisateur qui possède ces fichiers, dans le processus qui les lit. C’est pourquoi garder les secrets hors de portée d’un agent IA signifie ne pas les placer sur la machine. Une machine exécutant dsh ne devrait contenir que la clé du modèle dont elle a besoin. Vos identifiants cloud et vos clés de signature doivent être stockés ailleurs.
Pourquoi un plugin qui lit le Web modifie le modèle de menace
La couche Web fournit aux plugins des fournisseurs de recherche et de récupération. Un plugin qui charge une page dans votre session charge du texte qu’un attaquant peut rédiger. Un prompt de modèle ne sépare pas les instructions des données. Une page récupérée peut donc contenir une ligne destinée à votre agent, et un harness qui détient la capacité d’exécuter des commandes shell n’est plus qu’à une étape obéissante de son exécution.
Le contrôle existe déjà dans le harness. dsh-base, le premier bundle de chaque profil, fournit le sandbox et la politique d’approbation. Utilisez-les. Une session qui peut récupérer des pages non fiables doit demander une approbation pour toute opération d’écriture ou d’exécution. Ainsi, une instruction récupérée ne peut pas devenir une action par elle-même. Placer les actions de l’agent derrière des approbations explique comment déterminer où placer cette limite. La relation fonctionne aussi dans l’autre sens : votre propre serveur est une page que l’agent de quelqu’un d’autre va récupérer. C’est le cas du blocage des crawlers IA sur votre serveur.
Comment vérifier les modifications apportées par un plugin ?
Effectuez un instantané avant l’installation, installez le plugin, effectuez un instantané après l’installation, puis consultez les différences.
dsh --profile web --dump-config > /tmp/dsh-before.txt
dsh plugin --profile web add '<package-name>@<version>'
dsh --profile web --dump-config > /tmp/dsh-after.txt
diff -u /tmp/dsh-before.txt /tmp/dsh-after.txtLe diff indique quelles entrées du plugin l’installation a ajoutées à l’arbre composé. Si un plugin installé pour une fonctionnalité limitée ajoute plusieurs entrées que vous ne pouvez pas expliquer, arrêtez-vous et lisez son code source avant de le démarrer. dsh plugin --profile web why <package-name> répond à l’autre question : laquelle de vos dépendances directes a introduit un paquet donné.
Les paquets installés sont placés sous $DSH_HOME/profiles/node_modules. Vous pouvez donc également consulter l’arbre sur le disque :
ls ~/.dsh/profiles/node_modulesConservez un deuxième profil réservé aux essais. Si une installation casse le banc de test, démarrer dsh --profile <clean-name> vous permet de vérifier en quelques secondes si le plugin en est la cause.
Comment supprimer un plugin dsh ?
dsh plugin --profile web remove '<package-name>'
dsh --profile web --dump-config > /tmp/dsh-after-removal.txt
diff -u /tmp/dsh-before.txt /tmp/dsh-after-removal.txtLa suppression de la dépendance ne supprime pas toujours la configuration. Les entrées écrites dans le cordis.patch.yml du profil restent en place, car ce fichier vous appartient et le harness ne le réécrit pas à votre place. Ouvrez-le et supprimez tout bloc qui mentionne le package supprimé.
less ~/.dsh/profiles/web/cordis.patch.ymlIl faut ensuite traiter ce qu’aucune commande de désinstallation ne peut corriger. Si vous avez supprimé un plugin parce que vous ne lui faisiez plus confiance, il a déjà lu tout ce à quoi il pouvait accéder. Faites une rotation de la clé API DeepSeek dans la console du fournisseur, ainsi que de tout autre secret présent dans $DSH_HOME. Déterminez ensuite à quelles ressources du reste de votre réseau le compte Unix utilisé par le plugin pouvait accéder.
La version courte
- Lisez l’archive tar publiée avant l’installation, en commençant par
scriptset le fichier d’entrée - Épinglez la version exacte, ou le commit exact pour une spécification git, et conservez le lockfile
- Installez dans un seul profil et conservez un profil propre que vous pouvez démarrer en cas de problème
- Comparez
--dump-configavant et après chaque installation - Exécutez le harness avec son propre utilisateur Unix, sur loopback, et accédez-y via SSH
- Conservez une seule clé API sur la machine et faites-la tourner le jour où vous supprimez un plugin auquel vous ne faites plus confiance
Rien de tout cela ne justifie d’éviter les plugins. Le modèle de plugins explique l’utilité de dsh, et un harness que vous ne pouvez pas étendre finira par être remplacé. Cela signifie que vous devez savoir ce que vous avez installé, de qui cela vient et à quelle version, puis exécuter l’ensemble dans un environnement que vous pouvez reconstruire.
FAQ
Les plugins dsh sont-ils isolés les uns des autres ?
Non. Un plugin est chargé dans le processus du harness par l’intermédiaire de Cordis et peut accéder aux interfaces de capacité documentées, notamment au shell, au système de fichiers, au web, aux sous-processus, aux subagents et aux credentials. dsh-base, le premier bundle de chaque profil, fournit le sandbox et la policy d’approbation qui régissent les actions autorisées pour les outils de l’agent. C’est cette policy qui assure votre protection. Il n’existe pas de limite de permissions propre à chaque plugin. Le modèle réaliste consiste donc à considérer que l’installation d’un plugin étend votre confiance à son auteur et à chaque package de son arbre de dépendances.
Puis-je installer un plugin dsh sans exécuter ses scripts d’installation ?
pnpm 10 et les versions ultérieures bloquent par défaut les scripts de build des dépendances, et dsh plugin ... add transmet les installations à pnpm. Avec une version actuelle de pnpm, l’installation n’exécute donc pas les scripts des packages, sauf si vous approuvez le package concerné. Vérifiez votre version avec pnpm --version. Cela ne rend pas sûr un plugin dont vous n’avez pas lu le code. Le code du plugin s’exécute au boot suivant, car le harness le charge explicitement. Aucune restriction appliquée au moment de l’installation ne peut empêcher cela.
Où se trouvent réellement les plugins dsh et leur configuration ?
$DSH_HOME utilise ~/.dsh par défaut. Les profils se trouvent dans $DSH_HOME/profiles/<name>. Chacun contient un package.json avec ses dépendances de plugins, ainsi que le manifest dsh.profile des bundles ordonnés et une couche de patch cordis.patch.yml. Les packages installés se trouvent sous $DSH_HOME/profiles/node_modules. Les clés sont stockées dans $DSH_HOME/.credentials.yaml, les valeurs d’environnement dans $DSH_HOME/.env, et un $DSH_HOME/cordis.patch.yml au niveau du home s’applique à tous les profils. Exécutez dsh --profile web --dump-config pour afficher le résultat composé sans démarrer le harness.
Est-il sûr d’installer un plugin depuis le marché dsh ?
Le marché limite les installations aux sources d’un registry sélectionné et bloque les scripts de build, sauf si vous les approuvez package par package. C’est une amélioration réelle par rapport au fait de coller le nom d’un package depuis une fenêtre de chat. Son propre README précise toutefois que sa présence dans le catalogue ne constitue pas une recommandation, car les plugins sont du code tiers écrit par d’autres personnes. Lisez le code source et verrouillez la version. Exécutez le harness avec un compte utilisateur et, idéalement, sur une machine que vous pouvez vous permettre de perdre.