[Security Review] Daily Security Review and Threat Modeling – 2026-03-19 #1368
Closed
Replies: 1 comment
-
|
This discussion was automatically closed because it expired on 2026-03-26T13:56:45.911Z.
|
Beta Was this translation helpful? Give feedback.
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
This review covers the AWF (Agentic Workflow Firewall) codebase with evidence gathered by direct source inspection. The firewall's defense-in-depth architecture is generally sound, with multiple overlapping layers. No critical vulnerabilities were found. Four medium-severity findings and five low/informational findings are documented below with verifiable evidence.
Security Posture Overview
dstdomain+dstdom_regex, ReDoS-safe wildcardsdst_ipv4/dst_ipv6ACLs deny raw IP CONNECTscapsh --dropbefore user code; UID ≠ 0 enforcedapparmor:unconfinedto permit procfs mount🔍 Findings from Previous Security Workflow Runs
The
security-reviewandsecret-digger-*workflows are all compiled and active, but log downloads were unavailable in this run due to the environment not having git-based remote access. Findings below are based entirely on static source analysis.🛡️ Architecture Security Analysis
Network Security Assessment
Squid ACL rule ordering is correct. Evidence from
src/squid-config.ts:541–565:Squid evaluates first-match, so non-allowed domains are denied before the
allow localnetrule is reached. ✅Host-level iptables chain is well-structured.
src/host-iptables.tsbuilds a dedicatedFW_WRAPPERchain inserted intoDOCKER-USER, scoping rules to the specific bridge interface. Order:169.254.0.0/16,224.0.0.0/4)Finding (Medium) — IPv6 container OUTPUT chain lacks DROP rules
containers/agent/setup-iptables.shends with:# Drop all other TCP and UDP traffic (default deny policy) iptables -A OUTPUT -p tcp -j DROP iptables -A OUTPUT -p udp -j DROPThere are no corresponding
ip6tablesOUTPUT DROP rules. Also, insrc/host-iptables.ts, theCHAIN_NAME_V6chain is created only when IPv6 DNS servers are configured (hasIpv6Dns && ip6tablesAvailable) and is never inserted into ip6tables DOCKER-USER:If a Docker network is created with IPv6 support, IPv6 TCP/UDP from the agent container would be unfiltered. Docker disables IPv6 on user-defined bridge networks by default, limiting practical risk, but this is a defense-in-depth gap.
Finding (Low) — ICMP not blocked in container OUTPUT chain
containers/agent/setup-iptables.shdropstcpandudpbut noticmp/icmpv6. Raw ICMP packets (ping, unreachable messages) from the container are not filtered. While ICMP cannot carry application-layer payloads directly, ICMP tunneling tools (e.g.,ptunnel) can encapsulate TCP over ICMP. The host-level chain also does not explicitly drop ICMP:Recommendation: Add
iptables -A OUTPUT -p icmp -j DROPandip6tables -A OUTPUT -p icmpv6 -j DROPinsetup-iptables.shafter the TCP/UDP DROP rules (or use a policy drop on the OUTPUT chain).Container Security Assessment
Capabilities: partially hardened, with a necessary window.
The agent container is granted
SYS_CHROOTandSYS_ADMINfor startup operations, then drops them viacapshbefore executing user code (containers/agent/entrypoint.sh:307,src/docker-manager.ts:1012). NET_ADMIN is deliberately withheld from the agent; a separate init container (awf-iptables-init) handles iptables setup via shared network namespace.The
ptrace/process_vm_readv/process_vm_writevsyscalls are explicitly blocked in the seccomp profile atcontainers/agent/seccomp-profile.json.Finding (Medium) — AppArmor disabled for agent container
The rationale (procfs mounting for .NET CLR) is documented, but
apparmor:unconfinedremoves Docker's default AppArmor policy, which normally blocks:/proc/sysrq-trigger,/proc/kcoreCombined with
SYS_ADMINbeing temporarily available during startup and seccomp allowingmount/unshare/setns, this creates an elevated container escape window.Finding (Medium) —
open_by_handle_atin seccomp allowlistThis syscall was exploited in CVE-2014-5155 ("Shocker" container escape), allowing processes to open host filesystem files by inode handle even when path-based access is restricted. When
SYS_ADMINis held (startup window) AND AppArmor is unconfined,open_by_handle_atcan open inodes on any mounted filesystem. Modern kernel mitigations (fsopen, mount namespaces) reduce but don't eliminate this risk. Recommendation: explicitly denyopen_by_handle_atin seccomp (add to SCMP_ACT_ERRNO block alongside ptrace).Seccomp:
unshare,mount,setnsallowedInput Validation Assessment
Shell escaping is correct.
src/cli.ts:862–876:Single-quote wrapping with escaped inner single-quotes is safe against shell injection.
UID/GID validation is present.
containers/agent/entrypoint.sh:10–29validates that AWF_USER_UID/GID are numeric and non-zero (prevents root mapping):setup-iptables.sh: no ip6tables OUTPUT DROP;host-iptables.ts: no ip6tables DOCKER-USER insertionopen_by_handle_at+ SYS_ADMIN window + AppArmor unconfinedseccomp-profile.jsonallowsopen_by_handle_at;docker-manager.ts:1028apparmor:unconfinedsetup-iptables.sh: only drops tcp/udp; no icmp DROP rulesrc/dlp.ts;--enable-dlpnot default;src/redact-secrets.tsonly covers command stringssrc/host-iptables.ts:365–373:minPort:maxPort=10000:10004(contiguous range includes 10003)squid-config.tsDANGEROUS_PORTS includes 5984,6984,8086,8088,9200,9300;setup-iptables.shdoes not--enable-host-accesssetup-iptables.sh:170–210: host gateway and network gateway bypass Squid for ports 80/443src/squid-config.ts:read_timeout 30 minutes,connect_timeout 30s— very long timeouts🎯 Attack Surface Map
--allow-domainssrc/cli.ts:1318validateDomainOrPattern(), ReDoS-safe wildcards--env/-esrc/docker-manager.ts:373--env-allcopies entireprocess.envminus exclusions--allow-host-portssrc/squid-config.ts:460containers/agent/setup-iptables.shsrc/squid-config.ts:240containers/api-proxy/server.js:28containers/agent/entrypoint.sh:303containers/agent/seccomp-profile.jsonopen_by_handle_atallowed;unshare/mount/setnsallowedsrc/docker-manager.ts:850📋 Evidence Collection
IPv6 container OUTPUT chain – missing DROP rules
AppArmor disabled in docker-manager.ts
open_by_handle_at in seccomp allowlist
API proxy port range (10000:10004 includes 10003)
Dangerous ports mismatch
All moderate — only affect dev/docs tooling, not runtime security.
✅ Recommendations
🔴 Medium Priority
M1. Add IPv6 DROP rules in container OUTPUT chain (
containers/agent/setup-iptables.sh)Add after the existing TCP/UDP DROP rules:
Also insert
CHAIN_NAME_V6intoip6tables DOCKER-USERinsrc/host-iptables.tsfor host-level coverage.M2. Deny
open_by_handle_atin seccomp (containers/agent/seccomp-profile.json)Move
open_by_handle_atfrom the ALLOW block to the explicit ERRNO block (alongside ptrace):{ "names": ["open_by_handle_at", "name_to_handle_at"], "action": "SCMP_ACT_ERRNO", "errnoRet": 1, "comment": "Block file-handle syscalls used in Shocker-style container escapes (CVE-2014-5155)" }Verify that no agent use case requires this syscall before applying.
🟡 Low Priority
L1. Block ICMP in container OUTPUT (
containers/agent/setup-iptables.sh)Add before the final TCP/UDP DROP rules. This prevents ICMP tunneling and reduces the covert channel surface.
L2. Enable DLP by default for sensitive deployments
Consider making
--enable-dlpdefault-on for CI/CD environments where credential leakage is a high-risk scenario. The current opt-in model relies on operators knowing to enable it.L3. Fix API proxy iptables port range (
src/host-iptables.ts:365–373)Replace contiguous range with discrete multiport rules:
L4. Sync dangerous ports lists (
containers/agent/setup-iptables.sh)Add ports 5984, 6984, 8086, 8088, 9200, 9300 to the DANGEROUS_PORTS array in
setup-iptables.shto matchsquid-config.ts. Currently these are only blocked by the final OUTPUT DROP rule rather than the explicit RETURN-then-DROP path.🟢 Informational
I1. Consider image digest pinning — GHCR images are pulled by tag (
latestor version). Pinning to SHA256 digest would prevent tag mutation attacks.I2. Document AppArmor trade-off — The reason for
apparmor:unconfined(procfs mount for .NET CLR) is documented in code comments but could benefit from a dedicated security decision record.📈 Security Metrics
Beta Was this translation helpful? Give feedback.
All reactions