You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In pipeline mode (roborev ci review), the review agent runs with its working directory set to a checkout of the pull/merge request under review. Claude Code loads project-scoped configuration from that directory, and two of those files can execute commands:
Hooks in .claude/settings.json / .claude/settings.local.json run shell commands. Under -p there is no trust prompt — the docs state that "trust verification is disabled when running non-interactively with the -p flag", and the documented workspace-trust gate for hooks covers only subagent frontmatter hooks, not settings-file hooks.
.mcp.json can launch stdio MCP servers.
roborev's read-only review allowlist (--allowedTools Read,Glob,Grep, internal/agent/claude.go:239) does not contain either, because a hook is not a tool call.
So a PR/MR author who can trigger a pipeline can get command execution in the review job, in a process that holds the forge token and the agent's provider credentials.
Affected paths
GitHub Actions — the workflow from roborev init gh-action uses on: pull_request + actions/checkout, so the working tree is the PR merge ref. Mitigating factor: GitHub does not expose repository secrets to pull_request runs from forks, so this is limited to same-repo branches (i.e. anyone with push access), not arbitrary contributors.
GitLab CI (roborev ci review in a merge_request_event pipeline, Add GitLab merge request support to roborev ci review #1004) — same shape, and GitLab does inject project variables into MR pipelines from any branch, so the exposure is wider by default.
Not affected: the daemon CI poller. It fetches the PR head ref but reviews from the diff range without checking it out, so the working tree stays on the (trusted) default branch.
Suggested fix
Have the Claude adapter neutralize untrusted project config when reviewing, rather than leaving it to each user's CI config. Claude Code documents three mechanisms:
--setting-sources user — omits project and local, dropping project settings.json and project hooks while keeping user-level config.
--bare / CLAUDE_CODE_SIMPLE=1 — skips auto-discovery of hooks, skills, plugins, MCP servers, auto memory and CLAUDE.md wholesale. Note this also changes the default tool set and skips keychain/OAuth credential reads, so it is the blunt option.
The narrow combination (--setting-sources user --strict-mcp-config) looks like the right default for CI review runs: it removes the execution vectors while leaving CLAUDE.md, .claude/rules, and project skills available as review context — which is genuinely useful signal for a reviewer. There is a residual prompt-injection risk in those context files, but instructions steering a review are a different severity from arbitrary command execution.
Worth considering whether this should apply to all review-type jobs (the local post-commit path reviews your own commits, so the trust model differs) or only to CI/pipeline reviews.
Happy to send a PR for this if the approach sounds right — it would sit on top of #1004, which is where the GitLab side of pipeline mode lands.
Summary
In pipeline mode (
roborev ci review), the review agent runs with its working directory set to a checkout of the pull/merge request under review. Claude Code loads project-scoped configuration from that directory, and two of those files can execute commands:.claude/settings.json/.claude/settings.local.jsonrun shell commands. Under-pthere is no trust prompt — the docs state that "trust verification is disabled when running non-interactively with the-pflag", and the documented workspace-trust gate for hooks covers only subagent frontmatter hooks, not settings-file hooks..mcp.jsoncan launch stdio MCP servers.roborev's read-only review allowlist (
--allowedTools Read,Glob,Grep,internal/agent/claude.go:239) does not contain either, because a hook is not a tool call.So a PR/MR author who can trigger a pipeline can get command execution in the review job, in a process that holds the forge token and the agent's provider credentials.
Affected paths
roborev init gh-actionuseson: pull_request+actions/checkout, so the working tree is the PR merge ref. Mitigating factor: GitHub does not expose repository secrets topull_requestruns from forks, so this is limited to same-repo branches (i.e. anyone with push access), not arbitrary contributors.roborev ci reviewin amerge_request_eventpipeline, Add GitLab merge request support to roborev ci review #1004) — same shape, and GitLab does inject project variables into MR pipelines from any branch, so the exposure is wider by default.Not affected: the daemon CI poller. It fetches the PR head ref but reviews from the diff range without checking it out, so the working tree stays on the (trusted) default branch.
Suggested fix
Have the Claude adapter neutralize untrusted project config when reviewing, rather than leaving it to each user's CI config. Claude Code documents three mechanisms:
--setting-sources user— omitsprojectandlocal, dropping projectsettings.jsonand project hooks while keeping user-level config.--strict-mcp-config— ignores MCP configuration outside--mcp-config.--bare/CLAUDE_CODE_SIMPLE=1— skips auto-discovery of hooks, skills, plugins, MCP servers, auto memory and CLAUDE.md wholesale. Note this also changes the default tool set and skips keychain/OAuth credential reads, so it is the blunt option.The narrow combination (
--setting-sources user --strict-mcp-config) looks like the right default for CI review runs: it removes the execution vectors while leavingCLAUDE.md,.claude/rules, and project skills available as review context — which is genuinely useful signal for a reviewer. There is a residual prompt-injection risk in those context files, but instructions steering a review are a different severity from arbitrary command execution.Worth considering whether this should apply to all review-type jobs (the local post-commit path reviews your own commits, so the trust model differs) or only to CI/pipeline reviews.
Happy to send a PR for this if the approach sounds right — it would sit on top of #1004, which is where the GitLab side of pipeline mode lands.