# Remote code execution in cdnjs of Cloudflare

cdnjs autoupdate server extracted npm tarballs and git symlinks without sanitizing paths, letting a crafted package read /proc/self/environ and leak GitHub/KV API tokens.

- Payout: Research
- Severity: critical
- Program: Cloudflare
- Write-up by: RyotaK
- Disclosed: 2021-07-15
- Write-up quality: 9/10
- Original: https://blog.ryotak.net/post/cdnjs-remote-code-execution-en/
- Library page: https://bugbountylibrary.com/r/blog%3Ablog-ryotak-net-post-cdnjs-remote-code-execution-en
- Tags: area:cloud domain:infra impact:data-leak impact:integrity impact:rce kind:research platform:research sev:critical tech:go technique:chained technique:source-review vuln:path-traversal vuln:rce vuln:secrets-leak

**Target:** cdnjs library autoupdate server (Go tool cdnjs/tools, npm tarball and git repo ingestion)
**Root cause:** Untar used filepath.Join(dst, removePackageDir(header.Name)) where removePackageDir only strips the package/ prefix, so ../ sequences in tar entry names escape the temp dir; MoveFile also followed git symlinks when copying files.
**Steps:**
1. Read cdnjs/bot-ansible and cdnjs/tools; note autoupdate runs periodically and the running user can write the scheduled scripts.
2. Craft npm .tgz with entry name like `../../../../../../../path/to/scheduled/script` (e.g. via evilarc) and publish to npm registry.
3. Wait for autoupdate to download and Untar the tarball; the traversal overwrites the regularly executed script with attacker content.
4. Alternatively, add a symlink in a git-tracked library repo: `ln -s /proc/self/maps test.js`, publish a new version.
5. MoveFile opens the symlink source and copies its contents into the published library file, exposing environment variables.
**How found:** Targeting supply-chain attack surface, browsed cdnjs site, found library metadata managed via GitHub org; read bot-ansible/tools, guessed Go archive/tar doesn't sanitize names, confirmed removePackageDir only strips package/ prefix; then while planning RCE demo, read MoveFile and noticed symlinks aren't handled, pivoting to arbitrary file read.
**Exploitation:** Attacker publishes a malicious npm package version (or git repo with symlink) consumed by cdnjs autoupdate; path traversal overwrites a cron-executed script for RCE, or symlink copy exfiltrates /proc/self/environ (accidentally linked instead of /proc/self/maps) containing GITHUB_REPO_API_KEY and WORKERS_KV_API_TOKEN, which grant write to all cdnjs GitHub repos and Workers KV, enabling tampering of libraries served to 12.7% of websites.
**Escalation:** Leaked GITHUB_REPO_API_KEY (robocdnjs, write on all repos) plus WORKERS_KV_API_TOKEN (KV cache write) chain to full compromise of cdnjs origin data, KV cache, and cdnjs.com, enabling mass supply-chain tampering of served libraries.
**Insight:** When a service ingests third-party archives (npm/git), check whether extraction uses filepath.Join with unsanitized tar header names and whether file-copy helpers follow symlinks; also check what the ingestion process's environment holds, since /proc/self/environ turns a file-read into credential theft.

## Proof of concept (copied exactly from the original report)

**Symlink to /proc/self/environ published to Git repo**

```
ln -s /proc/self/maps test.js
```

