Reports
CRÍTICA[RCE]#3619288

DuckDuckGo: un workflow con pull_request_target permitía ejecutar código y robar un PAT de privacy-configuration

Un workflow de GitHub Actions de duckduckgo/privacy-configuration ejecutaba código de forks con acceso a secretos, lo que permitía robar un token capaz de aprobar cambios en la configuración de privacidad de todos los navegadores de DuckDuckGo.

Resumen
Resumen en castellano de un reporte público, no una traducción literal. El código y los comandos se mantienen como en el original.

Resumen

El repositorio duckduckgo/privacy-configuration contiene la configuración que usan los navegadores y extensiones de DuckDuckGo para bloquear rastreadores y protegerse contra el fingerprinting. Uno de sus workflows de GitHub Actions, .github/workflows/auto-respond-pr.yml, se disparaba con el evento pull_request_target, que se ejecuta en el contexto privilegiado del repositorio original y con acceso a sus secretos, aunque la pull request venga de un fork.

El problema tenía dos partes:

  1. La rama "base" también salía del fork. El paso que debía descargar el código base del repositorio original usaba como origen el repositorio de la PR:

`` repository: ${{ github.event.pull_request.head.repo.full_name }} ``

Es decir, tanto la copia "base" como la copia "PR" eran código controlado por el atacante. Cualquier comparación entre ambas para validar cambios quedaba anulada.

  1. Se ejecutaba ese código. Sobre esas copias el workflow lanzaba:

`` npm ci node index.js ``

y en los pasos siguientes tenía disponible el secreto PRIVACY_CONFIG_PAT, un Personal Access Token que se usaba para aprobar PR automáticamente.

Además, otro job del mismo workflow, sync_asana_on_close, exponía sin ninguna condición los secretos ASANA_ACCESS_TOKEN y GH_RO_PAT cada vez que se cerraba una PR, también las de forks.

El investigador aclara que es un fallo distinto de otro que reportó a la vez (#3619287, en content-scope-scripts/semver-label.yml): otro repositorio, otros secretos, otra vía de ataque y una cadena de suministro más corta.

Cómo se explotaba

La parte divulgada del reporte no incluye el YAML completo del workflow ni una prueba de concepto paso a paso. Según la descripción del investigador, bastaba con una cuenta de GitHub:

  1. Hacer un fork de duckduckgo/privacy-configuration y modificar en él el código que el workflow ejecuta.
  2. Abrir una pull request desde el fork contra el repositorio original.
  3. pull_request_target dispara auto-respond-pr.yml, que descarga el fork como "base" y como "PR", ejecuta npm ci y node index.js, y deja PRIVACY_CONFIG_PAT al alcance del código del atacante.
  4. Al cerrar cualquier PR, incluidas las de forks, el job sync_asana_on_close expone también ASANA_ACCESS_TOKEN y GH_RO_PAT.

Impacto

  • Ejecución de código y robo del PAT: cualquier usuario de GitHub podía ejecutar código arbitrario en el runner de Actions y llevarse PRIVACY_CONFIG_PAT. Según el investigador, ese token probablemente tenía permisos repo, lo que permitiría aprobar sus propias PR, hacer push a ramas y leer repositorios privados.
  • Cadena de suministro hacia todos los navegadores de DuckDuckGo: duckduckgo-privacy-extension consume privacy-configuration desde la rama main sin fijar etiqueta ni SHA. Con el token robado, un atacante podría aprobar y fusionar en main una configuración maliciosa que entraría en la siguiente compilación de los productos de DuckDuckGo: Android, iOS, macOS y las extensiones de Chrome y Firefox.
  • Degradación silenciosa de la privacidad: a diferencia de inyectar código, que puede provocar fallos visibles, una configuración envenenada podría desactivar el bloqueo de rastreadores o la protección contra fingerprinting sin que el usuario notara nada, creyéndose protegido.
  • Más secretos expuestos: ASANA_ACCESS_TOKEN daba acceso a la gestión de proyectos de DuckDuckGo en Asana, y GH_RO_PAT, acceso de lectura en GitHub.

El reporte se envió el 21 de marzo de 2026, consta como resuelto y se hizo público el 11 de junio de 2026.