Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 17, 2026

Switches seccomp profile from allowlist-with-denies (SCMP_ACT_ALLOW default) to deny-by-default (SCMP_ACT_ERRNO default), reducing attack surface by blocking unknown/new syscalls automatically.

Changes

Seccomp Profile (containers/agent/seccomp-profile.json)

  • Changed defaultAction from SCMP_ACT_ALLOW to SCMP_ACT_ERRNO
  • Added explicit allowlist of ~350 syscalls required for Node.js, curl, git, npm (based on Docker's default profile)
  • Organized denied syscalls into documented categories with security rationale:
    • Process inspection (ptrace, process_vm_*)
    • Kernel execution (kexec_load, reboot)
    • Kernel modules (init_module, finit_module, delete_module)
    • Mount operations (mount, umount, pivot_root)
    • Namespace manipulation (unshare, setns)
    • BPF/perf (bpf, perf_event_open)
    • Keyring (add_key, request_key, keyctl)
    • Raw I/O (ioperm, iopl)
    • Chroot

Tests (src/seccomp-validation.test.ts)

  • 23 new tests verifying profile structure, allowed syscall categories, and explicitly blocked syscalls

Documentation

  • docs/architecture.md: Added "Container Security Hardening" section
  • AGENTS.md: Updated agent container description with seccomp/capability info

Profile Structure

{
  "defaultAction": "SCMP_ACT_ERRNO",
  "defaultErrnoRet": 1,
  "syscalls": [
    {
      "names": ["read", "write", "open", "..."],
      "action": "SCMP_ACT_ALLOW",
      "comment": "Allow syscalls required for normal container operation"
    },
    {
      "names": ["ptrace", "process_vm_readv", "process_vm_writev"],
      "action": "SCMP_ACT_ERRNO",
      "errnoRet": 1,
      "comment": "Explicitly deny: Process inspection/modification - container escape vector"
    }
  ]
}
Original prompt

This section details on the original issue you should resolve

<issue_title>[plan] harden seccomp profile with deny-by-default approach</issue_title>
<issue_description>## 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

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com>
Copilot AI changed the title [WIP] Switch seccomp profile to deny-by-default approach feat: harden seccomp profile with deny-by-default approach Jan 17, 2026
Copilot AI requested a review from Mossaka January 17, 2026 21:29
@Mossaka Mossaka marked this pull request as ready for review January 18, 2026 01:35
@github-actions
Copy link

✅ Coverage Check Passed

Overall Coverage

Metric Base PR Delta
Lines 77.88% 77.88% ➡️ +0.00%
Statements 77.94% 77.94% ➡️ +0.00%
Functions 77.29% 77.29% ➡️ +0.00%
Branches 71.00% 71.00% ➡️ +0.00%

Coverage comparison generated by scripts/ci/compare-coverage.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

2 participants