fix(docker): mount plugins at /work/plugins/<i> and point the staged task there - #206
Merged
Merged
Conversation
…taged task there The runner resolved each agent.plugins[].path on the host and mounted it at its host path, but the task.yaml staged into the container kept the authored string. The in-container agent then re-resolved it against the container's cwd: a relative path, or a $VAR the container did not have, pointed at nothing and the skill silently never loaded (only a warning). Now plugin i mounts :ro at /coder_eval/plugins/<i>, and the staged task.yaml is rewritten to that path, via one shared _plugin_mounts() mapping so the bind and the rewrite cannot disagree. The anti-cheat tmpfs masks move under the container path. The host-side task is untouched. Entries that do not resolve to a host directory are neither mounted nor rewritten. /coder_eval/plugins joins RESERVED_CONTAINER_DIRS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
akshaylive
requested review from
CarlesUIPath,
bai-uipath,
tmatup and
uipreliga
as code owners
September 29, 2026 20:37
…plugins Every other framework-owned container path lives under /work, and _validate_extra_mount already refuses any extra_mounts destination under /work/, so a task can no longer shadow a plugin mount with its own. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bai-uipath
approved these changes
Sep 29, 2026
pip-audit started failing on two new advisories: - pyjwt 2.13.0, CVE-2026-102274 (a malformed RSA JWK aborts parsing of the whole JWK set): floor raised to >=2.14.0; the lock resolves 2.15.1, the newest release past the safe-chain minimum package age. - oauthlib 3.3.1, CVE-2026-49265 (PKCE timing side channel): the flaw is in the server-side code_challenge check, which coder-eval never runs; oauthlib is only transitive (azure-monitor-opentelemetry-exporter -> msrest -> requests-oauthlib). The fix, 4.0.0, is a major bump published inside the minimum-age window, so ignore it in pip-audit and osv-scanner for now and revisit next month. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ignore osv-scanner flagged a second oauthlib 3.3.1 advisory, GHSA-hj66-6f7g-4r5v (CVE-2026-49264, RevocationEndpoint JSONP callback injection with enable_jsonp=True), published 2026-09-29 and not yet in pip-audit's DB. Like CVE-2026-49265 it is a server-side OAuth endpoint coder-eval never runs, and the fix is the same too-new 4.0.0, so ignore it in both scanners. PYSEC-2025-183 (pyjwt 2.12.1) no longer applies now that pyjwt is 2.15.1; osv-scanner reported it as an unused ignore. Removed from both lists. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Problem
Under
driver: docker, the runner resolved eachagent.plugins[].pathon the host and mounted it at the same host path. But thetask.yamlstaged into the container kept the path as authored, and the in-container agent resolved it again against the container's cwd. As a result, a relative or$VARplugin path silently loaded no skill:pluginor./plugin: the host mounted it correctly, but inside the container the path pointed at a directory that doesn't exist. Codex loggedPlugin skills path did not resolve: ... (path does not exist), and Claude loaded nothing.${VAR}/plugin: it works only ifVARis in the real host environment (not just.env) and is forwarded into the container. Otherwise it isn't expanded, so nothing is mounted and nothing loads.Only absolute host paths worked end to end. The failure isn't obvious, because the run still grades normally, just without the skill.
Fix
iis mounted:roat/work/plugins/<i>, a newCONTAINER_PLUGINS_DIRconstant, which is also added toRESERVED_CONTAINER_DIRS. It sits under/work, so the existingextra_mountscheck (which refuses destinations under/work/) stops a task from shadowing a plugin mount._stage_inputsrewrites plugini's path in the stagedtask.yamlto/work/plugins/<i>. The host-side task isn't modified._plugin_mounts(), which gives each plugin's host directory and container path, so the mount and the rewrite can't disagree. Host-side resolution is unchanged (_resolve_mount_path: a relative path resolves against the task YAML's directory, and$VARand~are expanded).docs/DOCKER_ISOLATION.mdis updated.Testing
TestAutoMountAllowlistMasktests now assert container-path binds and masks. The newtest_the_staged_task_yaml_points_plugins_at_their_container_mountscovers thetask.yamlrewrite.uv run pytestgives 6727 passed and 1 failed,test_codex_golden[g_items_rebuild], which fails onmaintoo.make verifystill reports one error,harbor/agent.py:65(SUPPORTS_ATIF), which is also onmain.driver: dockertask withplugins: [{type: local, path: plugin}], run on claude-code (claude-sonnet-5) and codex (gpt-5.6-luna). Both got the bind…/plugin:/work/plugins/0:ro, loaded the skill, and passed:Skillcall succeeded, and it ran the skill's scripts from/work/plugins/0/skills/….Linked skill: copilot-usage-metrics.🤖 Generated with Claude Code