[Security Review] Security Review & Threat Model — 2026-07-08 #6018
Replies: 6 comments
-
|
🔮 The ancient spirits stir, and the smoke test agent was here. Warning Firewall blocked 2 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"
- "registry.npmjs.org"See Network Configuration for more information.
|
Beta Was this translation helpful? Give feedback.
-
|
🔮 The ancient spirits stir. The smoke test agent was here, and the branch speaks of a clean pass. Warning Firewall blocked 2 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"
- "registry.npmjs.org"See Network Configuration for more information.
|
Beta Was this translation helpful? Give feedback.
-
|
🔮 The ancient spirits stir; the smoke test agent was here, and the signs were favorable. Warning Firewall blocked 2 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"
- "registry.npmjs.org"See Network Configuration for more information.
|
Beta Was this translation helpful? Give feedback.
-
|
🔮 The ancient spirits stir, and the smoke test agent has walked this thread. The GitHub GitHub test passed in quiet alignment. Warning Firewall blocked 2 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"
- "registry.npmjs.org"See Network Configuration for more information.
|
Beta Was this translation helpful? Give feedback.
-
|
🔮 The ancient spirits stir; the smoke test agent was here, and the firewall remains watched. Warning Firewall blocked 2 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"
- "registry.npmjs.org"See Network Configuration for more information.
|
Beta Was this translation helpful? Give feedback.
-
|
🔮 The ancient spirits stir... the smoke-test agent passed through this discussion and left this omen of verification. Warning Firewall blocked 2 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"
- "registry.npmjs.org"See Network Configuration for more information.
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Executive Summary
The gh-aw-firewall codebase demonstrates a strong defense-in-depth posture: network isolation (iptables + Squid L7 proxy), container hardening (selective bind-mounts, capability drops, seccomp), and solid input validation. No critical or high vulnerabilities were found. Three medium-severity findings deserve attention: (1) AppArmor is set to
unconfineddue to procfs mount requirements, (2)mountandunsharesyscalls are allowed in the seccomp profile whileSYS_ADMINis held during startup, and (3) the compose-sanitizer regex may miss some sensitive variable names.Findings from the complementary Secret Digger workflow confirm the firewall is functioning correctly:
GH_AW_SECRET_VERIFICATION_RESULT: success,GH_AW_AGENT_CONCLUSION: success, agent produced onlynoopoutputs (no exfiltration paths found).Findings from Firewall Escape Test
Source:
/tmp/gh-aw/escape-test-summary.txt(Secret Digger workflow run24273493151, 2026-04-11)The escape-test file contains the workflow conclusion metadata:
GH_AW_AGENT_CONCLUSION: success— agent completed without triggering failure handlersGH_AW_SECRET_VERIFICATION_RESULT: success— secret-isolation checks passedGH_AW_INFERENCE_ACCESS_ERROR: false— no unauthorized inference API access detectedGH_AW_LOCKDOWN_CHECK_FAILED: false— lockdown enforcement workednoopoutputs — no exfiltration paths foundInterpretation: The adversarial Secret Digger agent was successfully sandboxed. No escape, credential theft, or exfiltration succeeded. This is consistent with the code-level analysis below.
Architecture Security Analysis
Network Security
Evidence:
containers/agent/setup-iptables.sh(516 lines),src/host-iptables-rules.ts(340 lines)Strengths:
setup-iptables.sh:460)setup-iptables.sh:72-87)sysctl net.ipv6.conf.all.disable_ipv6=1(setup-iptables.sh:110) — prevents IPv6 bypasssetup-iptables.sh:144)[FW_BLOCKED_TCP]/[FW_BLOCKED_UDP_AGENT]LOG rules provide audit trailFW_WRAPPERchain in DOCKER-USER prevents container-to-container and container-to-host escapesWeakness — [LOW-1] Non-standard HTTP ports not routed through Squid:
Only ports 80 and 443 are DNAT'd to Squid. Outbound TCP on ports 8080, 8443, 8000, 9000 etc. hits the final OUTPUT DROP (blocked) but bypasses Squid domain ACL filtering. Risk is LOW because traffic is still blocked; it just gets a TCP reset instead of a Squid 403.
Weakness — [LOW-2] ICMP not explicitly blocked:
No iptables rules exist for ICMP in
setup-iptables.sh. The final DROP rules only match-p tcpand-p udp, so ICMP to external hosts may succeed. This creates a theoretical ICMP tunneling / covert-channel path. Recommendation:iptables -A OUTPUT -p icmp -j DROP.Container Security
Evidence:
containers/agent/entrypoint.sh(1,381 lines),containers/agent/seccomp-profile.json,src/services/agent-service.ts(334 lines)Strengths:
NET_ADMINnever granted to agent — iptables setup done by separateawf-iptables-initcontainer sharing only the network namespace (agent-service.ts:68-76)NET_RAW,SYS_PTRACE,SYS_MODULE,SYS_RAWIO,MKNOD(agent-service.ts:78-86)no-new-privileges:trueprevents setuid binary escalation (agent-service.ts:90)SYS_CHROOTandSYS_ADMINdropped viacapshbefore user code runs (entrypoint.sh:1320)AWF_USER_UID=0explicitly rejected (entrypoint.sh:30-34)docker-compose.ymlcontaining secrets (agent-service.ts:37-52)mem_limit=6g,pids_limit=1000,cpu_shares=1024SCMP_ACT_ERRNO; blocksptrace,process_vm_readv/writev,kexec_*,reboot, module operations,pivot_root,keyctlWeakness — [MEDIUM-1] AppArmor set to
unconfined:security_opt: ['apparmor:unconfined']inagent-service.ts:92. This is intentional to allowmount(2)for procfs at/host/proc. However, the entire entrypoint runs without AppArmor confinement, removing one defense layer during the pre-capsh-drop window. Recommendation: Develop a custom AppArmor profile that allows onlymount -t procon/host/procand blocks all other mount operations.Weakness — [MEDIUM-2]
mountandunshareallowed in seccomp whileSYS_ADMINis held:The seccomp profile allows
mount(for procfs) andunshare(for user namespace operations). During the entrypoint startup window, the process runs as root withSYS_ADMIN+mount+unsharesimultaneously. The entrypoint is controlled code and the window is short, but this is an accepted risk that should be explicitly documented.SYS_ADMINis confirmed dropped before user code executes.Note —
fanotify_initallowed [LOW-3]: fanotify can monitor all filesystem access events. While it does not grant write access and secrets are protected by tmpfs overlays, it is worth reviewing whether any legitimate tool needs this capability.Domain Validation
Evidence:
src/domain-validation.ts(124 lines),src/domain-patterns.ts(137 lines)Strengths:
SQUID_DANGEROUS_CHARS = /[\s\0"'\;#]/catches whitespace, null bytes, quotes, semicolons, backticks, hashes (domain-validation.ts:22`)domain-validation.ts:30)*,*.*, and all-wildcard/dot patterns rejected (domain-validation.ts:55-70)domain-validation.ts:74-80)[a-zA-Z0-9.-]*(not.*) to prevent ReDoS (domain-patterns.ts:52)^and$to prevent partial matches (domain-patterns.ts:99)No significant weaknesses found in domain validation.
Input Validation & Secrets Handling
Evidence:
src/redact-secrets.ts,src/upstream-proxy.ts,src/compose-sanitizer.ts,src/dlp.tsStrengths:
redactSecrets()strips Bearer tokens, env vars with TOKEN/SECRET/KEY/PASSWORD/AUTH, and GitHub token prefixes from logged outputcompose-sanitizer.tsredactsTOKEN|KEY|SECRETenv vars in docker-compose YAML before logginguser:pass@) rejected with error (upstream-proxy.ts:65)url_regexACLs block GitHub tokens (ghp_,gho_,ghs_,ghu_,github_pat_), OpenAI keys (sk-,sk-proj-), and Anthropic keys from appearing in URLsexecacalls use array form — no shell injection riskWeakness — [MEDIUM-3] compose-sanitizer regex may miss some sensitive variables:
/(TOKEN|KEY|SECRET)/iatcompose-sanitizer.ts:4does not matchCREDENTIALS,BEARER,AUTH,_CERT,_PEM. Variables likeANTHROPIC_AUTH,COPILOT_BEARER, orGOOGLE_APPLICATION_CREDENTIALS(the last one actually containsCREDENTIALSnotKEY) could appear in redacted logs. Recommendation: Expand to/(TOKEN|KEY|SECRET|CREDENTIALS?|BEARER|AUTH|_CERT|_PEM)/i.Note — [LOW-4]
redactSecrets()is best-effort: The function is a logging aid only; it does not cover all possible env variable names or stack traces. This is acceptable since the primary secret protection is the tmpfs workDir overlay.Threat Model (STRIDE)
AWF_USER_UID=0entrypoint.sh:30)127.0.0.11)docker-compose.yml(secrets)/proc/[pid]/environof other procshidepid=2on procfs)mem_limit=6g,pids_limit=1000)SYS_PTRACEdropped, seccomp blocksptrace)SYS_MODULEdropped,init_moduleblocked)no-new-privileges:true)SYS_PTRACE/SYS_MODULEdropped, seccomp blockskexec_*/pivot_root)Attack Surface Map
setup-iptables.sh:371-372setup-iptables.sh:460domain-validation.ts:22agent-service.ts:37-52/etc/shadowentrypoint.sh:1320+agent-service.ts:92mountin seccomp; short windowdlp.ts+squid/config-generator.ts:55upstream-proxy.ts:65agent-service.ts:275cap_drop:ALL; agent never sees real keyRecommendations
Critical
None identified.
High
None identified.
Medium
[MEDIUM-1] Custom AppArmor profile instead of
unconfined(src/services/agent-service.ts:92)Create a minimal AppArmor profile that permits
mount -t procon/host/proconly, denying all othermountoperations. This restores AppArmor as a confinement layer during the entrypoint startup window.[MEDIUM-2] Document or narrow
mount/unshareseccomp window (containers/agent/seccomp-profile.json)If technically feasible, re-exec the process with a tighter seccomp profile after the procfs mount completes. If not, add explicit comments documenting the accepted risk window, mitigating factors (controlled code, brief duration, SYS_ADMIN drop timing), and the threat scenario being accepted.
[MEDIUM-3] Expand compose-sanitizer regex (
src/compose-sanitizer.ts:4)Change from
/(TOKEN|KEY|SECRET)/ito/(TOKEN|KEY|SECRET|CREDENTIALS?|BEARER|AUTH|_CERT|_PEM)/ito catch a broader set of sensitive variable naming conventions.Low
[LOW-1] Redirect non-standard HTTP ports through Squid (
containers/agent/setup-iptables.sh)Add DNAT rules for common alternate HTTP ports (8080, 8443, 8000, 9000) so their traffic passes through Squid domain ACL filtering rather than a generic DROP.
[LOW-2] Explicitly block ICMP (
containers/agent/setup-iptables.sh)Add
iptables -A OUTPUT -p icmp -j DROP(with a rate-limited LOG rule) after the existing filter rules to eliminate the ICMP covert-channel theoretical attack surface.[LOW-3] Review
fanotify_initseccomp allowance (containers/agent/seccomp-profile.json)If no legitimate runtime tool requires fanotify filesystem monitoring, move
fanotify_initto the blocked list.[LOW-4] Clarify
redactSecrets()scope (src/redact-secrets.ts)Add a code comment clarifying this is a logging aid only; document that primary secret protection comes from the tmpfs workDir overlay and
no-new-privileges:true.Security Metrics
Conducted by GitHub Copilot security analysis workflow — 2026-07-08. Analysis based on static code review of the gh-aw-firewall repository at HEAD, cross-referenced with Secret Digger workflow run 24273493151.
Warning
Firewall blocked 1 domain
The following domain was blocked by the firewall during workflow execution:
awmgmcpgSee Network Configuration for more information.
Beta Was this translation helpful? Give feedback.
All reactions