Skip to content

server: keep a child's environment out of the descriptor tests' failure messages - #94

Merged
novelKR merged 1 commit into
mainfrom
claude/project-thread-af6ntg
Oct 12, 2026
Merged

novelKR merged 1 commit into
mainfrom
claude/project-thread-af6ntg

Conversation

@novelKR

@novelKR novelKR commented Oct 11, 2026 •

Copy link
Copy Markdown
Owner

Issue

No issue. While #93 was validated on the owner's Mac, one descriptor test failed once, and its failure message printed the child's whole environment into a local, git-ignored validation log. That environment is the test process's own, so it carries whatever credentials the run was started with. Nothing was pushed. This change keeps the environment out of every such message.

Item Value
Base main at 3d051fa (#93's merge)
Head 6481e77, one commit
Pins Codex gitlink 6b9826e3 with its recorded patch, and DevGuard source 6e7e065, both unchanged

Summary

What this guarantees. When a descriptor test of the gateway fails, its message does not contain a child's environment.

  • Each report script prints an env: line and then the environment, always last. Failure messages print a report only up to that line (before_environment).
  • ChildReport's Debug lists descriptors and sockets and leaves the environment out. The checks that the secret never reaches a child still read the whole report, environment included.
  • The reporting worker now prints how many bytes its carrier holds before its environment instead of after it, so its messages keep that line. It still reads the carrier after it lists its descriptors.
  • The U4 probe in mcp.rs prints the same env: line, and its messages stop there too.
  • New test devguard::tests::failure_messages_leave_a_childs_environment_out: with \n and with a PTY's \r\n, neither a report's Debug nor before_environment shows a variable that only the environment holds, and the real report script prints such a variable only after its env: line.

Contract changes

None. Test code only.

Tests

  • Verified here (Linux x86_64, Rust 1.97.0), with Codex's recorded patch applied as CI applies it, and cargo started with an empty environment apart from PATH and HOME:
    • cargo fmt --check.
    • cargo clippy --locked -p codespace-server --features devguard --all-targets -- -D warnings.
    • The new test and both reporting-worker tests, a_started_worker_gets_its_settings_and_one_descriptor_never_the_secret and a_worker_whose_credential_cannot_be_used_gets_no_descriptor: 3 passed.
    • cargo test -p codespace-server --features devguard --lib -- devguard: 37 passed, 5 ignored (the ignored ones are run by their parent tests in a separate process). The tests that need DevGuard's binaries return early here without them; CI's integration and macOS jobs build the binaries and run them.
  • CI on 6481e77: CI run 38184571640 passed: plan, format and pin, policy scan, clippy (root), integration, and macOS contracts. The plan skipped the unit and Linux isolation jobs, which do not build the gateway crate. Documentation site run 38184571985 passed.

Security scenarios

  • Token logging: before this change, a failing descriptor test printed every variable of the test process in its message, and so into local validation logs and CI logs. Now it prints the report up to the environment.
  • The secret checks themselves are unchanged and still cover the child's whole output.
  • Nothing outside test code changes.

Out of scope

…re messages

The gateway's descriptor tests have each child report its descriptors and
then its environment, and their failure messages printed the whole report.
A child's environment is the test process's own, so a failing test printed
whatever credentials the run was started with into its log.

Each report now prints an `env:` line before the environment, always last,
and failure messages print a report only up to that line
(`before_environment`). `ChildReport`'s `Debug` leaves the environment out;
the checks that the secret never reaches a child still read the whole
report. The reporting worker prints how many bytes its carrier holds before
its environment rather than after it, so its messages keep that line; it
still reads the carrier after listing its descriptors. The U4 probe prints
the same `env:` line, and its messages stop there too.

A new test checks a report's `Debug` and `before_environment` against a
variable that only the environment holds, with `\n` and with a PTY's
`\r\n`, and that the real script prints such a variable only after its
`env:` line.

Test code only.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@novelKR
novelKR marked this pull request as ready for review October 11, 2026 23:47
@novelKR
novelKR merged commit d4ea680 into main Oct 12, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants