DuckDuckGo · Report #3619288
RCE + PAT Exfiltration via pull_request_target in privacy-configuration/auto-respond-pr.yml — Direct Supply Chain to All DDG Browsers
How it was found
Summary
The duckduckgo/privacy-configuration repository's .github/workflows/auto-respond-pr.yml GitHub Actions workflow uses pull_request_target trigger, checks out the fork's repository as both "base" and "PR" branches (attacker controls both), then executes npm ci + node index.js on the attacker-controlled code. The PRIVACY_CONFIG_PAT secret — a Personal Access Token used for PR auto-approval — is exposed in subsequent workflow steps. Additionally, the sync_asana_on_close job unconditionally exposes ASANA_ACCESS_TOKEN and GH_RO_PAT when any PR (including fork PRs) is closed.
This is a separate vulnerability from the previously reported content-scope-scripts/semver-label.yml finding. Different repository, different secrets, different attack path, and a shorter supply chain — privacy-configuration is consumed via a floating main branch dependency with no tag or SHA pinning.
Vulnerability Details
Root Cause
The workflow uses pull_request_target (privileged context with secrets) and contains two critical flaws:
- Fork checkout as "base": The base branch checkout uses
repository: ${{ github.event.pull_request.head.repo.full_name }}— this checks out the fork's repo, not the actual base. The attacker controls BOTH checkouts. - Arbitrary code execution:
npm ciandnode index.jsrun on fork code withPRIVACY_CONFIG_PATavailable in subsequent steps.
Vulnerable Workflow (auto-respond-pr.yml)
Cross-reference: This vulnerability is separate from report #3619287 (content-scope-scripts/semver-label.yml). Different repository, different secrets, different attack path, and a shorter supply chain.
Impact
-
RCE + PRIVACY_CONFIG_PAT Theft: Any GitHub user can execute arbitrary code on the Actions runner by opening a fork PR. The PRIVACY_CONFIG_PAT — used for PR auto-approval — is exfiltrable. This PAT likely has repo scope, enabling the attacker to approve their own PRs, push to branches, and access private repository contents.
-
Base Branch Impersonation: The "base" checkout retrieves the fork's code, not the real base. Any diff-based validation is defeated. The attacker controls 100% of the code the workflow operates on.
-
Direct Supply Chain — All DuckDuckGo Browsers: privacy-configuration controls tracker blocking, fingerprint protection, and privacy features for ALL DDG browsers. The duckduckgo-privacy-extension uses a floating main dependency with no tag or SHA pin. An attacker who steals PRIVACY_CONFIG_PAT can approve and merge a malicious PR to main, and the poisoned configuration propagates directly into the next build of every DuckDuckGo product — Android, iOS, macOS, Chrome extension, Firefox extension.
-
Silent Privacy Degradation: Unlike code injection (which may crash or behave visibly), a poisoned privacy configuration can silently disable tracker blocking or fingerprint protections for all users without any visible indicator. Users would believe they are protected while their privacy protections are disabled.
-
Additional Secrets: ASANA_ACCESS_TOKEN and GH_RO_PAT are unconditionally exposed when any fork PR is closed, enabling access to DuckDuckGo's Asana project management and GitHub read access.