Skip to content

AWF agent seccomp profile allows name_to_handle_at and open_by_handle_at — deviates from Docker default, single-layer Shocker de [Content truncated due to length] #2265

@szabta89

Description

@szabta89

Summary

The AWF agent container seccomp profile (containers/agent/seccomp-profile.json) includes name_to_handle_at (NR 303) and open_by_handle_at (NR 304) in the SCMP_ACT_ALLOW list. Docker's default seccomp profile explicitly blocks both syscalls to prevent the Shocker container-escape attack (CVE-2014-9357), where an attacker obtains a raw inode handle via name_to_handle_at and then opens it in a privileged context using open_by_handle_at to escape the container namespace. The current gh-aw-firewall configuration stops this chain only at the second step — via the capability bounding set (CAP_DAC_READ_SEARCH absent, NoNewPrivs=1) — rather than at both the seccomp and capability layers as Docker's recommended hardening prescribes.

Affected Area

Container isolation / kernel attack surface — AWF agent container seccomp profile (containers/agent/seccomp-profile.json) and associated tests (src/seccomp-profile.test.ts).

Reproduction Outline

  1. Run a workflow inside the AWF agent container (custom seccomp profile active, seccomp=unconfined not set).
  2. Call name_to_handle_at(AT_FDCWD, "/etc/passwd", ...) via syscall — returns ret=0 with a valid inode handle and mnt_id for the ext4 bind-mounted path.
  3. Attempt open_by_handle_at(mount_fd, handle, O_RDONLY) — returns ret=-1, errno=1 (EPERM) due to missing CAP_DAC_READ_SEARCH, not due to a seccomp block.
  4. Observe that step 2 is not blocked by seccomp (confirmed with EFAULT on null-ptr probes: errno=14, not errno=1), while Docker's reference profile would block it with ENOSYS.
  5. Verify that containers/agent/seccomp-profile.json lists both NR 303 and NR 304 in the single SCMP_ACT_ALLOW rule (lines ~192 and ~196) with no corresponding deny entry.

Observed Behavior

name_to_handle_at completes successfully, returning valid inode handles for host-bind-mounted ext4 paths (/etc/passwd, /home/runner/work, /bin/sh). The Shocker escape chain is halted only at open_by_handle_at by the capability bounding set. src/seccomp-profile.test.ts does not assert that NR 303 or NR 304 are blocked.

Expected Behavior

Both name_to_handle_at and open_by_handle_at should be denied at the seccomp layer (returned as SCMP_ACT_ERRNO), matching Docker's default hardening posture and providing two independent defense layers against the Shocker escape chain.

Security Relevance

The Shocker attack (CVE-2014-9357) uses name_to_handle_at + open_by_handle_at to escape container namespaces by obtaining a host-filesystem handle. While the capability bounding set currently prevents exploitation, relying on a single control means that any future configuration drift — capability grant, privilege escalation within the container, or a Linux kernel capability-check bypass — would leave the escape path fully open. Docker's explicit rationale for blocking these two syscalls is precisely this attack scenario.

Additional Context

This deviation from Docker's default seccomp policy is not documented in gh-aw's architecture or container isolation pages (introduction/overview/, introduction/architecture/). If allowing these syscalls is an intentional design choice (e.g., for legitimate filesystem handle use cases in workflows), that assumption should be documented explicitly alongside the capability-based mitigation that compensates for the missing seccomp block.

Suggested fix: Move name_to_handle_at (NR 303) and open_by_handle_at (NR 304) from the SCMP_ACT_ALLOW list to the SCMP_ACT_ERRNO deny list in containers/agent/seccomp-profile.json, and add assertions to src/seccomp-profile.test.ts confirming both are blocked (consistent with existing tests for ptrace, kexec_load, init_module).

gh-aw version: v0.68.3

Original finding: https://github.com/githubnext/gh-aw-security/issues/2064

Generated by File Issue · ● 243.4K ·

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions