feat(rtk): drop auto-allow — permission control returns to settings.json

The exit-0 branch emitted permissionDecision:allow, making rtk's internal
Rust registry a PARALLEL permission authority: a rewritten command
bypassed settings.json deny/ask entirely (audit #11). Both rewrite paths
now emit updatedInput only; the rewritten command goes through native
evaluation. Companion allow rules for read-only 'rtk <tool>' forms land
in settings.json (audit-hardening branch) to keep the safe majority
frictionless. Re-pinned.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016zA3Qh2Q1QpcGXzXxKeDHR
This commit is contained in:
Bastien Chanot
2026-07-02 14:28:31 +02:00
co-authored by Claude Fable 5
parent ca8df16885
commit 731ed95c98
2 changed files with 20 additions and 27 deletions
+1 -1
View File
@@ -1 +1 @@
0f43229d17d03342d27c0b836b9b70f25f98dfb80a35ffc8dc2488034cb8719c rtk-rewrite.sh 871efa28daf7c06a9c9039a2875407e2536646f5d82f7e7a9c6a80dd3742929c rtk-rewrite.sh
+19 -26
View File
@@ -12,7 +12,12 @@
# ANY edit here must re-pin: (cd hooks && sha256sum rtk-rewrite.sh > .rtk-hook.sha256) # ANY edit here must re-pin: (cd hooks && sha256sum rtk-rewrite.sh > .rtk-hook.sha256)
# #
# Exit code protocol for `rtk rewrite`: # Exit code protocol for `rtk rewrite`:
# 0 + stdout Rewrite found, no deny/ask rule matched → auto-allow # 0 + stdout Rewrite found, no rtk deny/ask rule matched → rewrite. NO
# permissionDecision is emitted (auto-allow dropped 2026-07-02:
# it made rtk's registry a parallel permission authority that
# bypassed settings.json deny/ask). The REWRITTEN command goes
# through native evaluation; explicit `rtk <tool>` allow rules
# in settings.json keep read-only forms frictionless.
# 1 No RTK equivalent → pass through unchanged # 1 No RTK equivalent → pass through unchanged
# 2 Deny rule matched → pass through (Claude Code native deny handles it) # 2 Deny rule matched → pass through (Claude Code native deny handles it)
# 3 + stdout Ask rule matched → rewrite but let Claude Code prompt the user # 3 + stdout Ask rule matched → rewrite but let Claude Code prompt the user
@@ -66,8 +71,8 @@ EXIT_CODE=$?
case $EXIT_CODE in case $EXIT_CODE in
0) 0)
# Rewrite found, no permission rules matched — safe to auto-allow. # Rewrite found. If the output is identical, the command was
# If the output is identical, the command was already using RTK. # already using RTK — nothing to do.
[ "$CMD" = "$REWRITTEN" ] && exit 0 [ "$CMD" = "$REWRITTEN" ] && exit 0
;; ;;
1) 1)
@@ -106,26 +111,14 @@ fi
ORIGINAL_INPUT=$(echo "$INPUT" | jq -c '.tool_input') ORIGINAL_INPUT=$(echo "$INPUT" | jq -c '.tool_input')
UPDATED_INPUT=$(echo "$ORIGINAL_INPUT" | jq --arg cmd "$REWRITTEN" '.command = $cmd') UPDATED_INPUT=$(echo "$ORIGINAL_INPUT" | jq --arg cmd "$REWRITTEN" '.command = $cmd')
if [ "$EXIT_CODE" -eq 3 ]; then # Rewrite WITHOUT a permissionDecision (exit 0 and exit 3 alike): the
# Ask: rewrite the command, omit permissionDecision so Claude Code prompts. # rewritten command goes through Claude Code's native allow/deny/ask
jq -n \ # evaluation. Permission control lives in settings.json, not in rtk.
--argjson updated "$UPDATED_INPUT" \ jq -n \
'{ --argjson updated "$UPDATED_INPUT" \
"hookSpecificOutput": { '{
"hookEventName": "PreToolUse", "hookSpecificOutput": {
"updatedInput": $updated "hookEventName": "PreToolUse",
} "updatedInput": $updated
}' }
else }'
# Allow: rewrite the command and auto-allow.
jq -n \
--argjson updated "$UPDATED_INPUT" \
'{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow",
"permissionDecisionReason": "RTK auto-rewrite",
"updatedInput": $updated
}
}'
fi