#!/usr/bin/env python3 """Probe: log the SHAPE of tool_response (keys, types, string lengths — never values); if SCRUB=1, replace every canary (files named in CANARIES, colon-separated) in every string, recursively, and return updatedToolOutput.""" import json, os, sys, time ev = json.load(sys.stdin) vals = [open(p).read().rstrip("\n") for p in os.environ.get("CANARIES", "").split(":") if p] def shape(o): if isinstance(o, dict): return {k: shape(v) for k, v in o.items()} if isinstance(o, list): return [shape(v) for v in o[:3]] + (["...%d" % len(o)] if len(o) > 3 else []) if isinstance(o, str): return "str(%d)%s" % (len(o), "+CANARY" if any(v in o for v in vals) else "") return type(o).__name__ changed = [False] def scrub(o): if isinstance(o, dict): return {k: scrub(v) for k, v in o.items()} if isinstance(o, list): return [scrub(v) for v in o] if isinstance(o, str): n = o for v in vals: n = n.replace(v, "«CANARY»") if n != o: changed[0] = True return n return o new = scrub(ev["tool_response"]) with open(os.path.expanduser("~/cc-creds-build/ev/shape.log"), "a") as fh: fh.write("%s %s scrub=%s changed=%s shape=%s\n" % (time.strftime("%H:%M:%S"), ev["tool_name"], os.environ.get("SCRUB"), changed[0], json.dumps(shape(ev["tool_response"])))) if os.environ.get("SCRUB") == "1" and changed[0]: print(json.dumps({"hookSpecificOutput": {"hookEventName": "PostToolUse", "updatedToolOutput": new}}))