feat(h4-hardening): Plan-07 Track A — A1 strict semantic, A2 unicode/encoding, A3 tool-output scan

A1 (V1): CASAN_SECURITY_STRICT=1 makes semantic classification REQUIRED and
  fail-closed — model unavailable/no-verdict → BLOCK, never a silent SKIP.
  Non-strict CASAN_SEMANTIC_CLASSIFY=1 keeps regex verdict but logs
  SEMANTIC_SKIPPED loudly (sourced casan-log.sh). Default (no flags) unchanged.
A2 (V3/V4): unicode-normalize.py (NFKC + zero-width strip + Cyrillic/Greek
  homoglyph fold) and decode-suspicious.py (base64/hex decode + rescan, printable
  filter to avoid false positives) feed new match_either/secret_match haystacks.
  Blocks homoglyph, zero-width, fullwidth, base64/hex-smuggled injection & secrets.
A3 (V7): tool-output-scan.sh scans tool output for injection/secret before it
  re-enters model context; wrapper runs it after H6-exec (mode off|warn|block,
  strict→block). warn is default to preserve benign-draft behaviour.

Baseline preserved: run-casan4 35/35, adversarial 44/44.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
thanhnv
2026-07-03 22:20:50 +09:00
co-authored by Claude Opus 4.8
parent fbcef967e5
commit ac40c0b281
5 changed files with 283 additions and 24 deletions
@@ -115,6 +115,32 @@ else
run_phase "H6-exec" "$SCRIPT_DIR/agent-metrics.sh" "$APPROVED_INPUT" "$RAW_OUTPUT"
fi
# V7: tool output can carry indirect injection that would re-enter a downstream
# model's context. Scan RAW_OUTPUT for injection/secret patterns before it is
# reused. Mode: off | warn (default) | block. Strict mode upgrades to block.
# warn keeps existing behaviour (logged, non-blocking) so benign drafts are not
# broken; block enforces (fail-closed) for production/strict runs.
TOOL_OUTPUT_SCAN_MODE="${CASAN_TOOL_OUTPUT_SCAN:-}"
if [[ -z "$TOOL_OUTPUT_SCAN_MODE" ]]; then
if [[ "${CASAN_SECURITY_STRICT:-0}" == "1" ]]; then TOOL_OUTPUT_SCAN_MODE="block"; else TOOL_OUTPUT_SCAN_MODE="warn"; fi
fi
if [[ "$TOOL_OUTPUT_SCAN_MODE" != "off" ]]; then
TOS_RC=0
"$SCRIPT_DIR/tool-output-scan.sh" "$RAW_OUTPUT" "$ACTION_NAME" >/dev/null 2>&1 || TOS_RC=$?
record_phase "H4-tool-output" "$TOS_RC"
if [[ "$TOS_RC" -eq 2 ]]; then
if [[ "$TOOL_OUTPUT_SCAN_MODE" == "block" ]]; then
casan_log error harness "TOOL_OUTPUT_INJECTION_BLOCKED action=$ACTION_NAME"
: > "$FINAL_OUTPUT"
write_phase_report
echo "TOOL_OUTPUT_INJECTION_BLOCKED action=$ACTION_NAME" >&2
exit 2
else
casan_log warn harness "TOOL_OUTPUT_INJECTION_SUSPECTED action=$ACTION_NAME mode=warn hint=set_CASAN_TOOL_OUTPUT_SCAN=block_or_CASAN_SECURITY_STRICT=1_to_enforce"
fi
fi
fi
run_phase "H4-out" "$SCRIPT_DIR/security-check.sh" "$RAW_OUTPUT" "$FINAL_OUTPUT" output
if [[ "$CACHE_STATUS" == "stored" ]]; then