[Security Review] Daily Security Review — gh-aw-firewall Threat Model & Codebase Analysis (2026-04-11) #1903
Replies: 7 comments
-
|
🔮 The ancient spirits stir in the firewall vault.
|
Beta Was this translation helpful? Give feedback.
-
|
🔮 The ancient spirits stir, and the smoke-test oracle has passed this threshold.
|
Beta Was this translation helpful? Give feedback.
-
|
🔮 The ancient spirits stir, and the oracle records this passage.
|
Beta Was this translation helpful? Give feedback.
-
|
🔮 The ancient spirits stir in thread #1903.
|
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 halls. The smoke-test seer has walked this thread, read the omens, and marked the paths of signal and shadow. May your guards stay sharp and your egress remain true.
|
Beta Was this translation helpful? Give feedback.
-
|
This discussion was automatically closed because it expired on 2026-04-18T13:09:47.836Z.
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
📊 Executive Summary
This review covers a deep, evidence-based security analysis of the
gh-aw-firewallcodebase conducted on 2026-04-11. The overall security posture is strong for its threat model (containing agentic LLM workflows). The architecture shows defence-in-depth layering: L3/L4 iptables, L7 Squid proxy, capability dropping, seccomp filtering, and UID isolation. Five security findings were identified — one high severity, three medium, and several low/informational items. No critical exploitable paths were discovered.🔍 Findings from Firewall Escape Test (Secret Digger Workflow)
The escape-test summary file at
/tmp/gh-aw/escape-test-summary.txtcontained the conclusion log of the "Secret Digger (Copilot)" workflow run (2026-04-11T03:25). Key outcome signals:The workflow concluded
successwithnoopoutputs — meaning no secrets were exfiltrated or discovered by the agent during that run. No injection or bypass was recorded. This is consistent with the firewall functioning correctly.🛡️ Architecture Security Analysis
Network Security Assessment
Evidence gathered:
The entire host
/tmpis mounted read-write into the chroot. In chroot mode, the entrypoint writes temporary script files to/host/tmp/awf-cmd-$$.sh. If two concurrent AWF sessions share the same host, their/tmpis visible to both agents. A malicious or compromised agent could read script files from another session, or race-condition write to another session's script path if it could predict the PID ($$). Shell PID values are typically sequential and predictable.Weakness — [MEDIUM] ICMP not explicitly logged or blocked at L4:
ICMP is blocked by the default DROP/REJECT rules but is not explicitly logged with a
[FW_BLOCKED_ICMP]prefix. This makes it harder to distinguish ICMP egress attempts in audit logs from normal blocked traffic.Container Security Assessment
Evidence gathered:
While the SYS_ADMIN capability is dropped before user code executes, the AppArmor profile is disabled for the entire container lifetime, not just the procfs-mount window. This means:
A more targeted mitigation would be a custom AppArmor profile that explicitly permits
mount -t procwhile denying other dangerous operations, or usingaa-execwith a temporary profile switch.[MEDIUM] Non-chroot mode drops no capabilities from bounding set:
In non-chroot mode (
AWF_CHROOT_ENABLED != true):In non-chroot mode,
capsh --drop=...is never called, so the bounding set equals what Docker configured. Theno-new-privileges:truesecurity_opt prevents gaining new caps via SUID, but does not shrink the existing bounding set further. An agent code path that callssetuid(0)or uses ambient capabilities would operate within the granted set.gosucorrectly drops to awfuser, but the bounding set is not tightened per-process.Strengths:
no-new-privileges:trueapplied to agent container (prevents SUID escalation)ptrace,process_vm_readv/writev,kexec_load,reboot,init_module,pivot_root,keyctl, etc.pids_limit: 1000limits fork bombs/proc/self/environDomain Validation Assessment
Evidence gathered:
Strengths:
[\s\0"';#]`^...$preventing catastrophic backtracking (ReDoS) via[a-zA-Z0-9.-]*character class instead of.*validateDomainOrPattern()[LOW] Backslash exclusion from
SQUID_DANGEROUS_CHARS:The comment in
domain-patterns.tsexplains that backslash is excluded because--allow-urlspatterns use\for regex escaping. This is technically correct but creates a subtle difference: domains vs URL patterns have different validation paths. A future code change that inadvertently passes a URL pattern value through the domain-only path could introduce a Squid config injection vector.Input Validation Assessment
Evidence gathered:
Strengths:
escapeShellArg(single-quote wrapping)src/docker-manager.ts:56,containers/agent/entrypoint.sh:15-32)[INFORMATIONAL] Single-argument pass-through is by-design but high trust:
✅ Recommendations
🔴 High Priority
H1 — Isolate
/tmpbetween concurrent AWF sessionssrc/docker-manager.ts:919/tmp:/host/tmp:rwcreates cross-session data leakage risk;/tmp/awf-cmd-$$.shfilenames are PID-predictable on busy hosts./tmp/awf-<timestamp>/agent-tmp) and mount that as/host/tmpinstead of the full host/tmp. Or, use a named Docker volume for each session's tmp rather than a host bind-mount.🟠 Medium Priority
M1 — Provide a custom AppArmor profile instead of
apparmor:unconfinedsrc/docker-manager.ts:1322mount -t procduring entrypoint initptrace, direct device access, and network socket creation to sensitive device files after initaa-execM2 — Drop additional capabilities in non-chroot mode via
capshcontainers/agent/entrypoint.sh:363-376CAPS_TO_DROP=""in non-chroot mode meanscapshis never invoked; bounding set is not tightened beyond what Docker'scap_dropconfig sets.capsh --drop=cap_sys_chroot,cap_sys_admin,cap_ipc_lock,cap_sys_rawio,cap_sys_boot -- -c "exec gosu awfuser ..."to minimise the bounding set before the agent process starts.M3 — Add explicit ICMP audit logging
containers/agent/setup-iptables.shiptables -A OUTPUT -p icmp -m limit --limit 5/min \ -j LOG --log-prefix "[FW_BLOCKED_ICMP] " --log-level 4 iptables -A OUTPUT -p icmp -j DROP🟡 Low Priority
L1 — Restrict
unsharesyscall in seccomp profileunshareis allowed in the current seccomp profile. While dangerous use requires capabilities that are dropped, explicitly denying user/network namespace creation viaunshare(CLONE_NEWUSER | CLONE_NEWNET)reduces attack surface. Consider addingclone_flagsargs restriction or blockingunshareat seccomp level.L2 — Consider session-scoped tmpfs for workDir instead of host-directory-based temp files
agentCommandand other sensitive content pass through/tmp/awf-cmd-$$.shon the host filesystem. Using an in-container tmpfs volume for sensitive ephemeral files would prevent host-side forensic recovery.L3 — Pin
execato v9+ (current pin is v5.1.1 inpackage.json)package.jsonspecifies"execa": "^5.1.1". v5 uses CommonJS; v9 uses pure ESM with improved security posture. An upgrade would keep the dependency current and aligned with other ESM-only deps.L4 — Document the
backslashexclusion inSQUID_DANGEROUS_CHARSwith a regression testdomain-patterns.ts:22-26explains why backslash is excluded from domain char filtering. This subtle invariant should be protected by an explicit test covering the domain vs URL-pattern validation split.L5 — Log the
open_by_handle_atsyscall invocationsopen_by_handle_atis allowed in the seccomp profile and has historically been used in Docker escape exploits ("Shocker attack"). While capability restrictions should mitigate this, adding a seccomp LOG action (or denying it) would improve auditability.📈 Security Metrics
Review conducted by: GitHub Copilot CLI (claude-sonnet-4.6) | Workflow run: 24283037968 | Date: 2026-04-11
Beta Was this translation helpful? Give feedback.
All reactions