OCI subprocess-deny profile
The 0.3 release adds the explicit worker protocol
apizr.subprocess-deny/v1. In an OCI execution policy, set:
{
"schema_version": "apizr.execution/v2",
"subprocess": {"mode": "deny"}
}
Use that policy with apizr execute, apizr generate rest|mcp, or
apizr expose build rest|mcp. Supply an immutable local image ID and its native
linux/amd64 or linux/arm64 platform as usual. Build a current worker using
scripts/build_worker_image.py; it includes the additional image label
org.apizr.subprocess-deny.protocol=apizr.subprocess-deny/v1. Repository execution
also requires the existing repository worker protocol label. Older images are
refused, without pulling, installing dependencies or falling back to allow mode.
The entrypoint installs an additional Linux seccomp BPF filter before importing
any project module. Docker's default seccomp and existing resource, filesystem,
network, privilege and cleanup controls remain active. The filter refuses native
fork, vfork, clone, clone3, execve and execveat, including calls issued
directly through libc. It also blocks ptrace and io_uring. Alternate syscall ABIs
terminate the worker; x32 aliases and syscall numbers at or above 512 are refused.
The implementation supports the reviewed native 64-bit little-endian x86-64 and
AArch64 syscall tables. It requires a single-threaded entrypoint and checks kernel
return values for no-new-privileges and filter installation. Failure stops startup.
Policy allowlists may not inject loader/interpreter bootstrap variables (LD_*,
DYLD_*, PYTHON*, GLIBC_*, or GCONV_PATH) before the filter is installed.
This strict profile also prohibits new threads and replacing the worker's
executable. Thread pools, multiprocessing, shell commands, external executables
and libraries that start background threads are therefore incompatible. Async
Python functions that do not start threads or child processes remain usable.
The caller can catch PermissionError; an uncaught application exception is
reported using the existing sanitized failure result. Kernel installation failure
is a worker failure, never successful execution with weaker controls.
This is a specific process-creation restriction for trusted-code execution, not a general untrusted-code sandbox or a VM boundary. It relies on a trusted image, Docker host and Linux kernel. See the Linux seccomp documentation for filter stacking and limitations, and the Linux syscall ABI guidance.
Compatibility and static evidence
Existing allow-mode artifacts, policies, canonical reports and backend APIs keep
their bytes and behavior. The profile is an opt-in extension, selected only by an
OCI execution policy requesting deny. Local-process execution continues to refuse
deny. The frozen Repository Readiness/Exposure v1 adapters describe the original
backend guarantees; they do not advertise this additional image protocol. Keep
oci-container in those policies and put the deny requirement in the separate
execution policy. A static require_controls: ["subprocess_deny"] still
refuses; no static report establishes host or worker-image availability.
Generated strict bundles contain a separate, manifest-bound bridge and use the
strict entrypoint on every invocation. Use their generated app.py or server.py.
For direct Python invocation use apizr.subprocess_guard.single.plan/execute, or
apizr.subprocess_guard.repository.container_plan/execute. The original low-level
apizr.oci and apizr.repository_execution APIs retain their allow-mode contract.
The required OCI job tests both single-source and repository execution, real REST/MCP stdio/MCP HTTP calls, direct libc syscalls, import-time protection, tamper refusal/recovery and cleanup. Independent positive controls verify that ordinary allow mode can still create a process. Unit tests cover ABI dispatch, unsupported workers and fail-closed installation; targeted mutations remove the filter action and the worker protocol requirement to verify these checks detect missing protection.