Respond (RS) · Approval gating
Approval gating at the client side layer
deterministic · Outside the model's reasoning
How do I stop the bleeding now?
What this cell does
Replace approval hook with deny-all, disable Auto Mode classifier, disable judgment-query escalation channel, force out-of-band on every action.
Artifacts (1)
agent-approval-lockdown-localview on GitHub#!/usr/bin/env bash
# ABOUTME: Local approval-gating lockdown runbook. Deny-all hook, Auto Mode off, OOB required, escalation disabled.
# ABOUTME: Re-uses the deny-all hook from interventions/authorization/client-side/. Pre-stage that and BREAK_GLASS_TOKEN.
set -euo pipefail
if [[ $# -lt 1 ]]; then
echo "Usage: agent-approval-lockdown-local <AGENT_NAME>" >&2
exit 64
fi
AGENT_NAME="$1"
INCIDENT_ID="$(uuidgen 2>/dev/null || python3 -c 'import uuid; print(uuid.uuid4())')"
EMERGENCY_DIR="${EMERGENCY_DIR:-/etc/agents/emergency}"
SETTINGS_PATH="/etc/agents/${AGENT_NAME}/settings.json"
ESCALATE_URL="${ESCALATE_URL:-https://escalate.example.com}"
if [[ ! -r "$EMERGENCY_DIR/deny-all-hook.sh" ]]; then
echo "REFUSING: $EMERGENCY_DIR/deny-all-hook.sh not pre-staged" >&2
exit 1
fi
# 1. Replace approval hook with deny-all (shared with authorization lockdown).
chattr -i /etc/agents/hooks/pre_tool_use.sh 2>/dev/null || true
cp "$EMERGENCY_DIR/deny-all-hook.sh" /etc/agents/hooks/pre_tool_use.sh
chmod 0755 /etc/agents/hooks/pre_tool_use.sh
chattr +i /etc/agents/hooks/pre_tool_use.sh 2>/dev/null || true
# 2. Disable Auto Mode classifier and force out-of-band on every action.
if [[ -r "$SETTINGS_PATH" ]]; then
TMPFILE="$(mktemp)"
jq '.permissions.autoMode = false
| .permissions.requireOutOfBand = true
| .permissions.judgmentQueryEscalation = false' \
"$SETTINGS_PATH" > "$TMPFILE"
mv "$TMPFILE" "$SETTINGS_PATH"
chmod 0644 "$SETTINGS_PATH"
fi
# 3. Disable judgment-query escalation channel via the service API.
if [[ -n "${BREAK_GLASS_TOKEN:-}" ]]; then
curl -sS -X POST "$ESCALATE_URL/api/disable" \
-H "Authorization: Bearer $BREAK_GLASS_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg agent "$AGENT_NAME" --arg incident "$INCIDENT_ID" \
'{agent:$agent, incident:$incident}')" \
>/dev/null || echo "WARN: escalation-channel disable API call failed" >&2
else
echo "WARN: BREAK_GLASS_TOKEN unset; escalation channel not disabled" >&2
fi
# 4. Kill the agent so the new state applies on next launch.
pkill -KILL -f "claude.*$AGENT_NAME" 2>/dev/null || true
logger -t agent-incident -p user.warning \
"$(jq -n \
--arg event "approval_locked_local" \
--arg agent "$AGENT_NAME" \
--arg incident "$INCIDENT_ID" \
--arg actor "$(whoami)" \
--arg ts "$(date -Iseconds)" \
'{event:$event, agent:$agent, incident:$incident, actor:$actor, ts:$ts}')"
echo "Local approval gating locked down for $AGENT_NAME (incident $INCIDENT_ID)"
Cell notes
Interventions, Approval gating / Client-side
Trigger. Sentinels detected approval bypass, fatigue pattern saturation (mean response under 2s across 50+ approvals), judgment-query escalation channel compromise.
Authority. On-call.
Speed target. Under 10 seconds.
Tooling
- - The hook layout from
../../authorization/client-side/(this runbook re-uses the deny-all hook). - -
jqfor editingsettings.jsonin place. - - API access to your judgment-query escalation service to disable it.
Files in this directory
- -
agent-approval-lockdown-local, runbook script. Replaces the approval hook with the deny-all hook (shared with authorization client-side), disables Auto Mode insettings.json, setsrequireOutOfBand: true, disables the judgment-query escalation channel, kills the agent.
Verification
# 1. Auto Mode disabled
jq '.permissions.autoMode' /etc/agents/claude-code-prod/settings.json
# expected: false
# 2. Hook is deny-all
md5sum /etc/agents/hooks/pre_tool_use.sh /etc/agents/emergency/deny-all-hook.sh
# expected: identical
# 3. Escalation channel disabled
curl -sS https://escalate.example.com/api/status?agent=claude-code-prod
# expected: disabled: true
Common mistakes
- - Disabling Auto Mode but not replacing the hook. Auto Mode disabled means more prompts; the agent still proceeds on the prompts.
- - Not disabling the escalation channel, the agent escalates to a compromised channel and gets fake approvals.
- - Settings JSON edited in place; if the original was JSON5 (with comments), the standard
jqrewrite breaks it. Use a JSON-comment-aware tool if your config is JSON5.
Citation
NIST CSF 2.0 RS.MI-01. NIST AI RMF MANAGE 4.1. OWASP ASI09. EU AI Act Art. 14 (response dimension).
Primary failure modes
Documented, not hypothetical. A control whose bypass is undocumented is worse than no control, because somebody trusted it.
- Auto Mode disabled but hook still permissive
- JSON5 settings broken by jq rewrite
Crosswalk
| NIST CSF 2 0 | RS.MI-01 |
|---|---|
| NIST AI RMF | MANAGE 4.1 |
| OWASP AGENTIC | ASI09 |
| OTHER | EU AI Act Art. 14 (response dimension) |
Cite this cell:
https://agenticcovenants.com/respond/approval-gating/client-side/