Raised during review of #18 (codex findings). The integration test tests/demoscene-bundle.test.mjs fetches the live production Demoscene bundle over HTTPS and executes it in-process via node:vm.runInContext.
The issue: node:vm is explicitly not a security sandbox. Code inside the vm context can recover the host Node process and gain full fs/env/credentials access — e.g. via setTimeout.constructor('return process')(). Reproduced during review (stripping host console does not close the escape; any function in the context exposes the Function constructor).
Exposure: npm test runs in .github/workflows/publish.yml in the same job that mints a write-capable GitHub App token and then performs authenticated git push. A compromise of the Pages deployment (axisrow.github.io/demoscene_classics) could mutate workspace/tooling and capture the App token. On pull_request runs (ci.yml) there are no secrets, so blast radius there is nil.
Accepted residual risk for #18 (bundle is first-party over HTTPS; trade-off weighed against keeping the test a true live regression guard), tracked here as a follow-up rather than a merge blocker.
Suggested fixes (pick one):
- Pin a content-hash-verified local fixture of the bundle and execute that instead of a network fetch in
npm test.
- Move the live canary into a separate disposable CI job with
permissions: contents: read, no secrets, no deployment perms, no writable shared workspace.
Refs #18.
Raised during review of #18 (codex findings). The integration test
tests/demoscene-bundle.test.mjsfetches the live production Demoscene bundle over HTTPS and executes it in-process vianode:vm.runInContext.The issue:
node:vmis explicitly not a security sandbox. Code inside the vm context can recover the host Nodeprocessand gain full fs/env/credentials access — e.g. viasetTimeout.constructor('return process')(). Reproduced during review (stripping hostconsoledoes not close the escape; any function in the context exposes theFunctionconstructor).Exposure:
npm testruns in.github/workflows/publish.ymlin the same job that mints a write-capable GitHub App token and then performs authenticatedgit push. A compromise of the Pages deployment (axisrow.github.io/demoscene_classics) could mutate workspace/tooling and capture the App token. Onpull_requestruns (ci.yml) there are no secrets, so blast radius there is nil.Accepted residual risk for #18 (bundle is first-party over HTTPS; trade-off weighed against keeping the test a true live regression guard), tracked here as a follow-up rather than a merge blocker.
Suggested fixes (pick one):
npm test.permissions: contents: read, no secrets, no deployment perms, no writable shared workspace.Refs #18.