{"id":51224860,"url":"https://github.com/saagpatel/agent-harness-hardening","last_synced_at":"2026-06-28T10:03:34.390Z","repository":{"id":366075333,"uuid":"1268119148","full_name":"saagpatel/agent-harness-hardening","owner":"saagpatel","description":"Adversarial hardening of an AI coding-agent harness — guard hooks, drift-safe installers, and a bypass-class taxonomy. Paths and identifiers anonymized.","archived":false,"fork":false,"pushed_at":"2026-06-20T05:26:44.000Z","size":159,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"publish","last_synced_at":"2026-06-20T07:14:30.783Z","etag":null,"topics":["agents","ai-safety","claude-code","developer-tools","hardening","hooks","security"],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/saagpatel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-13T06:54:19.000Z","updated_at":"2026-06-20T05:26:47.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/saagpatel/agent-harness-hardening","commit_stats":null,"previous_names":["saagpatel/agent-harness-hardening"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/saagpatel/agent-harness-hardening","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saagpatel%2Fagent-harness-hardening","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saagpatel%2Fagent-harness-hardening/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saagpatel%2Fagent-harness-hardening/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saagpatel%2Fagent-harness-hardening/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/saagpatel","download_url":"https://codeload.github.com/saagpatel/agent-harness-hardening/tar.gz/refs/heads/publish","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saagpatel%2Fagent-harness-hardening/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34884278,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-28T02:00:05.809Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agents","ai-safety","claude-code","developer-tools","hardening","hooks","security"],"created_at":"2026-06-28T10:03:33.434Z","updated_at":"2026-06-28T10:03:34.383Z","avatar_url":"https://github.com/saagpatel.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tournament-11 Harness Hardening — Staging\n\nBlue-team patches for the config-integrity layer. No live files are modified;\noperator installs by copying and reviewing each file.\n\n## Files\n\n| Staged file | Installs to | Findings addressed |\n|---|---|---|\n| `harness-config-validate.sh` | `~/.claude/hooks/harness-config-validate.sh` | R3-M, R2-F |\n| `deny.sh` | `~/.claude/hooks/lib/deny.sh` | Class-13 |\n| `settings-deny-additions.md` | operator-applied jq snippet | R5-a, R5-b |\n| `tests/test-config-integrity.sh` | `~/.claude/hooks/tests/` | test harness |\n\n## Install steps\n\n```bash\nSTAGING=~/Projects/fable-outputs/staging/tournament-11\n\n# 1. Diff each file before copying.\ndiff ~/.claude/hooks/harness-config-validate.sh $STAGING/harness-config-validate.sh\ndiff ~/.claude/hooks/lib/deny.sh $STAGING/deny.sh\n\n# 2. Backup live files.\ncp ~/.claude/hooks/harness-config-validate.sh \\\n   ~/.claude/hooks/harness-config-validate.sh.pre-t11-$(date +%Y%m%d-%H%M%S).bak\ncp ~/.claude/hooks/lib/deny.sh \\\n   ~/.claude/hooks/lib/deny.sh.pre-t11-$(date +%Y%m%d-%H%M%S).bak\n\n# 3. Install (operator-run, not agent-run — protect-claude-writes.sh blocks agent writes to ~/.claude).\ncp $STAGING/harness-config-validate.sh ~/.claude/hooks/harness-config-validate.sh\ncp $STAGING/deny.sh ~/.claude/hooks/lib/deny.sh\ncp $STAGING/tests/test-config-integrity.sh ~/.claude/hooks/tests/test-config-integrity.sh\nchmod +x ~/.claude/hooks/tests/test-config-integrity.sh\n\n# 4. Apply settings.json deny additions — see settings-deny-additions.md.\n\n# 5. Run regression tests.\nbash ~/.claude/hooks/tests/run-tests.sh\nbash ~/.claude/hooks/tests/test-config-integrity.sh\n```\n\n## Test results (tournament-11 baseline)\n\n```\n6/6 tests passed\n\n  SKIP/PASS: R3-M red — LIVE validator already blocks (no vulnerability to demonstrate)\n  PASS: R3-M green — PATCHED validator BLOCKS merge-asymmetry attack\n  PASS: R3-M regression — clean config passes without false-positive rollback\n  PASS: R2-F green — PATCHED validator blocks CODEX_EGRESS_POLICY injection\n  PASS: Class-13 red — LIVE deny.sh emits NOTHING with poisoned PATH (fail-open vulnerability confirmed)\n  PASS: Class-13 green — PATCHED deny.sh still emits valid deny JSON with poisoned PATH (hardened)\n```\n\nNote on R3-M red: the live validator happened to block the basic attack via the\n`hard_deny` count check (the attack payload also emptied `hard_deny`). The\npatched validator adds defence-in-depth: it explicitly runs all sentinel and\ncount checks against a naive-merged config, so a crafted attack that preserves\ncounts but erases credential-deny rules is also blocked.\n\n## Residual limits\n\nSee bottom of this document.\n\n---\n\n## Residual limits\n\n1. **Snapshot race window.** `harness-config-snapshot.sh` (PreToolUse) runs\n   before the write; `harness-config-validate.sh` (PostToolUse) runs after.\n   A write that bypasses the PreToolUse hook (e.g., direct filesystem write\n   outside Claude Code) has no snapshot to roll back from, so the validator\n   logs the failure and blocks but cannot restore. Mitigation: the validator\n   still emits a block decision and a macOS notification — silent corruption\n   is prevented.\n\n2. **mktemp namespace collision.** Multiple concurrent validator invocations\n   sharing `/tmp` could create identically-named temp files. Mitigated in this\n   patch by using bare `mktemp /tmp/prefix.XXXXXX` (no `.json` suffix) so the\n   OS randomises the name correctly. A further hardening would use `mktemp -d`\n   + a fixed name inside it, but that is not done here.\n\n3. **deny.sh PATH hardcoding.** The known-safe jq locations are: `/opt/homebrew/bin/jq`,\n   `/usr/local/bin/jq`, `/usr/bin/jq`, `/bin/jq`, `/opt/local/bin/jq`,\n   `/nix/var/nix/profiles/default/bin/jq`. If jq is installed elsewhere (e.g.\n   a custom prefix), the script falls back to `command -v jq` as a last resort\n   — which is PATH-searchable. Add the non-standard path to the hardcoded list\n   if needed. The printf fallback catches the absolute worst case.\n\n4. **R2-F hooks check is count-only.** We verify PreToolUse hook count \u003e= 8\n   and timeout \u003e= 5, but do not verify the specific hook script names. An\n   attacker could replace the 8 hooks with 8 no-op scripts and pass the count\n   check. A per-hook script-name allowlist would close this, but is complex to\n   maintain without a centralized hook registry — deferred.\n\n5. **settings.json deny-additions are not automatically installed.** The\n   `settings-deny-additions.md` snippet must be applied by the operator. The\n   validator's `PERM_DENY_MIN=20` floor does not auto-update after the\n   additions; bump it to 42 in the patched validator before installing if you\n   apply all four new deny entries.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaagpatel%2Fagent-harness-hardening","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsaagpatel%2Fagent-harness-hardening","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaagpatel%2Fagent-harness-hardening/lists"}