yuzu

platform_security

What it doesSecure Boot and code-integrity enforcement posture (read-only)
Version1.0.0
KindCollector · read-only · gathered (crossplatform.platform_security.secure_boot, crossplatform.platform_security.code_integrity)
PlatformsWindows ✅ · macOS ✅ · Linux ✅
Actionscode_integrity (definition crossplatform.platform_security.code_integrity) · secure_boot (definition crossplatform.platform_security.secure_boot)
Securitysecurable Security · operation Read · risk Low · dispatch ReadOnly · approval gate None
Rolesexecute: endpoint-admin, endpoint-operator, security-admin · author: content-author

How it works

Two read-only actions report whether boot-time and code-signing protections are configured on: secure_boot (is Secure Boot enforced) and code_integrity (is the OS restricting what code may run). Each writes rows of the form <action>|<os>|<key>|<raw>|<state>. Neither takes parameters, so no request text reaches a path, a registry name or a command line. Linux reads a few efivarfs and securityfs files; Windows reads registry values; macOS reports secure_boot as unsupported and runs spctl --status and csrutil status for code_integrity. Every read is a value with a state, absent (the OS definitively says it is not there) or unreadable (the read failed), and a failed read never reads as absent. enabled, disabled and partial describe the protection, not the raw number. The Windows rows report configured policy, not proof of what is running.

flowchart LR
  OP["Operator or workflow"] --> SRV["Server, authz Security Read"]
  SRV -->|"gRPC over mTLS"| EX["platform_security execute: secure_boot or code_integrity"]
  EX --> WIN["Windows leg: RegQueryValueExW on the SecureBoot State, CI Policy, DeviceGuard and Lsa keys"]
  EX --> MAC["macOS leg: secure_boot writes an unsupported row, code_integrity runs spctl and csrutil with a 5 second deadline"]
  EX --> LIN["Linux leg: open and read of efivarfs SecureBoot and SetupMode, securityfs lsm and lockdown"]
  WIN & MAC & LIN --> ROWS["rows with raw value and state, status OK, CONSTRAINED or PERMISSION_DENIED, UNAVAILABLE for macOS secure_boot"]
  ROWS --> RS[("ResponseStore")] --> API["REST /api/responses"]

This plugin’s priority is asserted, not evidenced: it was built from a reading of a capability gap, and no capability-map requirement, parity gap, compliance control, roadmap item or named customer asks for it.

What is read

How absence is decided

A BIOS or CSM (legacy-BIOS compatibility) boot has no efivars, many kernels have no lockdown LSM (Linux Security Module) and a default Windows install has no DeviceGuard values. Each of these is an absent row that adds no reason token and leaves the status OK. The rule differs by OS, because a not-found can also mean the surface itself was never exposed.

What you can decide with it

QuestionAction and keyWindowsmacOSLinux
Is Secure Boot enforced?secure_bootUEFISecureBootEnabled: 1 enabled, 0 disabled; absent on a BIOS or CSM bootnot available (unsupported)secure_boot row: efivar data byte 1 enabled, 0 disabled
Is a Platform Key enrolled, or can any image load?secure_boot, key setup_modenot readnot availableenabled means User Mode (a Platform Key is enrolled); disabled means Setup Mode
Is the OS restricting kernel or code changes?code_integritydeviceguard.* (virtualization-based security and hypervisor-enforced code integrity, HVCI); lsa.LsaCfgFlags is Credential Guard (isolated credentials), not code or kernel protectiongatekeeper and siplockdown: none disabled, integrity partial, confidentiality enabled; lsm enabled when SELinux, AppArmor, Smack or TOMOYO is in the active list
Is Smart App Control on?code_integrityci_policy.VerifiedAndReputablePolicyState: 0 disabled, 1 enabled, 2 evaluationnot availablenot available

Diagrams

Linux read of one variable or file

flowchart TD
  A["open the efivar or securityfs file"] --> B{"open result"}
  B -->|"opened"| C["read, at most 4095 bytes"]
  C -->|"expected shape"| V["decode and map to a state"]
  C -->|"efivar not 4 + 1 bytes"| U1["unreadable, key:efivars:shape"]
  C -->|"4096 bytes or more"| U2["unreadable, key:errno_27 (file too large)"]
  B -->|"ENOENT"| D{"parent surface present?"}
  D -->|"surface missing"| U3["unreadable, key:errno_19"]
  D -->|"present, or no /sys/firmware/efi"| AB["absent, no token"]
  B -->|"EACCES or EPERM"| U4["unreadable, key:eacces, status PERMISSION_DENIED"]
  B -->|"other errno"| U5["unreadable, key:errno_n"]

“Surface missing” means securityfs is not mounted at /sys/kernel/security, or /sys/firmware/efi exists but /sys/firmware/efi/efivars is not efivarfs. A host with no /sys/firmware/efi takes the absent branch, and a container that hides that directory is indistinguishable from a BIOS boot, which is why caveat 1 exists.

macOS tool outcome

flowchart TD
  R["run spctl or csrutil with a 5 second deadline"] --> Q{"outcome"}
  Q -->|"could not start"| U1["unreadable, key:spawn_failed, eacces or errno_n"]
  Q -->|"deadline hit"| U2["unreadable, key:timeout"]
  Q -->|"output cut at the cap"| U3["unreadable, key:output_truncated"]
  Q -->|"ran"| P{"first line matches a known status?"}
  P -->|"yes, any exit code"| S["enabled, disabled or partial"]
  P -->|"no, exit 0"| M["unmodelled, raw text kept"]
  P -->|"no, non-zero exit"| U4["unreadable, key:exit_n or key:exit_signal"]

OS capability

ActionWindowsmacOSLinux
code_integrity✅ supported · rung 1 · HKLM\SYSTEM\CurrentControlSet\Control\CI\Policy, Control\DeviceGuard and Control\Lsa\LsaCfgFlags registry values✅ supported · rung 2 · spctl —status + csrutil status via run_bounded_subprocess✅ supported · rung 1 · securityfs reads of /sys/kernel/security/lsm and /sys/kernel/security/lockdown (errno-classified absent/unreadable)
secure_boot✅ supported · rung 1 · HKLM\SYSTEM\CurrentControlSet\Control\SecureBoot\State registry (UEFISecureBootEnabled)⛔ unsupported✅ supported · rung 1 · efivarfs reads of /sys/firmware/efi/efivars/SecureBoot-* and SetupMode-* (4-byte attributes + 1 data byte; errno-classified absent/unreadable)

Declared limits per leg (descriptor fallback text, verbatim):

Privileges and prerequisites

OSRuns asExtra grant neededMeasuredIf the read is refused
Windowsagent service account (LocalSystem today, #1442)None documented for this plugin (docs/agent-privilege-model.md); HKLM Control reads are not expected to need elevationNT AUTHORITY\SYSTEM on a bare-metal Windows 11 Pro host (10.0.26200), 2026-09-21: SecureBoot\State UEFISecureBootEnabled was 1 (Secure Boot on; the off state was never captured), CI\Policy held 4 REG_DWORD values, the DeviceGuard, HVCI and LsaCfgFlags values were absent (no VBS, HVCI or Credential Guard on state was ever measured); the sample is docs/samples/windows.txtFor a per-VALUE read, ERROR_FILE_NOT_FOUND/ERROR_PATH_NOT_FOUND reports the row absent with no token. For a KEY OPEN, the same two codes report absent only for SecureBoot\State, CI\Policy, DeviceGuard and its HVCI scenario subkey; Lsa has no evidenced not-found case, so the identical codes there report unreadable with lsa:key_missing. ERROR_ACCESS_DENIED reports unreadable with <name>:access_denied and the action reports PERMISSION_DENIED/PARTIAL; any other Win32 error reports unreadable with <name>:win32_<n>
macOSagent daemon, root today (LaunchDaemon carries no UserName key, see the docs/agent-privilege-model.md TL;DR); both tools need no elevation to reportNone; spctl --status and csrutil status are unprivilegedBare-metal Mac, unprivileged (euid 501), 2026-09-21: real capture (docs/samples/macos.txt); no root-privileged run has been capturedA tool that cannot be started reports unreadable with <key>:spawn_failed (no errno) or <key>:eacces / <key>:errno_<n> (from the spawn errno, including a missing binary as errno_2); the other failures are <key>:timeout, <key>:output_truncated, <key>:exit_<n> and <key>:exit_signal
Linuxagent daemon, dedicated unprivileged account (the agent never runs as root on Linux)None documented for this plugin (docs/agent-privilege-model.md)aarch64 Debian 13 container, root, 2026-09-23: real capture of the built .so (docs/samples/linux.txt). secure_boot reads absent (the gap in caveat 1) and code_integrity reads unreadable with errno_19, which the plugin reports when securityfs is not mounted, so the container is inferred to have no securityfs and no EFI variables (the mounts themselves were not recorded); no real Secure Boot value or lockdown mode has been capturedEACCES/EPERM reports the row unreadable with <key>:eacces and the action reports PERMISSION_DENIED/PARTIAL. ENOENT reports absent with no token only when the parent surface is confirmed present (securityfs mounted; for efivars, /sys/firmware/efi absent or efivarfs mounted); otherwise it is remapped to ENODEV and reports unreadable with <key>:errno_19. Any other errno reports unreadable with <key>:errno_<n>

Binaries and subprocesses: macOS code_integrity runs exactly two, /usr/sbin/spctl --status and /usr/bin/csrutil status (each by absolute path, no shell); every other leg is an in-process read and spawns nothing. Network: none.

Data contract

Inputs

Neither action takes parameters.

Outputs

Pipe-delimited rows written via write_output(), in read order. The first field is the fixed action literal (secure_boot or code_integrity), then <os>, <key>, <raw> and <state>. <raw> is - when nothing was read (absent, unreadable, unsupported); a raw value that was read passes through the shared untrusted-output escaper, which turns a backslash into / and escapes a pipe.

crossplatform.platform_security.code_integrity — row_kind|os|key|raw|state

FieldTypeValuesAvailableExampleDescription
row_kindstringcode_integrity constrainedWindows, Linux, macOScode_integrityRow family: code_integrity (one per key read) or constrained (an internal-error row: the two-field row constrained|internal_error, which carries no os, key, raw or state).
osstringlinux macos windowsWindows, Linux, macOSlinuxThe leg that produced the row.
keystring-Windows, Linux, macOSlsmValue read: lsm and lockdown (Linux); gatekeeper and sip (macOS); ci_policy. for every value under CI\Policy, deviceguard.EnableVirtualizationBasedSecurity, deviceguard.RequirePlatformSecurityFeatures, deviceguard.HypervisorEnforcedCodeIntegrity, deviceguard.hvci_scenario_enabled and lsa.LsaCfgFlags (Windows; LsaCfgFlags lives under Control\Lsa, not DeviceGuard).
rawstring-Windows, Linux, macOScapability,landlock,yama,apparmorThe raw text or number read (the LSM list, the lockdown line with its bracketed active mode, the first line of tool output, or the registry value); ”-” when nothing was read (absent or unreadable).
statestringenabled disabled partial evaluation enabled_locked unmodelled absent unreadableWindows, Linux, macOSenabledenabled, disabled and partial describe the PROTECTION, not the raw value (Linux lockdown integrity is partial, confidentiality is enabled; macOS SIP with a custom configuration is partial). evaluation (Smart App Control in evaluation mode) and enabled_locked (Credential Guard with a UEFI lock) are Windows-only. unmodelled = a value was read that this table has no interpretation for (raw keeps it). absent = the OS definitively says it is not there (no lockdown LSM, no DeviceGuard values on a default Windows install), a normal answer and not a failure. unreadable = the read failed.

crossplatform.platform_security.secure_boot — row_kind|os|key|raw|state

FieldTypeValuesAvailableExampleDescription
row_kindstringsecure_boot constrainedWindows, Linux, macOSsecure_bootRow family: secure_boot (one per key read) or constrained (an internal-error row: the two-field row constrained|internal_error, which carries no os, key, raw or state).
osstringlinux macos windowsWindows, Linux, macOSlinuxThe leg that produced the row.
keystring-Windows, Linux, macOSsecure_bootValue read: secure_boot and setup_mode (Linux efivars), secure_boot (macOS, unsupported row), UEFISecureBootEnabled (Windows).
rawstring-Windows, Linux, macOS1The raw value read (the efivar data byte, or the registry DWORD as a number); ”-” when nothing was read (absent, unreadable or unsupported).
statestringenabled disabled unmodelled absent unreadable unsupportedWindows, Linux, macOSenabledenabled = Secure Boot enforcing (for setup_mode: User Mode, a Platform Key is enrolled); disabled = Secure Boot off (for setup_mode: Setup Mode, no Platform Key, any image may load). The state describes the protection, not the raw number. unmodelled = a value was read that this table has no interpretation for (raw keeps it). absent = the OS definitively says it is not there (a BIOS/CSM boot has no efivars or SecureBoot\State), a normal answer and not a failure. unreadable = the read failed. unsupported = no mechanism on this OS (macOS).

Result status

StatusCompletenessProvenanceWhen
OKFULL—No row was unreadable: every key was either read or absent. An absent row adds no reason token, so a BIOS host, a kernel without lockdown or a default Windows install still reports OK.
UNAVAILABLEFULLno public API; SIP reported under code_integritymacOS secure_boot: the leg is unsupported by design and reports its unsupported row.
CONSTRAINEDPARTIAL<key>:errno_<n>, <key>:efivars:shape, <key>:timeout, <key>:output_truncated, <key>:spawn_failed, <key>:exit_<n>, <key>:exit_signal, <name>:win32_<n>, <name>:type_<n>, <name>:size_<n>, <name>:oversized, ci_policy:enumeration_incomplete, lsa:key_missingAt least one row was unreadable and none was refused; one <key>:<cause> token per unreadable row, and <key>:efivars:shape is an efivar that is not 4 + 1 bytes. An absent row never appears here.
CONSTRAINEDPARTIALinternal_errorAny leg: an unexpected exception was contained in execute(); the action returns 1 with the row constrained|internal_error.
PERMISSION_DENIEDPARTIAL<key>:eacces, <name>:access_deniedAny leg: a read was refused, EACCES/EPERM on Linux and for a macOS spawn, ERROR_ACCESS_DENIED on Windows. A refusal outranks every other unreadable cause in the same run; the reason still lists every unreadable row’s token.

Where the data goes

Sample output

Windows — captured: windows Windows 10.0.26200 x86_64 · bare-metal · 2026-09-21 · LocalSystem (elevated) · leg-hash 9cf003de2f97

== action=secure_boot
secure_boot|windows|UEFISecureBootEnabled|1|enabled
[result_status] OK / FULL

== action=code_integrity
code_integrity|windows|ci_policy.EmodePolicyRequired|0|unmodelled
code_integrity|windows|ci_policy.SAC_PreviousState|4294967295|unmodelled
code_integrity|windows|ci_policy.SkuPolicyRequired|0|unmodelled
code_integrity|windows|ci_policy.VerifiedAndReputablePolicyState|0|disabled
code_integrity|windows|deviceguard.EnableVirtualizationBasedSecurity|-|absent
code_integrity|windows|deviceguard.HypervisorEnforcedCodeIntegrity|-|absent
code_integrity|windows|deviceguard.RequirePlatformSecurityFeatures|-|absent
code_integrity|windows|deviceguard.hvci_scenario_enabled|-|absent
code_integrity|windows|lsa.LsaCfgFlags|-|absent
[result_status] OK / FULL

macOS — captured: macos macOS 26.6.2 arm64 · bare-metal · 2026-09-21 · euid 501 · leg-hash 9cf003de2f97

== action=secure_boot
secure_boot|macos|secure_boot|-|unsupported
[result_status] UNAVAILABLE / FULL / no public API; SIP reported under code_integrity

== action=code_integrity
code_integrity|macos|gatekeeper|assessments enabled|enabled
code_integrity|macos|sip|System Integrity Protection status: enabled.|enabled
[result_status] OK / FULL

Linux — captured: linux Debian GNU/Linux 13 (trixie) aarch64 · container · 2026-09-23 · euid 0 · leg-hash 9cf003de2f97

== action=secure_boot
secure_boot|linux|secure_boot|-|absent
secure_boot|linux|setup_mode|-|absent
[result_status] OK / FULL

== action=code_integrity
code_integrity|linux|lsm|-|unreadable
code_integrity|linux|lockdown|-|unreadable
[result_status] CONSTRAINED / PARTIAL / lsm:errno_19,lockdown:errno_19

Caveats and known gaps

  1. A container without /sys/firmware/efi reads Secure Boot as absent, even on a Secure Boot host. The mount check separates “mounted, but this value is absent” from “the surface is not mounted” for the securityfs reads, but not for efivarfs: a default container’s /sys tree omits /sys/firmware/efi whatever the host’s firmware, and neither deploy/docker/Dockerfile.agent nor the repository’s compose files bind-mount it. Closing this needs a deploy-side change (bind-mounting /sys/firmware/efi read-only into the agent container), and the Linux sample, a container capture, shows exactly this on its two secure_boot rows.
  2. Configured policy, not runtime proof. The Windows rows read registry values, which say what is configured. Whether Device Guard, HVCI or Credential Guard is actually running is a separate runtime fact (Win32_DeviceGuard) that this plugin does not query, and it does not call WLDP.
  3. macOS secure_boot is unsupported, and code_integrity parses tool text. There is no public API for the boot-security policy and bputil is a recovery-environment tool that is not run, so secure_boot always reports UNAVAILABLE on a Mac. Gatekeeper and SIP have no library API either, so both are read from a tool’s text: the parsers match an exact line and report anything else as unmodelled. Security.framework SecStaticCode* is not used, because every call in that family validates one named code object’s own signature, not a machine-wide enforcement setting.
  4. Fixed reads, no discovery. The plugin reads only the keys named above; it does not walk securityfs or the registry (apart from listing the value names under CI\Policy), and it does not report TPM or measured-boot state.
  5. Windows CI\Policy is listed whole but modelled for one value. Every value under the key appears as a row, but only VerifiedAndReputablePolicyState has a state mapping; the others (for example SkuPolicyRequired) read unmodelled with the raw number, which says the value exists, not what it means.

Source and tests