Repository navigation
security(admission): reject special audit files without blocking #252
Description
Finding
Fresh review of Agent Artifact Admission after the #251 audit-path repair was integrated into exact parent feat/agent-artifact-admission@bf5a48b8a095359b28a067e019b93b8c0e26104f found a narrower local evidence-availability gap.
The Linux FileAuditSink::open_append_only now uses O_NOFOLLOW, creates with mode 0600, and verifies metadata().is_file() after open. This closes final-symlink redirection and permissive-umask creation, but the post-open type check cannot protect availability when the final pathname is a special file whose open itself can block. In particular, the current append/write-only open has no O_NONBLOCK; Linux fifo(7) specifies that opening a FIFO normally blocks until the other end is opened, while write-only O_NONBLOCK fails promptly with ENXIO when no reader exists. An attacker who can pre-place the configured audit filename as a FIFO can therefore stall the admission/evidence path before Wardnet reaches the regular-file check.
This remains Wardnet's own audit-evidence persistence boundary. It does not add sandbox execution, outbound policy, orchestration, package analysis, foreign-owner source or cross-service storage authority.
Hostile RED acceptance
From the exact #129 parent, add a Linux-only integration fixture that creates the configured audit pathname as a FIFO with no reader and invokes FileAuditSink::append in an isolated child process. The secure contract is that the append returns AuditError::StorageUnavailable promptly. Bound the parent wait and kill/reap a child that remains blocked so the regression fails semantically rather than hanging CI. Existing final-symlink, private-mode, append/order/sync and oversized-record tests must remain unchanged.
Runner/bootstrap/rustfmt failure is not RED. Current blocking behavior at the open boundary is RED.
Minimum GREEN acceptance
Keep the OS-native single-open boundary and existing O_NOFOLLOW/0600/post-open regular-file verification. Add only the Linux open flag(s) required to prevent blocking on special files before the descriptor type is checked; for a FIFO with no reader the open must return promptly and the public sink must preserve stable AuditError::StorageUnavailable. Do not introduce a pre-open pathname type check with a TOCTOU window, do not truncate existing evidence, and preserve append semantics, process-local serialization, bounded line encoding, flush + sync_data.
If additional special-file classes have observable open-time side effects that cannot be excluded by the same minimal boundary, record them as a separate hostile case rather than claiming broader protection than is tested.
Primary traceability
- Linux man-pages 6.18,
fifo(7): normal FIFO open blocks until the other end is opened; write-only nonblocking open fails withENXIOwhen no reader is present. - Linux man-pages 6.18,
open(2): documentsENXIOforO_NONBLOCK | O_WRONLYon a FIFO with no reader andEINTRwhile blocked opening slow devices such as FIFOs. - MITRE CWE-59: link/name resolution weaknesses can redirect file operations and compromise integrity/availability; this follow-on case is specifically an availability consequence after link-following was closed.
Keep docs/product-technical-gap-baseline.md untouched outside its sole writer #130.
Activity
seonghobae commentedon Sep 10, 2026
Hosted semantic RED is now established on test-only
#253@187aabd1ada11b5a5c9bbf3c07df143d645b492d. CI34448606974, rust job102778872900, acquired realubuntu-24.04; checkout/toolchain andcargo fmt --checkpassed. Workspace tests then reachedaudit_special_file_safety_contract: helper control passed, butfile_sink_rejects_fifo_without_blocking_on_openremained blocked for the bounded 3.11 s interval and failed withaudit append blocked while opening a FIFO; special audit files must fail closed promptly. Production was unchanged on that RED head.Minimum causal successor is now on
#253@1e2efdc9580328709b3d3bdde3682979abf46a2a:audit.rspreserves append/create mode0600,O_NOFOLLOW, post-open regular-file verification and stable error mapping, and adds LinuxO_NONBLOCKto the same singleopenoperation. Linuxfifo(7)/open(2)specify that write-only nonblocking FIFO open fails promptly withENXIOwhen no reader exists, whileO_NONBLOCKhas no effect on regular-file semantics relevant here. Exact-current CI/Fuzz are still non-terminal; no GREEN or merge claim yet.seonghobae commentedon Sep 10, 2026
Completion receipt: PR #253 preserved the #251
O_NOFOLLOW/0600/same-descriptor regular-file boundary and added the missing Linux nonblocking-open protection only. Test-only exact187aabd1ada11b5a5c9bbf3c07df143d645b492dreproduced the FIFO availability defect on real hosted CI: opening a write-only FIFO with no reader remained blocked beyond the bounded 3.11 s fixture. Exact successor1e2efdc9580328709b3d3bdde3682979abf46a2aadded LinuxO_NONBLOCKat the existing open boundary; CI34449016775and Fuzz34449016761reached SUCCESS with empty submitted-review and inline-thread inventories. #253 was ordinarily merged into canonical #129 asc4030f7fecaa5627ccec31ce58eca7e59db45334; the full #252 RED/GREEN/test evidence is therefore retained in the canonical lineage.