A compromised process can do whatever the kernel lets it do, so the last reliable place to contain it is the boundary between that process and the kernel. D3-SCF System Call Filtering is the MITRE D3FEND countermeasure for that boundary. D3FEND defines it as "Controlling access to local computer system resources with kernel-level capabilities." It sits in the Isolate tactic as a child of Access Mediation, filters the System Call artefact and isolates the Process artefact. D3FEND also lists "Mandatory Access Control" and "System Call Mediation" as alternative labels, and notes it was previously known as D3-MAC. This card explains the mechanisms D3FEND groups under the name, the ATT&CK techniques it relates to, where it is implemented, how to verify a profile is really enforcing, and the limits. It is written for platform, container and endpoint engineers. For the parent technique, see the MITRE D3FEND Access Mediation Implementation Guide.
Key takeaways
- D3-SCF covers two families of control. System call filters such as seccomp decide which kernel calls a process may make; mandatory access control systems such as SELinux, AppArmor and Windows Mandatory Integrity Control decide which objects a process may touch. D3FEND groups both under one technique.
- Policy is set centrally, not by resource owners. D3FEND's knowledge base stresses the mandatory, non-discretionary model: a local user cannot grant away what the policy denies.
- Defaults are often permissive. In Kubernetes, unless seccomp defaulting is enabled on the kubelet, a pod with no profile runs Unconfined, and privileged containers always run Unconfined.
- Start in log mode, then enforce. seccomp LOG actions, AppArmor complain mode and SELinux permissive mode exist to build a profile from real behaviour before it blocks anything.
- A loaded profile is not proof. Verify enforcement per running process, and test that a denied call is actually denied.
D3-SCF at a glance
| Field | D3-SCF System Call Filtering |
|---|---|
| D3FEND ID | D3-SCF (previously D3-MAC) |
| Tactic | Isolate |
| Parent technique | Access Mediation (siblings include Credential Transmission Scoping, IO Port Restriction, Network Access Mediation, Network Resource Access Mediation, Operating Mode Restriction, OT Variable Access Restriction and Physical Access Mediation) |
| Child technique | Local File Access Mediation (D3-LFAM) |
| Digital artefacts | System Call (filters), Process (isolates) |
| Implementations D3FEND names | Linux control groups, SELinux, AppArmor, Windows Mandatory Integrity Control |
| D3FEND references | Symantec analysis of the Windows Vista security model; NeuVector patent on transparent network security for application containers; overview of the seccomp sandbox |
| Related ATT&CK mitigations (D3FEND links) | M1018 User Account Management, M1025 Privileged Process Integrity, M1042 Disable or Remove Feature or Program, M1044 Restrict Library Loading, M1048 Application Isolation and Sandboxing, M1052 User Account Control |
How it works
D3FEND's knowledge base describes the model as subjects (the processes or users asking) and objects (the resources asked for), with rules set by a security authority. It names two common implementations: security label access control, where every object carries a label and the kernel compares the subject's security context with it (the SELinux model, described as the most flexible and the most complex to deploy), and file path level control, where rules are written against paths and attached to programs (the AppArmor model, with less management overhead). Its considerations warn that label-based rule sets are hard to verify and maintain, and that the access model needs initial planning and continuous monitoring.
| Mechanism | What it decides | Policy unit | Learning mode |
|---|---|---|---|
| AppArmor | Which paths, capabilities and network access a program has | Per-program profile, path based | Complain mode |
| Linux seccomp (filter mode) | Which system calls, and which argument values, a process may make | BPF filter installed by the process or its launcher, inherited by children | LOG action, subject to the actions_logged sysctl |
| SELinux | Which labelled objects a labelled subject may access and how | System-wide type enforcement policy | Permissive mode (global or per domain) |
| Windows Mandatory Integrity Control | Whether a process at one integrity level may write (and optionally read or execute) objects at a higher level | Integrity levels (low, medium, high, system) in tokens and object labels | None as such; levels are assigned by the system |
The Linux kernel documentation is explicit that seccomp "is not a sandbox" on its own: it reduces the kernel attack surface and is meant to be combined with other hardening or a Linux Security Module. Three details from the kernel documentation matter in practice. First, installing a filter needs no_new_privs or CAP_SYS_ADMIN, so a filter cannot be used to subvert a more privileged program. Second, when several filters apply, the most restrictive action wins (KILL_PROCESS down to ALLOW). Third, the most common mistake is matching system call numbers without checking the architecture field, which allows bypass through an alternate calling convention. For deeper treatment of each mechanism, see the seccomp Guide, SELinux Guide, AppArmor Guide and Reference Monitors and Mandatory Access Control Guide.
On Windows, Mandatory Integrity Control is evaluated before the object's DACL. By default every object carries a no-write-up policy, objects without a label are treated as medium, standard users run at medium and elevated users at high, and a process never runs above the integrity level of its executable. That is why a low-integrity process cannot alter user data even when the DACL would allow it.
ATT&CK techniques D3FEND relates to D3-SCF
Relationship type: inferred only. D3FEND derives these relationships through shared digital artefacts and labels them inferred and experimental (checked November 2026). The table lists the techniques that act directly on the System Call or Process artefacts. Every ID was checked against ATT&CK v20. The last column is NHI Mgmt Group's assessment, not D3FEND content.
| ATT&CK ID | Technique | D3FEND relation (via artefact) | What filtering changes (NHI Mgmt Group assessment) |
|---|---|---|---|
| T1055.001, T1055.003, T1055.005 | Process Injection: Dynamic-link Library Injection, Thread Execution Hijacking, Thread Local Storage | Invokes System Call | Partial: integrity levels and protected process rules stop lower-integrity processes opening higher ones; same-level injection needs other controls |
| T1055.008, T1055.014 | Ptrace System Calls, VDSO Hijacking | Invokes System Call | Strong on Linux where the profile denies ptrace and the related calls; the kernel docs warn seccomp sandboxes must not allow ptrace |
| T1106 | Native API | Invokes System Call | Partial: a filter limits which calls succeed, not whether native APIs are used |
| T1548.004 | Elevated Execution with Prompt | Invokes System Call | Partial: confines what the elevated helper can reach |
| T1003.001, T1003.002, T1003.004 | OS Credential Dumping: LSASS Memory, Security Account Manager, LSA Secrets | Accesses or may access Process | Partial: process isolation and protected processes raise the bar; an attacker at system level is above most of these controls (see Credential Guard and VBS) |
| T1505.003 | Web Shell | Produces Process | Strong where the web server's profile denies spawning shells and writing to web roots |
| T1546.007 | Netsh Helper DLL | Produces Process | Partial |
| T1553.006 | Code Signing Policy Modification | May create Process | Partial: depends on whether the policy protects the boot and signing configuration |
| T1564.011 | Ignore Process Interrupts | Creates Process | Minimal |
The D3FEND technique page also shows a wider inferred set that it derives through sub-artefacts, across discovery, persistence (for example T1053.005 Scheduled Task, T1546.009 AppCert DLLs, T1546.010 AppInit DLLs), privilege escalation (T1548.002 Bypass User Account Control, T1134.004 Parent PID Spoofing, further T1055 sub-techniques), stealth (System Binary Proxy Execution sub-techniques such as T1218.011 Rundll32) and credential access (T1555.003 Credentials from Web Browsers). One entry there uses an ID that ATT&CK has since revoked; its v20 successor is T1685 Disable or Modify Tools. The ICS matrix entry is T0834 Native API. See the T1055 Process Injection Defensive Guide, T1003 OS Credential Dumping and MITRE ATT&CK T1106 Native API.
Where it is implemented
| Layer | Control and setting | Default behaviour to know |
|---|---|---|
| Container engines | Default seccomp profile; custom profile via --security-opt seccomp=profile.json | Docker's default profile denies by default (SCMP_ACT_ERRNO) and allows a list, disabling around 44 system calls out of 300 or more, such as add_key, bpf and clock_settime |
| Kubernetes | securityContext.seccompProfile with type RuntimeDefault or Localhost (localhostProfile path); kubelet --seccomp-default | Without seccomp defaulting the effective mode is Unconfined; privileged containers always run Unconfined. The Restricted Pod Security Standard requires an explicit RuntimeDefault or Localhost profile |
| Linux hosts and services | SELinux enforcing mode with targeted policy; AppArmor profiles in enforce mode; systemd unit sandboxing options that apply seccomp filters to a service | Distribution dependent: some ship SELinux enforcing, others AppArmor with profiles for selected programs only |
| Windows endpoints | Mandatory Integrity Control, User Account Control, AppContainer for sandboxed apps | No-write-up on every object by default; standard users at medium, elevated at high |
| Application sandboxes | Browsers, document viewers and AI code execution sandboxes that install their own filters | Coverage depends on the vendor; confirm in the product's documentation |
Workloads that run AI agent tools or untrusted code are a natural fit: the agent's runtime identity can be well scoped in the cloud and still have unrestricted kernel access on the host. See the AI Agent Sandboxing and Code Execution Guide and the Container Runtime Security Guide.
Implementation steps
- Turn on the safe defaults first. Enforce the container runtime default seccomp profile everywhere (in Kubernetes, enable seccomp defaulting on nodes or set RuntimeDefault in pod specs) and confirm the host's SELinux or AppArmor is in enforcing mode.
- Find what runs unconfined. List privileged containers, pods with Unconfined profiles, SELinux permissive domains and programs without an AppArmor profile.
- Profile high-risk workloads. For internet-facing services and code execution sandboxes, record real behaviour with a logging profile (seccomp LOG, AppArmor complain, SELinux permissive for one domain) under representative load.
- Build an allowlist and enforce in rings. Convert the observed set into a deny-by-default profile, check the architecture field in custom seccomp filters, then enforce on a canary before the fleet.
- Admission control. Reject new workloads that ask for Unconfined or privileged mode without an approved exception; see the Kubernetes Admission Control Guide.
- Keep rollback simple. Rollback is switching one workload back to the runtime default or to log mode, not disabling the mechanism on the host.
How to verify it works
- Per-process status: on Linux, the Seccomp field in /proc/<pid>/status shows 2 for filter mode; check it for the main process of each critical workload. Check the SELinux context or AppArmor profile of the same process and that the mode is enforce.
- Denial test: in a test environment, run a harmless call that the profile should deny (for example, changing the system clock from inside a container) and confirm it fails with the expected error.
- Log review: collect seccomp, SELinux and AppArmor denials through auditd or the journal; see the Linux Logging and auditd for Defenders Guide. Unexpected denials in production mean either an attack or an incomplete profile, and both need triage.
- Cluster audit: query workloads for seccompProfile type and privileged flags, and compare with the exception list.
| Metric | What it shows | Example target (illustrative, not a standard) |
|---|---|---|
| Share of running containers with a RuntimeDefault or Localhost seccomp profile | Real seccomp coverage | 100% outside approved exceptions |
| Privileged or Unconfined workloads with an owner and expiry | Size of the bypass surface | Falling; none without an owner |
| Hosts with SELinux or AppArmor in enforcing mode | Host mandatory access control coverage | All production hosts |
| Permissive or complain-mode domains older than the profiling window | Profiles left in learning mode | Zero |
| Denial events triaged within the SOC's normal window | Whether denials are watched | All high-risk workloads |
For behaviour-based detection that complements filtering, see D3-SCA System Call Analysis.
Limits, bypasses and failure patterns
- Profiles that allow everything: a profile built from an over-broad learning run, or copied from a permissive template, gives the appearance of control with none of the effect.
- Kernel vulnerabilities: allowed system calls still reach kernel code. A kernel flaw reachable through an allowed call defeats the filter, which is why the kernel docs call seccomp a building block rather than a sandbox. Patch kernels and keep the allowed set small.
- Privileged escape hatches: privileged containers, CAP_SYS_ADMIN and host namespace sharing undo most of the isolation. See the Linux Capabilities Guide.
- Permissive mode left on: SELinux permissive or AppArmor complain, set during troubleshooting, and never reverted.
- Architecture gaps in custom filters: filters that check only syscall numbers can be bypassed through an alternate ABI, as the kernel documentation warns.
- Same-level attacks on Windows: integrity levels stop writes up, not attacks between processes at the same level or from system level.
Framework mapping
| Framework | Reference | Relationship to D3-SCF |
|---|---|---|
| MITRE ATT&CK | M1048, M1025, M1044, M1042, M1052, M1018 | The mitigations D3FEND links to D3-SCF |
| NIST SP 800-53 Rev 5 | AC-3(3) Mandatory Access Control; SC-39 Process Isolation; CM-7 Least Functionality | NHI Mgmt Group mapping: the control objectives these mechanisms implement |
| NIST CSF 2.0 | PR.PS-01 | Configuration management practices are established and applied |
Practitioner checklist
- Enforce the container runtime default seccomp profile on every node and workload.
- Keep SELinux or AppArmor enforcing on all production hosts; track any permissive domain with an owner and end date.
- Block privileged and Unconfined workloads at admission unless an approved exception exists.
- Build custom deny-by-default profiles for internet-facing services and code execution sandboxes from logged behaviour.
- Check the architecture field in every custom seccomp filter.
- Verify enforcement per running process, not per policy file.
- Send seccomp, SELinux and AppArmor denials to the SOC and triage them.
- Patch kernels promptly; filtering reduces but does not remove kernel exposure.
Standards and references
- MITRE D3FEND: System Call Filtering (D3-SCF)
- Linux kernel documentation: Seccomp BPF (SECure COMPuting with filters)
- Kubernetes: Restrict a Container's Syscalls with seccomp
- Docker: Seccomp security profiles for Docker
- Microsoft: Mandatory Integrity Control
- MITRE ATT&CK: M1048 Application Isolation and Sandboxing
- NIST: SP 800-53 Rev 5, Security and Privacy Controls
Related NHI Mgmt Group resources: MITRE D3FEND Access Mediation Implementation Guide · seccomp Guide · M1048 Application Isolation and Sandboxing · MITRE D3FEND Guide