Skip to content

Instantly share code, notes, and snippets.

@josephgimenez
Created March 1, 2026 20:20
Show Gist options
  • Select an option

  • Save josephgimenez/fcc6a73cb6f93e713f49eb0588a9bbd0 to your computer and use it in GitHub Desktop.

Select an option

Save josephgimenez/fcc6a73cb6f93e713f49eb0588a9bbd0 to your computer and use it in GitHub Desktop.

Linux: seccomp User Notification as the Equivalent to Endpoint Security

Linux already has the exact primitive we need — no special entitlements required.

SECCOMP_RET_USER_NOTIF (Linux 5.0+)

seccomp user notification allows a supervisor process to intercept syscalls from a sandboxed child and make allow/deny decisions — the same model as macOS Endpoint Security, but available to any unprivileged process.

Child (sandboxed)                    Kernel                     Supervisor (nono)
      │                                │                              │
      ├── openat("/home/.aws/config") ►│                              │
      │                                ├── SECCOMP_RET_USER_NOTIF ───►│
      │                                │   (syscall blocked)          │
      │                                │                              ├── Check policy
      │                                │                              ├── Prompt user?
      │                                │                              ├── openat() on behalf of child
      │                                │◄── NOTIF_ADDFD + NOTIF_SEND ─┤
      │◄── returns fd ─────────────────│                              │

How It Works

  1. Install filter: The child installs a seccomp-bpf filter with SECCOMP_FILTER_FLAG_NEW_LISTENER, which returns a notification fd to the supervisor
  2. Intercept: When the child hits a filtered syscall (e.g., openat), the kernel blocks it and delivers a notification to the supervisor via SECCOMP_IOCTL_NOTIF_RECV
  3. Decide: The supervisor inspects the syscall args (path, flags, etc.), checks policy, optionally prompts the user
  4. Respond: Three options:
    • Allow: Supervisor calls openat() itself and injects the resulting fd into the child's fd table via SECCOMP_IOCTL_NOTIF_ADDFD (Linux 5.9+) with SECCOMP_ADDFD_FLAG_SEND for atomic fd injection + response
    • Deny: Supervisor responds with an error code (e.g., -EPERM)
    • Pass through: Supervisor responds with SECCOMP_USER_NOTIF_FLAG_CONTINUE to let the syscall proceed normally (Linux 5.5+)

Why This Is Better Than Landlock Alone

nono currently uses Landlock on Linux, which (like Seatbelt on macOS) is static and allow-list-only:

Landlock (current) seccomp user notification
Permission model Static allow-list, set once Dynamic per-syscall decisions
Deny within allow Not possible (no deny semantics) Supervisor can deny any individual operation
Interactive retry Not possible (no notification) Supervisor can prompt user, then allow/deny
Dynamic expansion Not possible after apply Supervisor makes real-time decisions
exec() survival Permissions survive exec Notification fd is inherited; filter survives exec
Entitlements None needed None needed
Kernel version 5.13+ 5.0+ (NOTIF_ADDFD: 5.9+)

What nono Would Look Like

nono (supervisor)
  │
  ├── fork()
  │     │
  │     Child:
  │       ├── seccomp(SET_MODE_FILTER, FLAG_NEW_LISTENER, bpf_filter)
  │       │     → returns notify_fd (inherited by parent via fork ordering,
  │       │       or passed back via pre-arranged pipe)
  │       ├── Landlock (for the static allow-list baseline)
  │       └── exec(claude)
  │
  └── Supervisor loop:
        ├── SECCOMP_IOCTL_NOTIF_RECV(notify_fd)
        ├── Read path from /proc/<pid>/mem (seccomp provides pointer + pid)
        ├── Check against policy (deny_credentials, never_grant, etc.)
        ├── If denied → prompt user → allow/deny
        └── SECCOMP_IOCTL_NOTIF_SEND (with ADDFD if emulating open)

Hybrid Approach: Landlock + seccomp

The ideal architecture layers both:

  • Landlock provides the static baseline sandbox (allow project dir, system libs, etc.) — fast, no per-operation overhead for allowed paths
  • seccomp user notification intercepts operations on sensitive paths (credentials, SSH keys, etc.) — dynamic, interactive, per-operation decisions

This is analogous to what we want on macOS: Seatbelt for the baseline + Endpoint Security for dynamic decisions. The difference is that on Linux, both primitives are available without entitlements.

Key Advantage Over macOS

No entitlement, no Apple approval, no provisioning profile, no app bundle requirement. SECCOMP_RET_USER_NOTIF is available to any unprivileged process on any Linux 5.0+ kernel. This makes it immediately usable for nono without any distribution gatekeeping.

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