#107 Hostile .forge symlinks escape the repo and publish host files

closedkind:securityopened
details
updated
id
43b943b9-4e27-4b4a-a7d2-550f9a1e99d5

Problem

The .forge symlink refusal is incomplete. read_text_capped checks only the final file, but build readers follow a symlinked .forge root or section root, and artifact copy plus PR patch/CI log reads have no symlink check at all. A hostile repo can make hu13 build copy host files into the public site (including private inbox files, SSH keys, or CI secrets).

Verified vectors:

  1. .forge -> /tmp/secret-forge (external tree with issues/... and wiki/secret.md): build emits issues/leak.html and wiki/secret.md.html containing the external text.
  2. .forge/wiki -> /tmp/secret-wiki: build emits the external markdown page.
  3. .forge/releases/out/v1 -> /tmp/secret-dir: collect_artifacts/copy_tree follow the root symlink and copy /tmp/secret-dir/secret.txt to dist/releases/v1/secret.txt (downloadable).
  4. .forge/prs/<uuid>/patch.diff -> /tmp/secret.txt: build renders the external file as the PR patch.
  5. .forge/ci/runs/<ts>/steps/00.log -> /tmp/secret.log: build renders the external file as a CI log.

src/forge.rs:640 and src/forge.rs:842 use raw std::fs::read; src/releases.rs:127/181/476 start at the configured root; src/wiki.rs and src/releases.rs only reject entry-level symlinks.

Impact

Arbitrary local-file disclosure into dist/ when building an untrusted checkout. The same files can be served by serve/Pages. The patch and CI log reads are also unbounded, so a large .forge file can OOM the build even without a symlink.

Fix

Comments (1)

all issues