SSD Nodes Learn 🎉 VPS desde $5.50/mes
Guías Matt ConnorPor Matt Connor · Actualizado 2026-08-21

Plugins de dsh: cómo funcionan y cómo revisarlos

Instalar un plugin de dsh ejecuta código ajeno con los permisos del agente. Compruebe qué puede alcanzar y cómo limitar su acceso antes de instalarlo.

¿Qué es un plugin de dsh y qué puede hacer?

Los plugins de dsh son paquetes de Node que DeepSeek Harness carga en su propio proceso. Instalar uno ejecuta código de terceros con los permisos de su agente, en la máquina a la que el agente ya puede acceder. No hay ninguna separación entre un plugin cargado y el resto de Harness. Por tanto, antes de instalar uno debe preguntarse a qué puede acceder ese código y cómo mantener ese acceso limitado.

dsh (DeepSeek Harness) es el harness de agentes de código abierto de DeepSeek AI, basado en un framework de plugins llamado Cordis. El propio README del proyecto indica que todo es un plugin. El adaptador del modelo es un plugin. La interfaz web que utiliza también es un plugin. Todo lo que instale desde fuera del proyecto se incorpora al mismo árbol y tiene el mismo nivel de confianza que las partes incluidas originalmente. Si todavía no ha puesto uno en marcha, empiece por DeepSeek Harness en un VPS y vuelva aquí antes de añadirle nada.

Los puntos de extensión a los que puede acceder un plugin aparecen en AGENTS.md del repositorio. En agosto de 2026 incluyen:

  • LLM (modelo de lenguaje grande): el proveedor que paga con su clave de API
  • Shell: la capacidad de bash, con proveedores local y pwsh
  • Filesystem: acceso a archivos controlado por políticas
  • Web: proveedores de búsqueda y obtención de contenido
  • Subprocess: un proveedor de árboles de procesos
  • Workflow: hilos de trabajo
  • Subagent: delegación a agentes adicionales
  • Settings and credentials: la configuración guardada y las variables de entorno

Un plugin también registra herramientas en ctx.tools, y la documentación indica explícitamente que el esquema de una herramienta registrada se incorpora al ensamblado del prompt. Esta segunda parte suele pasarse por alto. Un plugin puede cambiar lo que su agente decide hacer sin que su propio código haga nada inusual, porque la descripción que aporta se convierte en texto que el modelo lee. Es el mismo tipo de problema que la inyección de prompts contra agentes de programación, con una diferencia: este texto llega cuando instala el plugin y permanece hasta que lo elimina.

¿Cómo encuentra y carga plugins dsh?

No existe un directorio global de plugins. Un dsh en ejecución es un árbol de plugins compuesto durante el arranque a partir de capas ordenadas, y la unidad que contiene tus elecciones es un perfil. $DSH_HOME usa ~/.dsh de forma predeterminada, y cada perfil se encuentra en $DSH_HOME/profiles/<name>. Los perfiles web y headless se crean automáticamente durante el primer uso a partir de las plantillas incluidas.

Un directorio de perfil contiene dos archivos que determinan todo:

  • package.json, con las dependencias de plugins externos y un manifiesto dsh.profile que contiene la lista ordenada de bundles
  • cordis.patch.yml, tu propia capa de parches sobre esos paquetes
ls ~/.dsh
ls ~/.dsh/profiles/web

El arranque aplica las capas en este orden. Las capas posteriores tienen prioridad:

  1. una raíz vacía
  2. los paquetes del perfil, en el orden indicado por el manifiesto
  3. cordis.patch.yml del perfil
  4. $DSH_HOME/cordis.patch.yml
  5. cualquier superposición --patch <path> indicada en la línea de comandos

Dos flags muestran el resultado de esta composición sin iniciar nada:

dsh --profile web --dump-default-config
dsh --profile web --dump-config

--dump-default-config muestra el árbol compuesto por sí solo. --dump-config añade las capas de parches del perfil y del directorio personal, por lo que es lo más parecido a un inventario exacto de lo que cargará el próximo arranque. Léelo antes de confiar en una máquina que has heredado.

Una advertencia sobre esos archivos de parches. La configuración no es aquí un conjunto de datos inerte, porque el formato permite valores etiquetados !!js dentro del bloque config de un plugin. Un fragmento cordis.patch.yml copiado de una publicación de un foro es código. Trátalo como tratarías un script de shell procedente de la misma fuente.

¿Qué ejecuta realmente dsh plugin add?

dsh plugin --profile <name> <args> reenvía sus argumentos a pnpm dentro del directorio de ese perfil, por lo que pnpm debe estar en PATH. Los verbos son los verbos 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 update

Por tanto, el modelo de seguridad de instalar un complemento de dsh es el modelo de seguridad de instalar cualquier dependencia de estilo npm, más un paso adicional en el que el resultado se carga en el agente. El paquete incluye su propio árbol de dependencias, y todos los paquetes de ese árbol terminan en el mismo proceso. Todo lo descrito en cómo los ataques a la cadena de suministro de npm llegan a un servidor se aplica aquí sin modificaciones.

pnpm 10 y posteriores no ejecutan de forma predeterminada los scripts de compilación de una dependencia, y la aprobación se realiza por paquete mediante onlyBuiltDependencies o pnpm approve-builds. Compruebe qué versión de pnpm tiene:

pnpm --version

Ese valor predeterminado es conveniente, pero también es la función de seguridad que más se interpreta de forma errónea en este ecosistema. Los scripts de compilación bloqueados impiden que se ejecute código durante la instalación. No hacen nada respecto al complemento, porque el objetivo de un complemento es que el entorno de ejecución lo importe y lo llame en el siguiente arranque. Un complemento no necesita un enlace postinstall. Se le permitió entrar.

Qué leer antes de instalar un plugin de dsh

Descargue el tarball publicado y léalo. No se ejecuta nada al desempaquetar un archivo.

npm pack '<package-name>@<version>'
tar -tzf '<package-name>-<version>.tgz'
tar -xzf '<package-name>-<version>.tgz'
less package/package.json

Cuatro campos de ese package.json le proporcionan casi toda la información que necesita. Lea scripts para consultar las entradas de preinstall, install y postinstall. Lea dependencies para comprobar los nombres que no reconoce o los que sólo se diferencian en un carácter de otros conocidos. Lea bin para revisar cualquier elemento que el paquete quiera añadir a su PATH. Lea main o exports para localizar el archivo de entrada. Después, abra ese archivo y sígalo.

A continuación, lea el código que se cargará realmente. Un plugin que anuncia una herramienta de notificaciones no tiene motivos para leer ~/.ssh, conectarse a un host que no conoce o iniciar un shell. Si el paquete sólo incluye JavaScript integrado o minimizado y no existe el código fuente correspondiente en un repositorio público, esa es la respuesta. Dé preferencia a los plugins cuyo código fuente pueda leer y a los que sean pequeños.

También puede consultar el registro sin instalar nada:

pnpm view '<package-name>' dependencies
pnpm view '<package-name>' versions

Un paquete publicado la semana pasada, con una sola versión, sin campo de repositorio y con un nombre que imita a algo popular es el truco más antiguo de cualquier registro. Verificar las descargas con sumas de comprobación es la práctica complementaria: sepa exactamente qué ha descargado antes de permitir que se ejecute.

Fije la versión y conserve el lockfile

Un rango de versiones flotante permite que el código dentro del proceso de su agente cambie durante cualquier instalación o actualización sin que usted decida nada. Fije la versión.

dsh plugin --profile web add --save-exact '<package-name>@<version>'

La posición de los flags varía entre versiones de pnpm, así que compruebe el resultado en lugar de confiar en el comando. Abra después el package.json del perfil y confirme que la dependencia aparece como una versión simple, sin ^ ni ~ delante. Ese archivo determina lo que se instala.

Después conserve el lockfile, que fija todo el árbol transitivo y no sólo el nombre de nivel superior:

find ~/.dsh -maxdepth 3 -name 'pnpm-lock.yaml'

Cópielo en una ubicación incluida en sus copias de seguridad, junto con el package.json del perfil. Esos dos archivos reconstruyen el mismo árbol en un servidor nuevo. Ejecute dsh plugin --profile web update cuando haya decidido cambiar de versión, nunca como tarea rutinaria de limpieza, y revise después las diferencias del lockfile.

Para un plugin instalado desde git en lugar de un registro, fije el commit y no la rama. Una especificación con el formato github:owner/repo#<full commit sha> proporciona un árbol fijo. Un nombre de rama proporciona lo que contenga esa rama la próxima vez que pnpm la resuelva. Esa decisión queda así en manos de otra persona. El propio harness requiere la misma disciplina, porque cada compilación publicada de dsh es una candidata a release y una instalación sin versión fijada puede resolver otra distinta cualquier día. De ahí proceden la mayoría de errores de instalación y versión de dsh.

El mercado de plugins y el valor real de que estén «seleccionados»

dsh tiene un mercado e instala sus componentes como plugins. Esto revela algunos aspectos de su arquitectura:

dsh plugin --profile web add dshmarket

Después de reiniciar, aparece en Settings, en Plugin Market. Su README explica claramente las limitaciones. Las instalaciones se restringen a las fuentes incluidas en un registro seleccionado y cualquier otra fuente se rechaza. Los scripts de compilación están bloqueados de forma predeterminada, y habilitar uno requiere aprobar cada paquete. Los plugins de terminal se marcan antes de incorporarse a un perfil web. La frase más importante indica que aparecer en el registro no equivale a una recomendación, porque los plugins son código de terceros.

Una lista seleccionada eleva el nivel mínimo de seguridad. No revisa el código por usted y tampoco puede indicar qué hará la siguiente versión de un plugin después de que la cuenta del mantenedor cambie de propietario. Trate una instalación con un solo clic como trataría curl | bash del mismo autor. Conviene repetir otra línea de ese README: una copia de seguridad exportada puede contener credenciales del archivo de configuración de su perfil, por lo que nunca debe adjuntarla a una incidencia pública ni subirla a un sitio de publicación de texto. Si busca una lista inicial y no un método, plugins de dsh que merece la pena instalar es el artículo complementario de este.

Ejecute dsh con su propio usuario, no como root

La verificación reduce la frecuencia con la que entra algo malicioso. El principio de mínimo privilegio limita lo que puede alcanzar cuando consigue entrar. En un VPS, configurar esta segunda capa es sencillo.

Asigne al harness su propia cuenta de Unix y su propio directorio de inicio. No lo ejecute nunca como root:

sudo adduser --disabled-password --gecos "" dshrun
sudo -iu dshrun

Dentro de esa sesión, inicie el harness para que escriba su directorio de inicio con esa cuenta:

npx @deepseek-ai/dsh web

La interfaz web se sirve en http://127.0.0.1:3080 de forma predeterminada. Déjelo así. Cualquier proceso que alcance ese puerto puede controlar un agente con acceso a un shell. Por tanto, publicar 3080 equivale a publicar un shell remoto sin privilegios con una interfaz sencilla. Acceda desde su portátil mediante un túnel SSH:

ssh -L 3080:127.0.0.1:3080 you@your-vps

Después, confirme que no haya ningún proceso escuchando en una dirección pública:

ss -lnt | grep 3080

La dirección local debe mostrar 127.0.0.1:3080. Si muestra 0.0.0.0:3080, el firewall es lo único que separa a un desconocido de su agente. El razonamiento de ejecutar Claude Code de forma segura en un VPS se aplica igualmente a dsh. Asigne al agente un único directorio de trabajo que pueda modificar o destruir, y mantenga fuera de esa máquina todo lo que no pueda reconstruir. Mejor aún, trate el equipo como una VM desechable para agentes de programación, porque reconstruir un VPS cuesta una hora, mientras que auditarlo cuesta una semana.

Dónde se almacenan las claves y por qué los permisos de archivo no bastan

dsh almacena las claves de API en $DSH_HOME/.credentials.yaml y los valores de entorno en $DSH_HOME/.env, mientras que la configuración de los modelos se encuentra en $DSH_HOME/settings.yaml y el historial de sesiones, en $DSH_HOME/storages. La clave que corresponde a cada archivo y lo que realmente sale del equipo en cada modo se explica en configurar las claves de API, los modelos y los endpoints de dsh. Conviene resolverlo antes de añadir un plugin, porque cada clave que conecte es otro dato que un plugin puede leer. Restrinja los permisos de estos dos archivos sensibles:

chmod 600 ~/.dsh/.credentials.yaml ~/.dsh/.env
ls -l ~/.dsh

El modo 600 permite al propietario leer y escribir, y no concede ningún permiso al resto. Es útil conocerlo en ambas notaciones (modos numéricos y simbólicos de chmod). Sea claro sobre lo que ofrece. Los modos de archivo protegen esos archivos frente a otras cuentas del equipo. No protegen frente a un plugin, porque el plugin se ejecuta como el usuario propietario de los archivos, dentro del proceso que los lee. Por eso mantener los secretos fuera del alcance de un agente de IA implica no almacenarlos en el equipo. Un equipo con dsh debería contener sólo la clave del modelo que necesita. Las credenciales de su proveedor cloud y sus claves de firma deben almacenarse en otro lugar.

Por qué un plugin que lee la web cambia el modelo de amenazas

La interfaz Web proporciona a los plugins proveedores de búsqueda y obtención de contenido. Un plugin que carga una página en tu sesión está cargando texto que un atacante puede escribir. Un prompt de modelo no separa las instrucciones de los datos, por lo que una página obtenida puede incluir una línea dirigida a tu agente, y un harness que tenga la capacidad de ejecutar comandos queda a un paso obediente de ejecutarla.

El control ya existe en el harness. dsh-base, el primer paquete de cada perfil, incluye el sandbox y la política de aprobación. Úsalo. Una sesión que pueda cargar páginas no confiables debería requerir aprobación para cualquier acción que escriba o ejecute, de modo que una instrucción obtenida no pueda convertirse por sí sola en una acción. Controlar las acciones del agente mediante aprobaciones explica cómo decidir dónde establecer ese límite. La relación también funciona en ambas direcciones, porque tu propio servidor es una página que el agente de otra persona cargará; ese es el caso de bloquear los rastreadores de IA en tu servidor.

¿Cómo compruebo qué cambios hizo un plugin?

Cree una instantánea antes, instale el plugin, cree otra instantánea después y lea las diferencias.

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.txt

La diferencia muestra qué entradas añadió la instalación del plugin al árbol compuesto. Si instala un plugin para una función pequeña y este añade varias entradas que no puede justificar, deténgase y lea el código fuente antes de iniciarlo. dsh plugin --profile web why <package-name> responde a la otra pregunta: qué dependencia directa incorporó un paquete determinado.

Los paquetes instalados se guardan en $DSH_HOME/profiles/node_modules, por lo que también puede revisar el árbol en el disco:

ls ~/.dsh/profiles/node_modules

Mantenga un segundo perfil en el que nunca haga pruebas. Si una instalación rompe el entorno de pruebas, iniciar dsh --profile <clean-name> le permite saber en segundos si el plugin fue la causa.

¿Cómo elimino un plugin de 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.txt

Eliminar la dependencia no siempre elimina la configuración. Las entradas escritas en el cordis.patch.yml del perfil permanecen donde están, porque ese archivo es suyo y el harness no lo reescribirá. Ábralo y elimine cualquier bloque que indique el paquete que quitó.

less ~/.dsh/profiles/web/cordis.patch.yml

Después debe abordar la parte que ningún comando de desinstalación puede corregir. Si eliminó un plugin porque dejó de confiar en él, ya ha leído todo lo que podía leer. Rote la clave de API de DeepSeek en la consola del proveedor y rote también cualquier otro secreto que estuviera en $DSH_HOME. Después determine a qué podía acceder en el resto de la red la cuenta de Unix con la que se ejecutaba.

La versión breve

  • Lea el tarball publicado antes de instalarlo, empezando por scripts y el archivo de entrada
  • Fije la versión exacta o el commit exacto para una especificación de git, y conserve el lockfile
  • Instale en un solo perfil y conserve un perfil limpio que pueda iniciar cuando algo falle
  • Compare --dump-config antes y después de cada instalación
  • Ejecute el harness con su propio usuario de Unix, en loopback, y acceda a él mediante SSH
  • Mantenga una sola clave de API en el equipo y rótela el día que elimine un plugin en el que ya no confíe

Nada de esto es motivo para evitar los plugins. El modelo de plugins es la razón por la que dsh resulta útil, y un harness que no pueda ampliar será sustituido. Es una razón para saber qué instaló, de quién procede y en qué versión, y para ejecutar todo en un lugar que pueda reconstruir.

FAQ

¿dsh aísla los plugins entre sí?

No. Cordis carga cada plugin en el proceso del harness, y este puede acceder a las interfaces de capacidad documentadas, incluidas shell, sistema de archivos, web, subprocesos, subagentes y credenciales. dsh-base, el primer bundle de cada perfil, proporciona el sandbox y la política de aprobaciones que regulan lo que pueden hacer las herramientas del agente. Esa política es la que proporciona la protección. No existe un límite de permisos independiente para cada plugin. Por tanto, el modelo realista es que instalar un plugin extiende la confianza al autor y a todos los paquetes de su árbol de dependencias.

¿Puedo instalar un plugin de dsh sin ejecutar sus scripts de instalación?

pnpm 10 y las versiones posteriores bloquean de forma predeterminada los scripts de compilación de las dependencias, y dsh plugin ... add delega en pnpm. Por tanto, con una versión actual de pnpm, la instalación no ejecuta los scripts de los paquetes salvo que apruebe ese paquete. Compruebe la versión con pnpm --version. Esto no hace seguro un plugin que no haya revisado. El código propio del plugin se ejecuta durante el siguiente arranque porque el harness lo carga de forma deliberada. Ninguna restricción del momento de instalación afecta a ese comportamiento.

¿Dónde se encuentran realmente los plugins de dsh y su configuración?

$DSH_HOME usa ~/.dsh de forma predeterminada. Los perfiles se encuentran en $DSH_HOME/profiles/<name>. Cada uno contiene un package.json con sus dependencias de plugins, el manifiesto dsh.profile de bundles ordenados y una capa de parches cordis.patch.yml. Los paquetes instalados se guardan en $DSH_HOME/profiles/node_modules. Las claves están en $DSH_HOME/.credentials.yaml, los valores de entorno en $DSH_HOME/.env y un $DSH_HOME/cordis.patch.yml del nivel de usuario se aplica a todos los perfiles. Ejecute dsh --profile web --dump-config para ver el resultado compuesto sin iniciar el sistema.

¿Es seguro instalar desde el mercado de plugins de dsh?

El mercado limita las instalaciones a fuentes de un registro seleccionado y bloquea los scripts de compilación salvo que los apruebe por paquete. Esto supone una mejora real frente a pegar el nombre de un paquete desde una ventana de chat. Su propio README indica que la inclusión no constituye una recomendación, porque los plugins son código de terceros creado por otras personas. Lea el código fuente y fije la versión. Mantenga el harness en una cuenta de usuario y, preferiblemente, en una máquina cuya pérdida pueda asumir.