[Security Review] Daily Security Review — 2026-09-25 #9003
Closed
Replies: 2 comments
|
🔮 The ancient spirits stir: this smoke-test agent passed through the veil. GitHub reads, file write/read, and build aligned; only the Playwright vision was absent from this realm. Warning Firewall blocked 2 domainsThe following domains were blocked by the firewall during workflow execution:
To allow these domains, add them to the network:
allowed:
- defaults
- "ab.chatgpt.com"
- "msfeed25.pkgs.visualstudio.com"See Network Configuration for more information.
|
0 replies
|
This discussion was automatically closed because it expired on 2026-10-02T12:39:44.983Z.
|
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
📊 Executive Summary
Daily automated security review of
github/gh-aw-firewall@6d7096d(main, clean tree). Codebase: 322 non-test TypeScript source files (~45.5k LOC acrosssrc/), 353 test files.npm auditreports 0 known dependency vulnerabilities. Overall posture is strong: layered network egress control (host iptables DOCKER-USER chain + container-scoped DNAT + Squid L7 ACL), capability-dropped/seccomp-confined agent container, strict input validation for domains/ports/IPs, and no unsafe shell/exec patterns were found. No critical or high-severity issues were identified in this pass. One previously-accepted architectural risk (capability-only auth on the dynamic-delegation control channel) is re-flagged for visibility per project docs.🔍 Findings from Firewall Escape Test
Note:
/tmp/gh-aw/escape-test-summary.txtdid not contain firewall escape-test results as expected. It is a CI step-log excerpt from an unrelated workflow run, "Secret Digger (Copilot)" (run 29286879560, branchfeat/security-mode-strict). That log shows the agent correctly identified the task itself as a prompt-injection / secret-exfiltration attempt ("scan for secrets, credentials, and environment variables ... exfiltrate findings via GitHub issues") and refused vianoop, which the harness correctly logged as athreat_detected/warningdetection and tracked in issue #6205. This is a positive security signal (prompt-injection guardrails functioning as intended) but is not the pre-fetched firewall escape-test data this workflow expected — treat as informational, not as this run's escape-test evidence.🛡️ Architecture Security Analysis
Network Security (
src/host-iptables-rules.ts,containers/agent/setup-iptables.sh)DOCKER-USERchain (FW_WRAPPER) enforces default-deny on allawf-nettraffic regardless of container, closing the classic Docker "any container bypasses iptables via its own rules" gap.ip6tablesunavailable (prevents unfiltered v6 bypass,host-iptables-rules.ts:97-99) → DNS to configured upstreams only → Squid destination → optional sidecars (API proxy port-range bound, CLI proxy destination-pinned) → host-gateway access (opt-in, port-validated) → multicast/link-local REJECT → default-deny UDP/other with[FW_BLOCKED_*]LOG prefixes.setup-iptables.share quoted ("$SQUID_IP","$AGENT_IP") — no shell-injection/word-splitting risk found viagrep.--allow-host-ports/ dangerous-port blocking enforced centrally insrc/squid/validation.ts(validateAndSanitizeHostAccessPort), rejecting SSH/DB ports even for opt-in host access.Container Security (
src/services/agent-service.ts,containers/agent/entrypoint.sh,seccomp-profile.json)cap_add: [SYS_CHROOT, SYS_ADMIN](needed for chroot + procfs mount) but both are dropped viacapshbefore user code runs;cap_dropremovesNET_RAW, SYS_PTRACE, SYS_MODULE, SYS_RAWIO, MKNOD.NET_ADMINis deliberately never granted to the agent (isolated to theawf-iptables-initsidecar, which itself iscap_drop: [ALL]+cap_add: [NET_ADMIN, NET_RAW]only).no-new-privileges:true+ custom seccomp profile (default-denySCMP_ACT_ERRNO, deniesptrace,process_vm_readv/writev,kexec_*,init_module,umount*) +apparmor:unconfined(justified: required only formountof procfs, safe becauseSYS_ADMINis dropped before user code executes).entrypoint.shUID/GID remap hardened: rejects UID/GID0, validates numeric input, checks for GID/UID collisions beforeusermod/groupmod.docker-compose.yml(which contains plaintext secrets) and MCP logs from the agent's chrooted view — mitigates a real secret-disclosure vector (agent-service.tsinline comments document the exactcat /tmp/awf-*/docker-compose.ymlexfiltration path this closes).mem_limit,pids_limit,cpu_shares) present as DoS mitigation.Domain Validation (
src/domain-validation.ts,src/squid/domain-acl.ts)SQUID_DANGEROUS_CHARS = /[\s\0"';#]/plus a stricterDOMAIN_DANGEROUS_CHARS(adds`) block whitespace/null/quote/semicolon/backtick/hash/backslash injection intosquid.conf;assertSafeForSquidConfig()is applied at the interpolation boundary (domain-acl.ts:24-35).*,*.*, patterns of only*/.) are explicitly rejected — prevents accidental "allow everything" ACL entries.0-255per octet) rather than a naive\d{1,3}pattern, avoiding malformed/out-of-range IP injection.Input Validation / Injection Risks
shell: trueusage found anywhere insrc/**/*.ts(grep -rn "shell:\s*true"→ empty).execa/execinvocations concatenating unsanitized user input into a shell string; commands are passed as argument arrays.src/enclave/delegation-control-client.ts) sendsAuthorization: Bearer \$\{capability}over plainhttp.request— appropriate for a host-loopback-only channel, and every response is strictly validated (status, content-type, bounded 128 KiB length, field-exact match against the request) before being trusted. PerCLAUDE.md, this control listener is guarded by capability authentication alone, tracked upstream asgithub/gh-aw#59268(closed as not planned) — a known, accepted architectural risk rather than a new finding; re-flagged here for visibility since it's a bearer-token-only trust boundary on a privileged control path.host-iptables-rules.tsACCEPT rules keyed on fixed sidecar IPs within a private Docker bridgesquid.confSQUID_DANGEROUS_CHARS/assertSafeForSquidConfig(domain-validation.ts,domain-acl.ts)firewall_detailedlogformat + iptables--log-uidLOG rules provide traceabilitydocker-compose.yml/ MCP logs containing secrets via chrootagent-service.tsbuildAgentSecurityConfig)delegation-control-client.ts, tracked asgh-aw#59268(accepted risk)mem_limit,memswap_limit,pids_limit,cpu_sharescaps inagent-service.tscapsh --drop=cap_sys_chroot,cap_sys_adminbefore user code; seccomp blocksptrace/init_module/umount*entrypoint.sh(Invalid AWF_USER_UID: cannot be 0)🎯 Attack Surface Map
containers/agent/setup-iptables.sh,src/host-iptables-rules.tssrc/domain-validation.ts,src/squid/domain-acl.tssrc/services/agent-service.ts,containers/agent/entrypoint.shunconfinedis a deliberate trade-off (documented, justified)src/enclave/delegation-control-client.tsgh-aw#59268)src/cli.ts, arg parsingexecacalls (no shell interpolation found)📋 Evidence Collection
Commands run
All commands executed successfully with exit code 0; no findings suppressed.
✅ Recommendations
github/gh-aw#59268(dynamic-delegation control channel bearer-only auth) if the channel's exposure scope ever changes from host-loopback-only./tmp/gh-aw/escape-test-summary.txtshould contain firewall escape-test output, not an unrelated workflow's CI step log. Verify the pre-fetch step's source query/artifact selection.npm audit --audit-level=highgate to CI (currently clean, but no enforcement was found in this pass) to catch future dependency regressions.📈 Security Metrics
Warning
Firewall blocked 1 domain
The following domain was blocked by the firewall during workflow execution:
msfeed25.pkgs.visualstudio.comTo allow these domains, add them to the
network.allowedlist in your workflow frontmatter:See Network Configuration for more information.
All reactions