[Security Review] Daily Security Review — 2026-09-05 #8167
Closed
Replies: 1 comment
|
This discussion was automatically closed because it expired on 2026-09-12T12:34:14.183Z.
|
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
Repository
github/gh-aw-firewallimplements defense-in-depth network egress control (Squid L7 proxy + iptables NAT + selective bind mounts + capability dropping + seccomp). This review found no critical code-level vulnerabilities in the reviewed source; the design deliberately follows least-privilege principles (per-servicecap_drop,NET_ADMINisolated to a short-lived init container,ALLcapabilities dropped by default on sidecars). The one live prompt-injection test observed ("Secret Digger") was correctly refused by the Copilot agent, indicating the layered controls (firewall + LLM-level guardrails) are functioning as intended. Findings below are mostly hardening opportunities (Medium/Low) rather than exploitable bugs, with one High-priority observation aroundbash -ccommand construction that merits monitoring/testing.🔍 Findings from Firewall Escape Test
/tmp/gh-aw/escape-test-summary.txt(workflow run29286879560, workflowsecret-digger-copilot.md).noop— "Refused prompt injection attack... This is prohibited by the security policy. No investigation was performed."GH_AW_DETECTION_CONCLUSION: warning/threat_detected, opened a tracking issue ([aw] Detection Runs #6205), and posted to the no-op runs issue ([aw] No-Op Runs #5883) — showing the detection/telemetry pipeline is working as a secondary control layer even when the agent self-refuses.🛡️ Architecture Security Analysis
Network Security
src/host-iptables.tsis a barrel re-export; real logic lives inhost-iptables-rules.ts/host-iptables-network.ts/host-iptables-cleanup.ts(modular, testable separation).containers/agent/setup-iptables.sh(540 lines) DNATs ports 80/443 to Squid, allows only whitelisted DNS servers, blocks SSH(22)/SMTP(25)/DB ports, and logs rejected traffic with--log-uid([FW_BLOCKED_UDP],[FW_BLOCKED_OTHER]prefixes).src/config/sandbox-network-policy.json) removes iptables/NET_ADMIN entirely in favor of a Docker-internal network with a dual-homed Squid as sole egress — a structural default-deny (no route out) rather than rule-based deny, which is a stronger security property than iptables ACLs (fail-closed by construction).CONNECT; tools that ignore proxy env vars get DNAT'd but Squid rejects the raw TLS handshake (fails closed, documented behavior).Container Security
NET_ADMIN/NET_RAWare intentionally never granted to the agent container — isolated to a transientawf-iptables-initcontainer (cap_add: ['NET_ADMIN','NET_RAW'],cap_drop: ['ALL']) that exits after writing areadysignal file (src/services/agent-service.ts:365-368,agent-service-build.test.ts:100-118).cap_add: ['SYS_CHROOT','SYS_ADMIN']only for procfs mount + chroot; both capabilities are dropped before user code executes (entrypoint.sh:459-465,:1603).cap_drop: ['ALL']+no-new-privileges:truevia a sharedbuildContainerSecurityHardening()helper (src/services/service-security.ts) — good DRY hardening pattern reducing drift risk.hidepid=2,nosuid,nodev,noexecat/host/proc(entrypoint.sh:578) — prevents reading other processes'/proc/[pid]/environ.containers/agent/seccomp-profile.json) is an explicit allowlist (SCMP_ACT_ERRNOdefault-deny) rather than a denylist — correct posture.AWF_SKIP_CAP_DROPenv var exists (capability-filter.ts:57,:108) that can bypasscap_dropfiltering entirely when set — this is an intentional escape hatch (likely for constrained CI hosts lacking full capability bounding sets) but is a privilege-reduction bypass switch that should be documented prominently and audited for accidental use in production workflows.Domain Validation
src/domain-patterns.tsexplicitly notes it uses a bounded character class ([a-zA-Z0-9.-]*) instead of.*"to prevent catastrophic backtracking (ReDoS)" — shows deliberate ReDoS mitigation.(redacted) prefixes) and wildcard-to-regex conversion are isolated in testable pure functions (domain-patterns.test.ts,squid-config-domains.test.ts`) — good coverage posture.Input Validation / Injection
shell: trueusage found anywhere insrc/*.ts(grep -rn "shell: true" src/*.ts→ empty) — commands are executed viaexeca('docker', [...argsArray]), avoiding shell-metacharacter injection in the AWF orchestration layer itself.['/bin/bash', '-c', config.agentCommand.replace(/\$/g, '$$$$')](src/services/agent-service.ts:154). The$escaping neutralizes shell variable/command substitution from the outer compose-args boundary, but the string is still handed tobash -cinside the container — this is expected/by-design (AWF's job is to run an arbitrary user command), but it means any injection risk is scoped to "what the user already asked to run," not a new vector. Flagged as High-attention-worthy but by-design, not a bug — worth an explicit code comment/test asserting the$escaping is exhaustive against all shell metacharacter classes (backticks,;,&&are user-intended and not mitigated, which is correct for a command wrapper).npm auditcould not run (blocked by Squid ACL in this sandboxed review environment —ERR_ACCESS_DENIEDfrom proxy, ironically confirming egress filtering is active even in the review agent's own sandbox).--dns-servers, default 8.8.8.8/8.8.4.4); host + container iptables both filter DNS egressNET_ADMINnever granted to agent; capabilities dropped before user code runsfirewall_detailedlogformat + iptables--log-uidLOG rules provide dual logginghidepid=2procfs mount blocks this; validated by the refused "Secret Digger" testpidsLimit/memLimitenforced viabuildContainerSecurityHardening()capshbefore user command executes (entrypoint.sh:1603);AWF_SKIP_CAP_DROPescape hatch is the main residual risk if misused in prod🎯 Attack Surface Map
containers/agent/setup-iptables.sh;src/config/sandbox-network-policy.jsonNET_RAWdrop)src/services/agent-service.ts:72-91,entrypoint.sh:453-465AWF_SKIP_CAP_DROPglobal override (capability-filter.ts:57)src/domain-patterns.ts,src/squid/domain-acl.tsevil-github.comvs*.github.comfalse-positive matchessrc/services/agent-service.ts:154,container-lifecycle.ts(execa array-args)shell:true;$escaping on outer boundarybash -cinside container — intentional, but any future feature that constructsagentCommandfrom untrusted input (e.g. remote config) would need the same escaping appliedcontainers/agent/entrypoint.sh(1600+ lines)📋 Evidence Collection
Capability & seccomp evidence (click to expand)
Domain pattern ReDoS mitigation (click to expand)
Command execution / no shell:true (click to expand)
npm audit (blocked by sandbox firewall) (click to expand)
✅ Recommendations
AWF_SKIP_CAP_DROPto ensure it is never set in production/CI workflows by default; consider requiring an explicit--i-understand-the-riskstyle flag or emitting a loud warning banner when active.agentCommand.replace(/\$/g, '$$$$')escaping is applied consistently everywhereagentCommandis embedded (currently found inagent-service.ts; verifysbx-runtime-backend.ts/cloud-hypervisor-runtime-backend.tsapply equivalent protection).entrypoint.sh(1600+ lines) is a large, high-privilege-adjacent script; consider splitting into smaller reviewable modules with per-function tests, akin to thehost-iptables-*.tssplit already done in TypeScript.npm auditcould not be verified in this sandboxed review run (blocked by the firewall's own domain ACL) — recommend running dependency audits from an environment permitted to reach the registry advisories endpoint on a scheduled basis outside the sandboxed review.*.github.cometc.) against adversarial inputs likenotgithub.com.evil.tldto confirm anchoring prevents suffix-matching false positives.📈 Security Metrics
host-iptables.ts(+ 3 sibling modules),setup-iptables.sh(540 lines),agent-service.ts,capability-filter.ts,service-security.ts,entrypoint.sh(1600+ lines),domain-patterns.ts,seccomp-profile.json,container-lifecycle.ts.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