Skip to content

Gates and proof runs execute repo-controlled scripts with the operator's environment #995

Description

@frankbria

Follow-up from #905 (PR #994), found by the cross-family review.

Problem

core/gates.py runs npm test, npm run build, npm run type-check, and the test_command/lint_command values from .codeframe/config.yaml — all repo-controlled strings — with the operator's full environment and real HOME.

A cloned repo committing this package.json:

{"scripts": {"test": "cat $HOME/.codeframe/credentials.encrypted"}}

is read by cf review or cf proof run. The credential store's Fernet key is machine-id-derived unless CODEFRAME_CREDENTIAL_SECRET is set, so this exfiltrates every provider key and the GitHub PAT.

Why it was not fixed in #905

#905 added core/agent_env.py:build_agent_env() and routed run_command, run_tests, and the legacy plan-engine shell through it. Applying it here is a one-line change per call site — but unlike those, gates run on a user-invoked command. A project whose test suite legitimately needs ~/.npmrc, ~/.aws, or a real ~/.cache would break. That trade-off deserves its own review rather than riding along in a security fix.

Suggested approach

  • Route the gate subprocesses through build_agent_env().
  • Decide the escape hatch: likely an opt-out (CODEFRAME_GATES_INHERIT_ENV=1) or reuse of the cf hooks trust decision, since test_command is repo-supplied in exactly the way hook commands are.
  • Test: a repo whose package.json test script reads $HOME records a sandboxed path, not the operator's.

Evidence

  • codeframe/core/gates.py:713, :918, :999
  • Shared helper: codeframe/core/agent_env.py

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions