Skip to content

[plan] harden seccomp profile with deny-by-default approach #311

@github-actions

Description

@github-actions

Objective

Switch seccomp profile from allowlist-with-denies to denylist-with-allows (deny-by-default) for more restrictive security posture.

Context

Current state: containers/agent/seccomp-profile.json uses defaultAction: SCMP_ACT_ALLOW with specific syscalls denied.

Risk: New syscalls or overlooked dangerous syscalls remain accessible to container processes.

Risk level: 🟡 MEDIUM - Allowlist approach has larger attack surface

Trade-off: More restrictive profile requires careful testing to identify all syscalls needed by legitimate workloads.

Implementation Approach

Phase 1: Audit Required Syscalls

  1. Run test suite with strace to capture all syscalls used
  2. Run common workloads (git clone, npm install, curl, etc.) with strace
  3. Compile list of required syscalls for normal operation

Phase 2: Create Deny-by-Default Profile

  1. Change defaultAction to SCMP_ACT_ERRNO
  2. Add "action": "SCMP_ACT_ALLOW" section with required syscalls
  3. Keep existing dangerous syscall blocks for clarity

Phase 3: Testing and Validation

  1. Test all integration workflows with new profile
  2. Document any syscalls added and rationale
  3. Add test that verifies dangerous syscalls still blocked

Files to Modify

  • containers/agent/seccomp-profile.json - Restructure to deny-by-default
  • tests/security/seccomp-validation.test.ts - New test to verify profile
  • README.md - Document seccomp approach and syscall rationale
  • AGENTS.md - Update container security section

Example Structure

{
  "defaultAction": "SCMP_ACT_ERRNO",
  "architectures": ["SCMP_ARCH_X86_64", "SCMP_ARCH_X86", "SCMP_ARCH_AARCH64"],
  "syscalls": [
    {
      "names": [
        "read", "write", "open", "close", "stat", "fstat",
        "lseek", "mmap", "mprotect", "munmap", "brk",
        "rt_sigaction", "rt_sigprocmask", "ioctl", "access",
        "... (all required syscalls)"
      ],
      "action": "SCMP_ACT_ALLOW"
    },
    {
      "names": [
        "ptrace", "kexec_load", "mount", "pivot_root"
      ],
      "action": "SCMP_ACT_ERRNO",
      "comment": "Explicitly deny dangerous syscalls"
    }
  ]
}

Testing Strategy

  1. Run full test suite with new profile
  2. Test with different workloads:
    • curl to allowed domain
    • git clone from GitHub
    • npm install with dependencies
    • MCP server execution (stdio and HTTP)
  3. Verify dangerous syscalls blocked:
    • ptrace attempt returns EPERM
    • mount attempt returns EPERM
    • kexec_load attempt returns EPERM

Rollback Plan

If testing reveals too many legitimate syscalls needed:

  • Keep allowlist approach but add comprehensive documentation
  • Create issue to investigate alternative container runtime security (gVisor, Kata)

Acceptance Criteria

  • Seccomp profile uses defaultAction: SCMP_ACT_ERRNO
  • All allowed syscalls documented with rationale
  • All integration tests pass with new profile
  • Dangerous syscalls still explicitly denied
  • Performance impact measured (< 5% overhead acceptable)
  • Documentation explains security improvement
    Related to [plan] security improvements from threat model review #306

AI generated by Plan Command for discussion #302

Metadata

Metadata

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