feat(plugins): stage agent-visible plugin bundles with digest verification and agent env scrub - #89
Open
dmorosanu wants to merge 4 commits into
Open
feat(plugins): stage agent-visible plugin bundles with digest verification and agent env scrub#89dmorosanu wants to merge 4 commits into
dmorosanu wants to merge 4 commits into
Conversation
…ation and agent env scrub
… answer-key guards
dmorosanu
requested review from
akshaylive,
bai-uipath,
tmatup and
uipreliga
as code owners
August 6, 2026 15:46
|
Claude finished @dmorosanu's task in 1m 31s —— View job 🔍 Reviewing PR #89: Plugin Bundle Staging with Digest VerificationTodo List:
|
…message and tests
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

What
Stages an allowlisted, digest-verified copy of every
agent.plugins[{type: local}]source and hands the agent that path instead of the raw checkout.src/coder_eval/plugin_bundle.py— builds a bundle per resolved source path (once per process, thread-safe, cached) under a temp staging root:skills,commands,agents,.claude-plugin,hooks. An allowlist, not a denylist, so a newly added answer-bearing top-level directory is excluded by default.RESOLUTION.md,check_*.py) fails the build loudly rather than shipping. A symlink whose target escapes the source root fails the build; in-root symlinks are copied verbatim, never followed (loop-proof).Every layer fails closed: a violation raises
PluginBundleErrorand nothing ever falls back to the raw path.orchestrator.py—_stage_agent_plugin_bundles()rewritesagent.plugins[].pathto the bundle before agent creation, so the projection is driver-independent (tempdir and docker alike) and lands at a single choke point. The resulting digests are recorded inenvironment_info["plugin_bundles"]. Skipped whenCODER_EVAL_IN_CONTAINERis set, where the docker driver's own staging surface already applies.Agent env scrub (
utils.py+ the three agent spawn seams) —SKILLS_REPO_PATHand theCODER_EVAL_*prefix are masked from every agent subprocess. The overrides are explicit empty values, not omissions: the SDK merges{**os.environ, **options.env}, so an omitted key would simply be inherited. Antigravity, which spawns its harness offos.environ, scrubs and restores inside the existing spawn-guard window.Lint rule CE034 (
tests/lint/rules/ce034_plugin_bundle_choke_point.py) — keeps the staging call at its single choke point so a future agent cannot re-introduce a raw plugin path.Why
A task's local plugin path typically expands to an entire skills checkout. Handed to the agent raw, that path also exposes the repo's own grading material —
RESOLUTION.mdreference answers,check_*.pygrader scripts, andtests/fixtures with golden outputs — giving the evaluated agent unintended access to the answer key on every driver, not just one. The bundle projects only the plugin-consumable subtrees, so the agent sees the skills it is meant to read and nothing else.Grading is unaffected:
run_commandcriteria and the sandbox environment keep resolving$SKILLS_REPO_PATHto the raw checkout (covered by a dedicated test), because the scrub applies at agent-spawn seams only.Validation
make verifyon the rebased branch (Windows, Python 3.13):ruff format --check— 362 files already formattedruff check— all checks passedpyright— 0 errors (1 pre-existing warning inantigravity_agent.py, unchanged frommain)tests/test_custom_lint.py) — 177 passed, CE034 registered and uniqueNew tests:
tests/test_plugin_bundle.py(26 cases) covering the adversarial projection, hidden-material detection inside allowed subtrees, symlink safety, digest verification and fail-closed drift, once-per-source and concurrent staging, the orchestrator seam (including the in-container skip), and the env scrub vs. grading-env split. Plus scrub coverage intests/test_codex_agent.py/tests/test_antigravity_agent.pyand a CE034 rule test.The 105 skips are the usual POSIX-only cases on Windows (docker driver, symlinks, mode bits). Two
tests/test_sandbox.pyfailures on this machine (WinError 1314, symlink creation without Developer Mode) are pre-existing onmainand touch files this branch does not modify.