feat(phai): gate PostHog MCP exec writes behind approval on Codex#115
Open
skoob13 wants to merge 1 commit into
Open
feat(phai): gate PostHog MCP exec writes behind approval on Codex#115skoob13 wants to merge 1 commit into
skoob13 wants to merge 1 commit into
Conversation
The PostHog MCP exposes a single `exec` umbrella tool. Once a user allow-lists it on Codex, every dispatched write (experiment-update, notebooks-destroy, …) runs without a prompt — the Claude Code write-gate deliberately skips Codex because its PreToolUse protocol rejects `permissionDecision: "ask"`. Enforce writes-only approval on Codex via two pieces, since Codex's PermissionRequest hook can only allow/deny/defer (there is no "ask"): - put the posthog server in `prompt` approval mode in .mcp.json, so every exec call reaches the approval flow by default; - add a PermissionRequest hook (hooks/codex-gate-exec-write.sh, registered via .codex-plugin/plugin.json) that returns `allow` for reads/meta verbs and allow-listed writes (suppressing the prompt) and defers writes so the prompt fires only on them. Extract the shared write-verb regex and exec-payload parsing into hooks/lib-exec-gate.sh, now sourced by both the Claude and Codex gates so the write surface can't drift. Claude Code behavior is unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <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
The PostHog MCP exposes a single
execumbrella tool. Once a user allow-lists it on Codex, every dispatched write (experiment-update,notebooks-destroy,cdp-functions-delete, …) runs without a prompt. The existing Claude Code write-gate (hooks/gate-exec-write.sh) deliberately skips Codex because Codex'sPreToolUseprotocol rejectspermissionDecision: "ask", so on Codex there was no plugin-level write gate at all.Changes
Enforce writes-only approval on Codex, mirroring the Claude Code behavior. Codex's
PermissionRequesthook can onlyallow/deny/defer (there is no "ask" verdict), so two pieces are needed:.mcp.json— put theposthogserver inpromptapproval mode (default_tools_approval_mode), so everyexeccall reaches the approval flow by default.hooks/codex-gate-exec-write.sh(new) +hooks/codex-hooks.json(new), registered via.codex-plugin/plugin.json— aPermissionRequesthook that returnsallowfor reads / meta verbs / allow-listed writes (suppressing the prompt) and defers writes so the prompt fires only on them.hooks/lib-exec-gate.sh(new) — extracts the write-verb regex and exec-payload parsing into one sourced helper, now used by both the Claude and Codex gates so the write surface can't drift. Claude Code behavior is unchanged./hookstrust step on Codex and thePOSTHOG_MCP_EXEC_GATE_ALLOWopt-out (works on both clients).Note: a freshly installed plugin hook is untrusted on Codex and does not run until the user trusts it via
/hooks(Codex prints a startup warning). The plugin setspromptas a default; a user can still override it in their own config.How did you test this code?
PermissionRequest/PreToolUsepayloads through the scripts:allowfor meta verbs, readcalls, non-exec tools, and allow-listed writes; no decision (defer → prompt) for writecalls, allowlist mismatches, and unparseablecalls.askonly for non-allow-listed writes (incl. plugin-prefixedmcp__posthog_posthog__exec), silent otherwise, and still skips on Codex (PLUGIN_ROOTset).jqvalidation on all touched JSON;bash -non all scripts.posthogMCP server with the new.mcp.jsonkey, and that on Codex a read runs silently while a write prompts after trusting the hook.Publish to changelog?
no