[Security Review] Daily Security Review — 2026-04-20 #2112
Replies: 6 comments
-
|
🔮 The ancient spirits stir, and the smoke-test agent has walked this thread. Warning
|
Beta Was this translation helpful? Give feedback.
-
|
🔮 The ancient spirits stir, and the smoke-test agent has walked this thread. Warning
|
Beta Was this translation helpful? Give feedback.
-
|
🔮 The ancient spirits stir in the firewall halls. Warning
|
Beta Was this translation helpful? Give feedback.
-
|
🔮 The ancient spirits stir, and the smoke-test agent has walked these halls. The omens were read, the runes were checked, and this discussion now bears the mark of passage. Warning
|
Beta Was this translation helpful? Give feedback.
-
|
🔮 The ancient spirits stir, and the firewall omens align. Warning
|
Beta Was this translation helpful? Give feedback.
-
|
🔮 The ancient spirits stir in the firewall halls. This smoke-test oracle has walked this thread, read the runes, and marked its passage. May the network wards hold true. Warning
|
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 mature, defense-in-depth security posture. The architecture deliberately separates privilege boundaries (iptables-init container holds
NET_ADMIN; the agent container does not), enforces L7 egress filtering via Squid, drops capabilities before executing user code, and applies a seccomp profile. npm audit reports zero vulnerabilities across all dependencies. No critical findings were identified in this review.🔍 Context from Firewall Escape Test
The pre-fetched escape test file (
/tmp/gh-aw/escape-test-summary.txt) contained only workflow orchestration telemetry from a "Secret Digger (Copilot)" run (workflow run24273493151, dated 2026-04-11). Key signals:GH_AW_AGENT_CONCLUSION: success— agent completed successfullyGH_AW_SECRET_VERIFICATION_RESULT: success— no secrets were exfiltratedGH_AW_LOCKDOWN_CHECK_FAILED: false— lockdown constraints heldGH_AW_INFERENCE_ACCESS_ERROR: false— no inference endpoint access errorsnoopsafe-output — no escalation, no data exfiltration discoveredThis corroborates the static analysis findings: the sandbox successfully contained the agent and no secret-leakage bypass was achieved.
🛡️ Architecture Security Analysis
Network Security Assessment
Evidence gathered from
src/host-iptables.ts,containers/agent/setup-iptables.shThe network enforcement has three layers:
Host-level
FW_WRAPPERchain (src/host-iptables.ts) — Applied on the Docker bridge interface (fw-bridge). Restricts which containers on the bridge can reach the outside world. DNS restricted to configured servers only (default8.8.8.8,8.8.4.4); all other DNS is blocked.Container NAT chain (
setup-iptables.sh) — Runs inside the agent's network namespace (viaawf-iptables-init). DNAT rules redirect all TCP 80/443 to Squid at172.30.0.10:3128. Localhost and agent self-IP are explicitly bypassed.IPv6 disabled at container startup (
setup-iptables.shlines ~55-58):This prevents IPv6 from serving as a proxy bypass path.
http_proxy(lowercase) is intentionally not set (httpoxy mitigation, documented in AGENTS.md). Tools that bypassHTTP_PROXYand also attempt raw TCP to port 80 will be correctly DNAT'd to Squid. However, if iptables rules fail to install (e.g., container capability issues), HTTP traffic would not be intercepted. The defensive comment in AGENTS.md acknowledges this but there is no runtime assertion verifying the DNAT rules succeeded before user code runs.Container Security Assessment
Evidence from
src/docker-manager.tslines 683, 1524-1544, 1683-1684:After chroot,
capsh --drop=SYS_CHROOT,SYS_ADMINis called before user code executes (entrypoint.sh), so those elevated capabilities are removed from the bounding set before the agent process starts.✅ Strength: The separation of
NET_ADMIN(iptables-init) from the agent container is a sound design — the agent process cannot modify its own firewall rules.SYS_ADMINgrant): The agent container requiresSYS_ADMINtemporarily fortmpfsmount during SSL bump setup (src/ssl-bump.ts:70).SYS_ADMINis extremely broad — it allows overlayfs mounts, namespace creation, and many other privileged operations. While it is dropped before user code runs, a race window exists between container start and capability drop where a compromised dependency in the entrypoint chain could exploit it.UID/GID validation (
src/docker-manager.ts:124) correctly rejects UIDs/GIDs 0–999 (system range) and the entrypoint (containers/agent/entrypoint.sh) additionally rejects UID/GID = 0 explicitly.Domain Validation Assessment
Evidence from
src/domain-patterns.ts:27,src/squid-config.ts:102-116:All user-supplied domain strings are sanitized before interpolation into
squid.conf. Characters that could inject Squid directives (whitespace, null bytes, quotes, semicolons, backticks, hash, backslash) are rejected with an exception.\(backslash) in the character class but the comment says it does ("and backslashes"). Verified:SQUID_DANGEROUS_CHARS = /[\s\0"';#]/— backslash` is NOT in the class. A backslash in a domain name (which is invalid per RFC 1123 and would be rejected by Squid anyway) would not be caught here. This is a documentation inconsistency rather than an exploitable flaw, since Squid'sdstdomainACL would reject backslash-containing names. Still, the guard should match its stated scope.Input Validation Assessment
Evidence from
src/cli.ts:1052-1070:SQUID_DANGEROUS_CHARS definition (src/domain-patterns.ts:27)
Note: backslash
\is absent from this regex despite the accompanying comment claiming it is included.Capability configuration (src/docker-manager.ts:1524-1544)
iptables-init separation (src/docker-manager.ts:1683)
Agent container does NOT get NET_ADMIN — confirmed by test at line 895.
IPv6 disable in container (setup-iptables.sh)
Failure is non-fatal (prints WARNING). If sysctl fails, IPv6 remains enabled.
Escape test run telemetry
Workflow:
Secret Digger (Copilot), run24273493151(2026-04-11)GH_AW_SECRET_VERIFICATION_RESULT: successGH_AW_LOCKDOWN_CHECK_FAILED: false✅ Recommendations
🔴 High
H1 — Assert iptables DNAT rules installed successfully before starting user command
Currently
setup-iptables.shcan emit warnings (e.g., IPv6 sysctl failure) and continue. If the DNAT redirect for port 80/443 silently fails, HTTP/HTTPS traffic would egress without filtering. Add a verification step after rule installation that confirms the expected DNAT rules exist (e.g.,iptables -t nat -L OUTPUT | grep REDIRECTcheck) and fail the container if they are absent.🟠 Medium
M1 — Harden
SYS_ADMINgrant scope (SSL Bump path only)SYS_ADMINis only needed fortmpfsmount during SSL Bump setup. Consider splitting the entrypoint into a privileged setup phase and a capability-drop phase more aggressively, or replacing thetmpfsapproach with a pre-allocated ramdisk, to narrow theSYS_ADMINwindow.M2 — Handle IPv6 sysctl failure as fatal
The current code prints a WARNING if
sysctl -w net.ipv6.conf.all.disable_ipv6=1fails, then continues. An attacker in a container where sysctl is restricted would retain IPv6 connectivity that bypasses the IPv4 DNAT rules. Treat this as fatal, or verify no IPv6 routes exist before proceeding.M3 — Document the one-shot-token timing window
The
entrypoint.shruns the agent in background, waits up to 1 second for token caching, then unsets tokens from the parent shell. The comment acknowledges tokens are cached in ~100ms. This is correct for single-process agents, but if the agent forks quickly before the LD_PRELOAD hook initializes (e.g.,/bin/shshebang scripts), tokens may not be cached before the parent unsets them. Add a test case covering shell-script agents.🟡 Low
L1 — Fix
SQUID_DANGEROUS_CHARSto include backslashsrc/domain-patterns.ts:27— Add\\to the regex character class to match the documented behavior. While backslash in domain names is invalid per RFC 1123 and Squid would reject such entries, the guard should accurately reflect its intent:L2 — Add iptables log verification test
Integration test coverage for the
[FW_BLOCKED_UDP]and[FW_BLOCKED_OTHER]iptables LOG rules is absent (perdocs/INTEGRATION-TESTS.md). Add a test that verifies blocked non-HTTP traffic appears in kernel logs.L3 — Pin
ubuntu/squid:latestto a digestcontainers/squid/Dockerfile(viaubuntu/squid:latest) uses a floating tag. A supply-chain compromise of the upstream image would affect all users pullinglatest. Pin to a specific digest with automated update tooling (e.g., Dependabot or Renovate).L4 — Consider AppArmor profile for Squid container
The Squid container has no AppArmor profile configured (only the agent has seccomp). Adding an AppArmor profile for the Squid process would restrict file system access and syscalls beyond what seccomp alone provides.
📈 Security Metrics
src/cli.ts,src/host-iptables.ts,src/docker-manager.ts,src/squid-config.ts,src/domain-patterns.ts,src/ssl-bump.tscontainers/agent/entrypoint.sh,containers/agent/setup-iptables.shOverall security posture: Strong. The architecture correctly separates privilege, enforces L7 egress filtering, uses seccomp + capability drop, and validates all user-controlled input before injection into configuration files. Recommended improvements are hardening measures, not fixes for exploitable vulnerabilities.
Beta Was this translation helpful? Give feedback.
All reactions