feat: advisory hooks, session store and disclosure docs (P3) - #13
Conversation
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
Security findingsAdvisory findings (1)ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
🛡️ Codex Security Review · Automatically triggered
Here are some automated security review suggestions for this pull request.
Reviewed commit: 6345338612
ℹ️ About Codex security reviews in GitHub
This is an experimental Codex feature. Security reviews are triggered when:
- You comment "@codex security review"
- A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review
Once complete, Codex will leave suggestions, or a comment if no findings are found.
| "type": "command", | ||
| "command": "sh", | ||
| "args": ["${CLAUDE_PLUGIN_ROOT}/scripts/run.sh", "--hook", "pre-tool-use"], | ||
| "timeout": 5, |
There was a problem hiding this comment.
🛡️ Codex Security Review · Automatically triggered
Security: Execute only the plugin-owned hook handler
When the plugin is enabled and a checkout contains .claude/rulebook.yaml, this new Write/Edit hook automatically invokes run.sh. Before reaching the plugin handler, run.sh executes any executable at $CLAUDE_PROJECT_DIR/node_modules/.bin/nestjs-hexagonal-check. A repository contributor can commit that path or a symlink and gain arbitrary code execution as the developer on the next matched write; the opt-in and containment gates pass because the rulebook, binary, and write are all inside the attacker-controlled checkout. Hook mode must use only the plugin-owned handler or an explicitly trusted, identity-verified installation.
Useful? React with 👍 / 👎.
Summary
P3 of the Jev plan: the plugin ships hooks. Version 1 is advisory: the only thing that blocks is a static FAIL rule; semantic (Jev) results are advisory text, never a gate.
hooks/hooks.json:SubagentStart(rulebook slice per layer asadditionalContext),PreToolUse Write|Edit(static rules on the resulting content; FAIL →denywith rule id, evidence and fix; WARN →additionalContextwithoutpermissionDecision, so the plugin never auto-approves a write),PostToolUse Write|Edit(records touched paths; static for every agent, semantic only for plugin subagents with a key; context only when there are findings; per-agent advisory byte cap),SubagentStopfor the six layer agents (files touched = session store ∪git diffsince the agent started; static FAIL →decision: blockwithreason; released withsystemMessageafter 2 blocks),PostToolUse Agent(residual FAILs back to the orchestrator). Every hook runs throughrun.sh --hook <name>: opt-in gate (.claude/rulebook.yaml),NESTJS_HEXAGONAL_DISABLE=1, path containment, single execution source, fail-open, always exit 0.$CLAUDE_PLUGIN_DATA/sessions/<session>/<agent>.jsonwith lock + atomic rename and 24 h GC; concurrency test with two processes.nestjs-hexagonal-check export-logs --since <date>(p50/p95 per hook, decisions by kind, uncertain/uncalibrated rates) for the pilot's weekly report.permissionDecisionReason,additionalContext,reasonor the log (tested with the key in the environment).plugin.json:defaultEnabled: false,userConfig.TYPESAFE_API_KEY(sensitive, optional) reaching hooks asCLAUDE_PLUGIN_OPTION_TYPESAFE_API_KEY;TYPESAFE_API_KEYenv as fallback.uncalibrated; now compared against the version of the base rulebook that declares the semantic rules.--plugin-dirgets no automatic install), Onboarding another project.calibration/README.md: live spike checklist for the SubagentStop gate.295 tests offline,
tsc --noEmitclean, examples pass--strict,run.sh --hook subagent-stopwithout a rulebook is silent with exit 0.Pending spike (coordinator)
Verify in a live Claude Code session:
create-subdomainon a dummy project with.claude/rulebook.yaml; make the domain agent write@Injectableintodomain/; observe the PreToolUse deny and the SubagentStop block; confirmagent_idvstool_response.agentIdequivalence for theAgentPostToolUse hook (subagents run in the background by default since v2.1.198).