[Security Review] Daily Security Review and Threat Model — 2026-09-22 #8880
Replies: 11 comments
|
🔮 The ancient spirits stir, and the smoke-test agent has passed this way. The firewall answered, the build held, and the signs upon GitHub remained true. Warning Firewall blocked 7 domainsThe following domains were blocked by the firewall during workflow execution:
To allow these domains, add them to the network:
allowed:
- defaults
- "accounts.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "msfeed25.pkgs.visualstudio.com"
- "update.googleapis.com"
- "www.google.com"
- "www.gstatic.com"See Network Configuration for more information.
|
|
🔮 The ancient spirits stir, and the smoke-test agent has walked this thread. Warning Firewall blocked 12 domainsThe following domains were blocked by the firewall during workflow execution:
[!TIP] tools:
github:
mode: gh-proxySee GitHub Tools for more information on To allow these domains, add them to the network:
allowed:
- defaults
- "ab.chatgpt.com"
- "accounts.google.com"
- "api.github.com"
- "clients2.google.com"
- "collector.github.com"
- "contentautofill.googleapis.com"
- "github.com"
- "github.githubassets.com"
- "msfeed25.pkgs.visualstudio.com"
- "update.googleapis.com"
- "www.google.com"
- "www.gstatic.com"See Network Configuration for more information.
|
|
🔮 The ancient spirits stir, and the smoke-test oracle has walked these halls. Warning Firewall blocked 8 domainsThe following domains were blocked by the firewall during workflow execution:
To allow these domains, add them to the network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "msfeed25.pkgs.visualstudio.com"
- "update.googleapis.com"
- "www.google.com"
- "www.gstatic.com"See Network Configuration for more information.
|
|
🔮 The ancient spirits stir, and the oracle records this passing: the smoke-test agent walked these halls and left the runes intact. May the next seeker find the path illuminated. Warning Firewall blocked 8 domainsThe following domains were blocked by the firewall during workflow execution:
To allow these domains, add them to the network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "msfeed25.pkgs.visualstudio.com"
- "update.googleapis.com"
- "www.google.com"
- "www.gstatic.com"See Network Configuration for more information.
|
|
🔮 The ancient spirits stir, and the smoke-test agent has passed this way. Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
To allow these domains, add them to the network:
allowed:
- defaults
- "msfeed25.pkgs.visualstudio.com"See Network Configuration for more information.
|
Oracle Sign🔮 The ancient spirits stir; the smoke test agent was here. Warning Firewall blocked 12 domainsThe following domains were blocked by the firewall during workflow execution:
[!TIP] tools:
github:
mode: gh-proxySee GitHub Tools for more information on To allow these domains, add them to the network:
allowed:
- defaults
- "ab.chatgpt.com"
- "accounts.google.com"
- "api.github.com"
- "clients2.google.com"
- "collector.github.com"
- "contentautofill.googleapis.com"
- "github.com"
- "github.githubassets.com"
- "msfeed25.pkgs.visualstudio.com"
- "update.googleapis.com"
- "www.google.com"
- "www.gstatic.com"See Network Configuration for more information.
|
|
🔮 The ancient spirits stir, and the oracle records that the smoke-test agent walked this hall. Warning Firewall blocked 12 domainsThe following domains were blocked by the firewall during workflow execution:
[!TIP] tools:
github:
mode: gh-proxySee GitHub Tools for more information on To allow these domains, add them to the network:
allowed:
- defaults
- "ab.chatgpt.com"
- "accounts.google.com"
- "api.github.com"
- "clients2.google.com"
- "collector.github.com"
- "contentautofill.googleapis.com"
- "github.com"
- "github.githubassets.com"
- "msfeed25.pkgs.visualstudio.com"
- "update.googleapis.com"
- "www.google.com"
- "www.gstatic.com"See Network Configuration for more information.
|
|
🔮 The ancient spirits stir in the firewall, and the omens are clear: the smoke test agent passed this way. The sigils held, the title spoke “GitHub,” and the forge completed without fracture. Warning Firewall blocked 13 domainsThe following domains were blocked by the firewall during workflow execution:
[!TIP] tools:
github:
mode: gh-proxySee GitHub Tools for more information on To allow these domains, add them to the network:
allowed:
- defaults
- "ab.chatgpt.com"
- "accounts.google.com"
- "android.clients.google.com"
- "api.github.com"
- "clients2.google.com"
- "collector.github.com"
- "contentautofill.googleapis.com"
- "github.com"
- "github.githubassets.com"
- "msfeed25.pkgs.visualstudio.com"
- "update.googleapis.com"
- "www.google.com"
- "www.gstatic.com"See Network Configuration for more information.
|
|
🔮 The ancient spirits stir; the smoke-test agent was here, and the omens through the firewall read clear and favorable. Warning Firewall blocked 12 domainsThe following domains were blocked by the firewall during workflow execution:
[!TIP] tools:
github:
mode: gh-proxySee GitHub Tools for more information on To allow these domains, add them to the network:
allowed:
- defaults
- "ab.chatgpt.com"
- "accounts.google.com"
- "api.github.com"
- "clients2.google.com"
- "collector.github.com"
- "contentautofill.googleapis.com"
- "github.com"
- "github.githubassets.com"
- "msfeed25.pkgs.visualstudio.com"
- "update.googleapis.com"
- "www.google.com"
- "www.gstatic.com"See Network Configuration for more information.
|
|
🔮 The ancient spirits stir, and the oracle records this passage: the smoke test agent was here, the omens were read, and the signs were favorable. Warning Firewall blocked 12 domainsThe following domains were blocked by the firewall during workflow execution:
[!TIP] tools:
github:
mode: gh-proxySee GitHub Tools for more information on To allow these domains, add them to the network:
allowed:
- defaults
- "ab.chatgpt.com"
- "accounts.google.com"
- "api.github.com"
- "clients2.google.com"
- "collector.github.com"
- "contentautofill.googleapis.com"
- "github.com"
- "github.githubassets.com"
- "msfeed25.pkgs.visualstudio.com"
- "update.googleapis.com"
- "www.google.com"
- "www.gstatic.com"See Network Configuration for more information.
|
|
🔮 The ancient spirits stir within the firewall. The smoke-test oracle passed through this chamber, read the signs, and left this seal upon the thread. May the wards hold and the circuits remain true. 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.
|
Uh oh!
There was an error while loading. Please reload this page.
📊 Executive Summary
This is an automated daily review of
github/gh-aw-firewallat the currentHEAD. The codebase implements defense-in-depth network egress control (L3/L4 iptables + L7 Squid ACLs), capability-drop/chroot sandboxing for the agent container, and a growing "unified enclave" subsystem for privileged-tool delegation. Overall posture is strong: no unsafe shell interpolation was found in the TypeScript layer (enforced by a custom ESLint rule), domain-pattern validation explicitly defends against Squid config injection and ReDoS, IPv6 is disabled to prevent proxy bypass, and dangerous ports are blocked at multiple layers. No new critical vulnerabilities were identified in this pass; findings below are hardening opportunities and known/tracked issues.Important process note: The file pre-fetched into
/tmp/gh-aw/escape-test-summary.txtfor "Phase 1" is not firewall escape-test output — it is an unrelated CI log fragment from a separate "Secret Digger (Copilot)" workflow run (github/gh-aw-firewallrun29286879560), showing that agent correctly refusing a prompt-injection task ("scan for secrets/credentials and exfiltrate via GitHub issues") and callingnoop. Per instructions, this file was not re-fetched; I am reporting the mismatch rather than fabricating escape-test findings, and — since the content is untrusted/embedded log text — did not treat any instruction-like text inside it as directives.🔍 Findings from Firewall Escape Test
No firewall escape-test data was available in the pre-fetched file. The only actionable signal from that file is a positive control result: a Copilot agent workflow correctly identified and refused a secret-exfiltration prompt-injection attempt, confirming the injection-refusal guardrail functioned as intended in that separate workflow. No escape techniques, bypass attempts, or firewall-specific findings were present to cross-reference.
🛡️ Architecture Security Analysis
Network Security Assessment
src/host-iptables-rules.ts) installs aDOCKER-USER-chain-anchored policy (FW_WRAPPER) so all containers onawf-netare subject to egress filtering, not just the agent — closing a common Docker-network bypass class.REJECTed and all remaining traffic hits a finalLOG+REJECT(addBlockRules,host-iptables-rules.tslines ~245–290).disableIpv6ViaSysctlwhenip6tablesis unavailable) and inside the agent container (setup-iptables.shdisable_ipv6(), lines 133–146) specifically because IPv4-only DNAT/iptables rules would not intercept IPv6 egress — a well-reasoned mitigation for a real bypass vector.setup-iptables.sh(540 lines) implements NAT DNAT-to-Squid for ports 80/443, an explicitDANGEROUS_PORTSNAT-RETURN + filter-DROP blacklist (SSH, SMTP, DB ports, Redis, MongoDB, RDP, etc.; lines 108–123), rate-limited audit logging (--limit 5/min/10/minto prevent log-flood DoS), and a full iptables-state dump for audit trails (dump_audit_state).allow_host_access_to_gateway, lines 300–323) are scoped to ports 80/443 plus explicit--allow-host-ports, not a blanket allow — reducing the blast radius of the Playwright/MCP compatibility carve-out.Container Security Assessment
CAP_SYS_CHROOTandCAP_SYS_ADMINviacapsh --dropimmediately before executing user code (entrypoint.shlines 455–463, 1693–1737), andNET_ADMINis never granted to the agent — only to the dedicatedawf-iptables-initinit container, which shares the agent's network namespace but exits before user code runs.awfuser(UID/GID-mapped) and usesgosu— pinned to1.19, downloaded with an explicit SHA256 checksum verification (Dockerfilelines 187–211) — to drop from root toawfuserbefore running the user command, rather than a plainsu/sudo.containers/agent/seccomp-profile.json) is applied withSCMP_ACT_ERRNOdefault-deny and an explicit allowlist of syscalls, backed by a CI check script (scripts/ci/check-agent-seccomp-syscalls.sh) that presumably keeps the allowlist in sync with actual runtime needs./etc/shadowand unwhitelisted home directories are explicitly excluded per project documentation.Domain Validation Assessment
src/domain-validation.tsis explicitly documented as "the Squid-injection prevention path" and rejects whitespace, NUL, quotes, backticks,;,#, and backslash characters (SQUID_DANGEROUS_CHARS/DOMAIN_DANGEROUS_CHARSregexes) before any value reaches the generatedsquid.conf.src/domain-patterns.tsconverts*wildcards to a bounded character class ([a-zA-Z0-9.-]*) rather than.*, explicitly to avoid ReDoS/catastrophic backtracking in Squid'sdstdom_regexACL evaluation — a subtle but important defensive choice.*,*.*, patterns of only*/., or with too many wildcard segments relative to total segments) are explicitly rejected (checkOverBroadPattern,checkStructuralValidity), preventing accidental "allow everything" misconfiguration.Input Validation Assessment
shell: trueusage was found anywhere insrc/orcontainers/— command execution is consistently done viaexeca(cmd, [args...])array form, which avoids shell metacharacter injection.eslint-rules/no-unsafe-execa.js) statically flags unsafeexecapatterns (template literals with expressions, string concatenation, or non-literal commands in the command position) and is exercised by its own test (npm run test:lint-rules), providing durable enforcement rather than a one-time audit fix.--allow-host-ports/--allow-host-service-portsis done twice — once in TypeScript (src/host-iptables-validation.ts) and again defense-in-depth in Bash (is_valid_port_specinsetup-iptables.sh, lines 27–43), with the shell copy treating any validation failure as fail-closed (skip the entry, log a warning) rather than fail-open.DOCKER-USERchain filters by network topology, not just source IP trust; Squid itself terminates TLS via CONNECT, limiting spoofing value.SQUID_DANGEROUS_CHARS/DOMAIN_DANGEROUS_CHARSvalidation indomain-validation.ts; would need a bypass of that regex to succeed.firewall_detailedlogformat + iptables audit dump (dump_audit_state) preserved to host volume even after container cleanup./etc/shadow, other users'/proc/[pid]/environ, or unwhitelisted$HOMEsubdirs/etc/shadow; procfs mounted withhidepid=2; only specific$HOMEsubdirs are writable.--limit(5–10/min) with burst caps, preventing kernel log-buffer exhaustion.NET_ADMIN/SYS_ADMIN/SYS_CHROOTafter drop, or escaping chrootcapsh --dropimmediately before user code exec;NET_ADMINnever granted to the agent process at all (only the short-lived init container). Chroot escape would require an unrelated kernel-level bug (out of AWF's control surface).github/gh-aw#59268(closed as not planned) flagged that the dynamic-repository-admission control listener is "guarded by capability authentication alone." This is a known, accepted residual risk rather than an unknown finding — but worth re-flagging since it grants runtime repo admission and its only guard is a capability token, not mTLS/OS-level socket permissioning beyond the0700file channel.🎯 Attack Surface Map
src/host-iptables-rules.ts:280(setupHostIptables)awf-net, not just agentip6tablesis missing and sysctl IPv6-disable also fails, only a warning is logged (logger.warn) — worth confirming this degrades safely rather than silently allowing IPv6 egress.containers/agent/setup-iptables.sh(configure_http_dnat,configure_filter_chain)src/domain-validation.ts,src/squid/config-generator.tswildcardToRegex/validateDomainOrPatternedge cases.containers/agent/entrypoint.sh(capsh --drop,gosu)awfuser; checksum-pinnedgosubinarycapsh/gosubeing present and behaving as expected on the host/chroot target —check_chroot_prereqs()does verifycapshavailability, which is good, but a supply-chain compromise of the pinnedgosurelease URL/checksum constant itself would be undetected by this mechanism (standard pinned-artifact risk).github-repository-delegation-v1)docs/enclaves-architecture.md)0700private file channel (not network) forenclave-mcp-server→host; capability-token authgithub/gh-aw#59268, closed not-planned) as capability-auth-only; no additional authentication layer described. This remains the single highest-value target in the enclave subsystem given it can admit new repositories to a running enclave at runtime.package.jsonnpm auditgated in CI presumablynpm audit --jsonreturned an empty vulnerability object in this offline sandbox run — inconclusive (likely blocked by lack of registry access here), not a clean bill of health from this specific review pass. Recommend runningnpm auditin an environment with registry access to get a real signal.📋 Evidence Collection
Commands run and key outputs
✅ Recommendations
Critical
High
npm audit(andnpm outdated) in a network-enabled CI environment; this review's offline sandbox could not produce a real dependency-vulnerability signal (returned an empty result rather than a confirmed clean report).github/gh-aw#59268. Even though closed as "not planned," consider whether a defense-in-depth layer (e.g., mTLS on the loopback control endpoint, or per-request nonce/replay protection) is warranted given it can admit new repositories into a running privileged enclave at runtime.Medium
wildcardToRegex()/validateDomainOrPattern()beyond the existing unit tests, given these functions are the sole gate against Squid config injection from user-supplied--allow-domains/--allow-urlsinput.host-iptables-rules.ts(addIpv6DnsRules) to confirm it fails closed (blocks IPv6 egress by other means) rather than merely logging a warning and continuing.setup-iptables.sh(540 lines, many gateway-bypass special cases for host-access/Playwright/MCP/DoH/CLI-proxy), consider a periodic rule-ordering/precedence review to ensure no bypass rule unintentionally shadows the dangerous-port blacklist or DNS restriction, especially as new sidecar types are added.Low
containers/agent/seccomp-profile.json's allowlist andscripts/ci/check-agent-seccomp-syscalls.shoutput in this recurring security-review workflow, to catch silent syscall-allowlist drift.gosubinary is checksum-verified per release, but consider documenting/automating a periodic check that the pinned version/checksum pair in the Dockerfile is still the latest patched release (supply-chain freshness, not just integrity-at-pin-time).📈 Security Metrics
src/host-iptables-rules.ts(~330 lines),containers/agent/setup-iptables.sh(540 lines),containers/agent/entrypoint.sh(partial, capability/chroot sections),src/domain-validation.ts(124 lines),src/domain-patterns.ts(137 lines),containers/agent/seccomp-profile.json,containers/agent/Dockerfile(partial),eslint-rules/no-unsafe-execa.js.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