You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Deep evidence-based security review of the gh-aw-firewall codebase (2,513 lines of security-critical code analyzed across 5 core files). The overall security posture is strong. No critical vulnerabilities were found, and no npm dependency vulnerabilities exist. Three low/medium findings were identified, all of which are defense-in-depth gaps rather than direct exploitable issues.
Severity
Count
Critical
0
High
0
Medium
1
Low
2
Informational
3
🔍 Findings from Firewall Escape Test
Workflow logs for the security-review workflow could not be fetched in this run (GitHub CLI git discovery issue in sandbox). Analysis is based entirely on static source code review below.
🛡️ Architecture Security Analysis
Network Security Assessment ✅ (with caveats)
The firewall implements a layered defense using two independent enforcement points:
git safe.directory='*' disables ownership protections in container
containers/agent/entrypoint.sh:296
Informational
Low
T6
Information Disclosure
SSL Bump (opt-in) decrypts all HTTPS traffic including credentials
src/squid-config.ts:147-182 – documented but high-impact if misused
Informational
Operator-controlled
🎯 Attack Surface Map
Attack Surface
Location
Current Protections
Residual Risk
Egress HTTP/HTTPS
Squid:3128, DNAT rules
Domain ACL, port allowlist, IP-direct blocking, forwarded_for stripped
Low
Egress DNS
UDP/TCP 53 to Docker embedded DNS
Only 127.0.0.11 in resolv.conf; upstream whitelisted; direct DNS blocked
Low
Egress non-TCP/UDP (ICMP, SCTP)
Container OUTPUT / Host FORWARD
Container: not explicitly dropped (see T2); Host FW_WRAPPER: final REJECT catches all
Very Low
API proxy sidecar
172.30.0.30:10000-10004
Host iptables allows 10000-10004 (incl. 10003 gap); agent uses only API calls
Very Low
Dangerous service ports
Setup-iptables NAT RETURN + OUTPUT DROP
15 ports in iptables NAT, 21 in Squid; final DROP catches all TCP anyway
Very Low
Container → Host filesystem
Selective bind mounts
/etc/shadow excluded, home dir allow-list, chroot root is /host
Low
Privilege escalation
Entrypoint capability drops
capsh drops caps, NET_ADMIN not granted to agent, seccomp blocks syscalls
Low
Token leakage via /proc
One-shot-token library + token unset
LD_PRELOAD protects env, 5s sleep before unset
Very Low
IPv6 bypass
ip6tables / sysctl disable fallback
If ip6tables available: rules applied; if not: sysctl disable_ipv6=1
Very Low
📋 Evidence Collection
Finding T1: Dangerous Port List Mismatch
# Command run:
diff <(grep -E "^\s+[0-9]+" setup-iptables.sh | grep -oE "[0-9]+") \
<(grep -E "^\s+[0-9]+," squid-config.ts | grep -oE "[0-9]+")# Output (ports in squid-config.ts but NOT in setup-iptables.sh):# 5984 CouchDB# 6984 CouchDB (SSL)# 8086 InfluxDB HTTP API# 8088 InfluxDB RPC# 9200 Elasticsearch HTTP API# 9300 Elasticsearch transport# Relevant code (setup-iptables.sh DANGEROUS_PORTS array):# 15 ports total – missing: 5984, 6984, 8086, 8088, 9200, 9300# Relevant code (squid-config.ts DANGEROUS_PORTS):# 21 ports total – correctly includes all of the above
Impact: Minimal. The container's final iptables -A OUTPUT -p tcp -j DROP catches all TCP regardless of the NAT RETURN list. However, this inconsistency could mislead operators and represents incomplete defense-in-depth documentation.
Finding T2: ICMP Not Explicitly Blocked in Container OUTPUT
# Command run:
grep "iptables -A OUTPUT" containers/agent/setup-iptables.sh | grep -E "\-p (tcp|udp|icmp)"# Output (only TCP and UDP are dropped – no ICMP rule):# iptables -A OUTPUT -p tcp -d 127.0.0.11 --dport 53 -j ACCEPT# iptables -A OUTPUT -p tcp -d "$SQUID_IP" -j ACCEPT# iptables -A OUTPUT -p tcp -d "$AWF_API_PROXY_IP" -j ACCEPT# iptables -A OUTPUT -p tcp -j DROP# iptables -A OUTPUT -p udp -j DROP## → No "iptables -A OUTPUT -p icmp -j DROP"# Host-level mitigation (src/host-iptables.ts:413-417):# Final catch-all REJECT in FW_WRAPPER does block ICMP via FORWARD chain.# ICMP to external IPs is therefore blocked at the host level.# Only ICMP within the 172.30.0.0/24 Docker network is not explicitly restricted.
Impact: Very low. External ICMP exfiltration (ICMP tunneling to internet) is blocked at the host level. Intra-network ICMP (agent→squid pings) is inconsequential.
Finding T3: API Proxy Port Range Gap (10003)
# Port definition (src/types.ts:16-44):# OPENAI: 10000# ANTHROPIC: 10001# COPILOT: 10002# OPENCODE: 10004 ← gap at 10003# Host iptables rule (src/host-iptables.ts:365-373):
const allPorts = Object.values(API_PROXY_PORTS); // [10000, 10001, 10002, 10004]
const minPort = Math.min(...allPorts); // 10000
const maxPort = Math.max(...allPorts); // 10004
// Rule: -p tcp -d $apiProxyIp --dport 10000:10004 -j ACCEPT
# → Port 10003 on 172.30.0.30 is allowed through firewall with no service behind it
Impact: Very low. No service listens on 10003 at the API proxy IP, so connections would be refused by the container. An adversary would need to compromise the API proxy container and bind a service to 10003.
Finding T4: Token Unset Timing Assumption
# containers/agent/entrypoint.sh:641-695
AGENT_PID=$!# Wait for agent to initialize and cache tokens (5 seconds)
sleep 5
# Unset all sensitive tokens from parent shell environment
unset_sensitive_tokens
wait$AGENT_PID
Design: The one-shot-token library intercepts getenv() via LD_PRELOAD and caches the value. Subsequent calls return the cached value even after the shell unsets the variable. The 5-second window is intentional to allow the library to be loaded and the first read to occur. Tokens are never directly visible in /proc/self/environ after the parent unsets them.
Context: This is required because the workspace bind mount may be owned by a different UID than awfuser (before UID/GID remapping takes effect). The risk is limited to the container environment where the operator controls what is mounted.
# src/squid-config.ts – confirmed positive security controls:
grep "pinger_enable\|forwarded_for\|via off\|cache deny" src/squid-config.ts
# 517: pinger_enable off ← disables ICMP at L7# 532: cache deny all ← no disk caching (cross-request leakage)# 568: cache deny all ← duplicate/confirmed in second location# 574: forwarded_for delete ← no X-Forwarded-For header# 575: via off ← no Via header (topology hiding)
While the final iptables -A OUTPUT -p tcp -j DROP catches these, the intent of the NAT RETURN list is explicit defense-in-depth documentation. Add the 6 missing ports to DANGEROUS_PORTS in setup-iptables.sh.
L1 – Explicitly Block ICMP in Container OUTPUT Chain
Add iptables -A OUTPUT -p icmp -j DROP to setup-iptables.sh after the UDP DROP rule. While ICMP is blocked at the host level via FW_WRAPPER, adding an explicit container-level rule closes the defense-in-depth gap and prevents any intra-network ICMP leakage.
Files: containers/agent/setup-iptables.sh after line 320
L2 – Use Explicit Port List Instead of min-max Range for API Proxy
Replace the minPort:maxPort range in src/host-iptables.ts with explicit per-port rules matching exactly API_PROXY_PORTS values (10000, 10001, 10002, 10004), eliminating the unintended port 10003 allowance.
Files: src/host-iptables.ts lines 365-374
🟢 Informational
I1 – Document 5-second Token Caching Window
The sleep 5 before unset_sensitive_tokens is correct but worth explicitly documenting the security model: tokens are readable by the agent during the first 5 seconds via direct env read, then only via the one-shot-token library cache. Consider making the delay configurable via an env var for high-security environments.
I2 – Consider Restricting git safe.directory
The global safe.directory='*' is necessary for workspace access but broad. Consider restricting to specific mounted paths (e.g., the workspace directory) rather than all paths.
I3 – SSL Bump Operational Guidance
When --enable-ssl-bump is used, the Squid CA key should be treated as a highly sensitive secret. Consider adding a prominent warning in the CLI output when SSL bump is active, noting that HTTPS credentials will be visible to the Squid proxy.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
📊 Executive Summary
Deep evidence-based security review of the gh-aw-firewall codebase (2,513 lines of security-critical code analyzed across 5 core files). The overall security posture is strong. No critical vulnerabilities were found, and no npm dependency vulnerabilities exist. Three low/medium findings were identified, all of which are defense-in-depth gaps rather than direct exploitable issues.
🔍 Findings from Firewall Escape Test
Workflow logs for the
security-reviewworkflow could not be fetched in this run (GitHub CLI git discovery issue in sandbox). Analysis is based entirely on static source code review below.🛡️ Architecture Security Analysis
Network Security Assessment ✅ (with caveats)
The firewall implements a layered defense using two independent enforcement points:
Layer 1 – Host-level (FORWARD chain,
src/host-iptables.ts)FW_WRAPPERchain is inserted at position 1 ofDOCKER-USER224.0.0.0/4) and link-local (169.254.0.0/16) rangesicmp-port-unreachable)Layer 2 – Container-level (OUTPUT chain,
containers/agent/setup-iptables.sh)iptables -A OUTPUT -p tcp -j DROPandiptables -A OUTPUT -p udp -j DROPL7 – Squid Proxy (
src/squid-config.ts)dstdomain) and wildcard regex (dstdom_regex)acl dst_ipv4 dstdom_regex ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$pinger_enable offforwarded_for delete+via offcache deny all(prevents cross-request side-channel via cache)http_access deny !Safe_portsContainer Security Assessment ✅
NET_ADMINis never granted to the agent container (only to the ephemeral init containerawf-iptables-init)if [ "$HOST_UID" -eq 0 ]; then … exit 1ptrace,process_vm_readv,process_vm_writev,kexec_load,reboot, kernel module operations,pivot_root, key management syscalls (add_key,request_key,keyctl)LD_PRELOAD) prevents multiple reads of sensitive env varsunset_sensitive_tokensallows agent to cache tokens via the libraryDomain Validation Assessment ✅
*and*.*explicitly rejected*rejected*.and.*rejected(redacted)https://` prefixes)Input Validation Assessment ✅
--allow-host-ports(enforced in both Squid config and iptables)setup-iptables.shhas 15 ports;squid-config.tshas 21iptables -A OUTPUT -p icmp -j DROPinsetup-iptables.shsrc/host-iptables.ts:371uses\$\{minPort}:\$\{maxPort}=10000:10004containers/agent/entrypoint.sh:641-689containers/agent/entrypoint.sh:296src/squid-config.ts:147-182– documented but high-impact if misused🎯 Attack Surface Map
/etc/shadowexcluded, home dir allow-list, chroot root is/hostsysctl disable_ipv6=1📋 Evidence Collection
Finding T1: Dangerous Port List Mismatch
Impact: Minimal. The container's final
iptables -A OUTPUT -p tcp -j DROPcatches all TCP regardless of the NAT RETURN list. However, this inconsistency could mislead operators and represents incomplete defense-in-depth documentation.Finding T2: ICMP Not Explicitly Blocked in Container OUTPUT
Impact: Very low. External ICMP exfiltration (ICMP tunneling to internet) is blocked at the host level. Intra-network ICMP (agent→squid pings) is inconsequential.
Finding T3: API Proxy Port Range Gap (10003)
Impact: Very low. No service listens on 10003 at the API proxy IP, so connections would be refused by the container. An adversary would need to compromise the API proxy container and bind a service to 10003.
Finding T4: Token Unset Timing Assumption
Design: The one-shot-token library intercepts
getenv()via LD_PRELOAD and caches the value. Subsequent calls return the cached value even after the shell unsets the variable. The 5-second window is intentional to allow the library to be loaded and the first read to occur. Tokens are never directly visible in/proc/self/environafter the parent unsets them.Finding T5: git safe.directory Disabled
Context: This is required because the workspace bind mount may be owned by a different UID than
awfuser(before UID/GID remapping takes effect). The risk is limited to the container environment where the operator controls what is mounted.Positive Finding: Zero npm Vulnerabilities
Positive Finding: Squid Security Hardening
✅ Recommendations
🔴 Critical
None identified.
🟠 High
None identified.
🟡 Medium
M1 – Synchronize Dangerous Port Lists
containers/agent/setup-iptables.shDANGEROUS_PORTS is missing 6 ports present insrc/squid-config.ts:5984(CouchDB),6984(CouchDB SSL),8086(InfluxDB HTTP),8088(InfluxDB RPC),9200(Elasticsearch HTTP),9300(Elasticsearch transport).While the final
iptables -A OUTPUT -p tcp -j DROPcatches these, the intent of the NAT RETURN list is explicit defense-in-depth documentation. Add the 6 missing ports toDANGEROUS_PORTSinsetup-iptables.sh.Files:
containers/agent/setup-iptables.shlines 222-249🔵 Low
L1 – Explicitly Block ICMP in Container OUTPUT Chain
Add
iptables -A OUTPUT -p icmp -j DROPtosetup-iptables.shafter the UDP DROP rule. While ICMP is blocked at the host level via FW_WRAPPER, adding an explicit container-level rule closes the defense-in-depth gap and prevents any intra-network ICMP leakage.Files:
containers/agent/setup-iptables.shafter line 320L2 – Use Explicit Port List Instead of min-max Range for API Proxy
Replace the
minPort:maxPortrange insrc/host-iptables.tswith explicit per-port rules matching exactlyAPI_PROXY_PORTSvalues (10000, 10001, 10002, 10004), eliminating the unintended port 10003 allowance.Files:
src/host-iptables.tslines 365-374🟢 Informational
I1 – Document 5-second Token Caching Window
The
sleep 5beforeunset_sensitive_tokensis correct but worth explicitly documenting the security model: tokens are readable by the agent during the first 5 seconds via direct env read, then only via the one-shot-token library cache. Consider making the delay configurable via an env var for high-security environments.I2 – Consider Restricting git safe.directory
The global
safe.directory='*'is necessary for workspace access but broad. Consider restricting to specific mounted paths (e.g., the workspace directory) rather than all paths.I3 – SSL Bump Operational Guidance
When
--enable-ssl-bumpis used, the Squid CA key should be treated as a highly sensitive secret. Consider adding a prominent warning in the CLI output when SSL bump is active, noting that HTTPS credentials will be visible to the Squid proxy.📈 Security Metrics
Beta Was this translation helpful? Give feedback.
All reactions