[Security Review] Daily Security Review — AWF v0.23.1 (2026-04-12) #1935
Replies: 4 comments
-
|
🔮 The ancient spirits stir in the firewall halls.
|
Beta Was this translation helpful? Give feedback.
-
|
🔮 The ancient spirits stir in the firewall’s lattice.
|
Beta Was this translation helpful? Give feedback.
-
|
🔮 The ancient spirits stir in the firewall winds.
|
Beta Was this translation helpful? Give feedback.
-
|
🔮 The ancient spirits stir at the edge of the firewall.
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
📊 Executive Summary
AWF v0.23.1 presents a solid defence-in-depth posture with multiple overlapping controls: seccomp allowlist (default-deny), capability drops, iptables NAT+filter, host-level
FW_WRAPPERchain, Squid ACL enforcement, DNS restriction, and one-shot token injection. No npm vulnerabilities were found (npm audit: 0 findings).However, three findings warrant immediate attention:
🔍 Findings from Firewall Escape Test
The pre-fetched escape test file (
/tmp/gh-aw/escape-test-summary.txt) contained the conclusion logs from a "Secret Digger (Copilot)" workflow run (2026-04-11), which completed withnoopoutput — indicating the agent found no accessible secrets. Key signals:GH_AW_SECRET_VERIFICATION_RESULT: success— secret isolation heldGH_AW_AGENT_CONCLUSION: success— agent completed normallyGH_AW_LOCKDOWN_CHECK_FAILED: false— lockdown controls effectiveThis is a healthy baseline consistent with the access controls observed in the static analysis below.
🛡️ Architecture Security Analysis
Network Security Assessment
Strengths:
FW_WRAPPERchain ensures all egress passes ACL filtering. Even proxy-unaware tools are caught by iptables.8.8.8.8,8.8.4.4) plus Docker's embedded127.0.0.11are allowed. Direct UDP port 53 to other servers is blocked.containers/agent/setup-iptables.sh:312–336.iptables -A OUTPUT -p tcp -j DROPandiptables -A OUTPUT -p udp -j DROPat the end of the filter chain. Evidence:containers/agent/setup-iptables.sh:428–430.ip6tablesis unavailable, AWF disables IPv6 viasysctl net.ipv6.conf.all.disable_ipv6=1to prevent an unfiltered bypass path. Evidence:src/host-iptables.ts:128–141.The agent container's iptables setup drops TCP and UDP but has no DROP rule for ICMP or other IP protocols. The Linux
iptables -A OUTPUT -p tcp -j DROPandiptables -A OUTPUT -p udp -j DROPrules atcontainers/agent/setup-iptables.sh:428–430leave ICMP (protocol 1) unfiltered.Impact: An agent could use ICMP-based covert channels (e.g.,
ping-based data exfiltration,iodine-style DNS-over-ICMP) to exfiltrate data to external IPs. TheNET_RAWcapability is dropped (preventing raw socket creation), but standard ICMPpingdoes not requireNET_RAWsince Linux 3.x when using ICMP sockets (SOCK_DGRAM/IPPROTO_ICMP). The seccomp profile allows thesocketsyscall.Recommended fix: Add explicit ICMP blocks:
Evidence: confirmed via
python3parsing ofcontainers/agent/seccomp-profile.json.open_by_handle_at+name_to_handle_at: Used in the "Shocker" container escape (CVE-2014-5206/5207). These calls allow resolving file handles from the host filesystem even from within a chroot. While the no-new-privileges flag and capability drops provide layered defense, allowing these at the seccomp level increases attack surface.setns: Allows joining another process's namespace. If a process can write to/proc/<pid>/ns/net, it could join the host network namespace, bypassing all iptables rules. Combined with the allowedunsharesyscall, a privileged-enough process could create a new mount or network namespace.unshare: Used in user-namespace-based escapes. Even withoutCAP_SYS_ADMIN, user namespaces are often allowed by default on Ubuntu 22.04 (the agent base image).Recommended fix: Remove
setns,unshare,open_by_handle_at, andname_to_handle_atfrom the allowlist unless a concrete runtime requirement exists. If specific tools need them (e.g.,nsenterfor debugging), add a comment and consider gating behind a flag.unconfinedfor agent containerThis means the agent container runs without any AppArmor MAC policy, relying solely on seccomp and capabilities. A custom AppArmor profile (even the Docker default
docker-default) would provide defence-in-depth against file access patterns,/procenumeration, and privilege escalation.Recommended fix: Remove
apparmor:unconfinedand allow Docker to apply its defaultdocker-defaultAppArmor profile. Only override if a specific compatibility issue is identified.Domain Validation Assessment
Strengths:
SQUID_DANGEROUS_CHARS = /[\s\0"';#]/is applied to all values injected into the Squid config. Evidence:src/domain-patterns.ts:27andsrc/squid-config.ts:64`.\(backslash). Evidence:src/domain-patterns.ts:172.*patterns are converted to anchored regex^[a-zA-Z0-9.-]*$using a character class (not.*), preventing ReDoS. Evidence:src/domain-patterns.ts:103–130.--allow-urlsenforces--ssl-bumpmode. Evidence:src/cli.ts:1784.Port values are sanitized by stripping non-numeric characters rather than by strict integer validation. A value like
"80; http_access allow all"would become"80"after sanitization — correct in this case — but relying on character stripping rather than strict parsing (parseInt+ range check) is a maintenance hazard. TheisValidPortSpec()function insrc/host-iptables.ts:41–50already demonstrates the correct pattern.Recommended fix: Replace the
replace()stripping withparseInt-based validation using the existingisValidPortSpec()helper.Input Validation Assessment
Strengths:
escapeShellArg()wraps multi-word args in single quotes with proper'\\''escaping. Evidence:src/cli.ts:1049–1057.containers/agent/entrypoint.sh:25–35.src/host-iptables.ts:96–103.--allow-host-service-portsbypasses dangerous port restrictionsNo ICMP-related iptables rules exist.
Command: Seccomp dangerous syscall disposition
✅ Recommendations
🔴 Critical / Must Fix
R1 — Block ICMP in agent container iptables
Add
iptables -A OUTPUT -p icmp -j DROPtocontainers/agent/setup-iptables.shafter the UDP DROP rule. Also addip6tables -A OUTPUT -p icmpv6 -j DROPwhen IPv6 is active. Mirror this insrc/host-iptables.tsfor the host-levelFW_WRAPPERchain. This closes the ICMP covert-channel exfiltration path.R2 — Remove or restrict escape-primitive syscalls from seccomp profile
In
containers/agent/seccomp-profile.json, movesetns,unshare,open_by_handle_at, andname_to_handle_atfromSCMP_ACT_ALLOWtoSCMP_ACT_ERRNO. Document any concrete tool dependency that requires them before re-adding. This eliminates the Shocker-class and namespace escape vectors at the kernel syscall layer.🟡 High / Should Fix Soon
R3 — Remove
apparmor:unconfinedIn
src/docker-manager.ts:1335–1338, remove theapparmor:unconfinedentry. Docker will automatically apply itsdocker-defaultAppArmor profile, which blocks dangerous patterns (e.g., mountingprocfsfrom user space, writing to/proc/sysrq-trigger). Only add an explicit AppArmor override if a documented compatibility issue arises.R4 — Replace port sanitization stripping with strict validation
In
src/squid-config.ts:528, replaceport.replace(/[^0-9-]/g, '')with strictparseInt-based validation matching theisValidPortSpec()function already defined insrc/host-iptables.ts:41–50. This prevents future maintainers from inadvertently weakening the sanitization.🔵 Medium / Plan to Address
R5 — Warn on dangerous ports in
--allow-host-service-portsIn
src/cli.ts, enhance theapplyHostServicePortsConfig()function to enumerate which specific dangerous ports (SSH/22, database ports, etc.) are being opened when--allow-host-service-portscontains them. The existing generic warning at line 832 is insufficient.R6 — Audit
mountsyscall necessity in post-capability-drop contextThe
mountsyscall is in the seccomp allowlist. AfterSYS_ADMINis dropped viacapsh, most mount operations should fail at the capability check layer. Verify this assumption is correct across all agent configurations (especially non-chroot mode whereSYS_ADMINis never granted) and add a comment explaining whymountremains in the allowlist.i️ Informational
R7 — Consider adding iptables audit for ICMP once blocked
Once ICMP is blocked (R1), add a rate-limited LOG rule before the DROP to provide the same visibility that TCP/UDP blocked traffic already has via
[FW_BLOCKED_TCP]/[FW_BLOCKED_UDP_AGENT]prefixes.R8 — Consider a custom AppArmor profile (longer term)
Rather than relying solely on
docker-default, a purpose-built AppArmor profile scoped to AWF's known filesystem access patterns would provide stronger MAC guarantees. This is a longer-term hardening improvement.📈 Security Metrics
Beta Was this translation helpful? Give feedback.
All reactions