~0x64616E69656C
project 03 / R3 / genuine kernel evidence / 27 October 2026

The First
Real Byte.

The response existed. The kernel evidence arrived. nginx stopped the stream. The client received zero body bytes.

FUNCTIONAL PASS / BOUNDED RESEARCH
Four predetermined single-stream HTTP/2 cases, each run once.
Genuine AppArmor audit evidence.
No production architecture selected.
CPU acceptance remains unresolved.
0
E1 client body bytes / HTTP/2 reset
3,996
E1 body bytes preread before hold
20 ms
nominal response hold
4 / 4
predetermined case expectations met
Genuine evidence → Gate B → independently verified client bytes27 October 2026 · experimental · no deployment
01 / QUESTION

Can real evidence
beat the first byte?

R1 demonstrated synthetic HTTP/2 containment, with a failed CPU budget. R2 established independent AppArmor prevention and isolated kernel-audit receipt. R3 asks whether genuine evidence can traverse that boundary in time for nginx to withhold an already-ready response.

The distinction matters: AppArmor prevents the defined native operation. nginx decides whether to deliver the response. Neither a denial nor a server-side abort proves what the client received; that requires a separate client-byte oracle.

Two separate advances: R2² proved one native BPF denial. R3 uses the AppArmor audit path. It does not demonstrate integrated BPF-to-nginx evidence transport.
02 / MINIMAL METHOD

One request.
An already-ready response.

Each case used a fresh experimental nginx worker, backend and authenticated session, with one HTTP/2 request in flight. The backend submitted HTTP 200 and the complete fixed 8,192-byte fixture body immediately.

GATE B / NOMINAL 20 MS HOLD

Delay delivery at a defined boundary.

The experimental gate held downstream delivery before header/body filter entry. Matching accepted evidence could abort the stream during that window; expiry without accepted evidence released the response as unverified. No challenge page or replacement body was evaluated.

The native operation ran independently after response submission. An nginx abort could not cancel the operation or create a false prevention result.

INDEPENDENT CLIENT / ACTUAL RECEIPT

Count received bytes, not intended bytes.

A separate HTTP/2 client recorded response headers, DATA bytes, END_STREAM and reset codes. Complete cases required an exact 8,192-byte body match. E1 required no response headers and zero DATA bytes, followed by RST_STREAM / INTERNAL_ERROR.

The repeated body pattern is a controlled fixture, not a malicious-content classifier. E2 and E3 legitimately deliver it.

03 / EVIDENCE CHAIN

A kernel denial.
A checked association.

E1 originated in a genuine AppArmor kernel audit denial of the actual protected write-open, returning EACCES. An isolated trusted observer validated the record before forwarding authenticated evidence to nginx.

Kernel record
Kernel sender and audit framing checked; actual denial matched against the expected profile, operation, requested/denied masks, protected path and registered backend identity.
Association
Privileged preparation registered the backend identity and its one-request session. The backend remained identifiable until observation closed. This bounded association is not a concurrent request-attribution solution.
Authenticated input
Separate unprivileged identities, local peer-credential checks and session binding, with freshness and ordering checks before nginx accepted the alert. The experimental receiver is trusted.
Negative control
E3 produced a genuine denial from the controlled backend against a different protected target. The observer rejected the exact-path mismatch and forwarded no positive evidence.
Independent boundaries: AppArmor denied the native operation; the observer checked provenance; nginx Gate B stopped response delivery; the client verified receipt. A compromised nginx worker could bypass its own response gate.
04 / FOUR CASES

Zero bytes when timely.
All bytes when too late.

Four predeclared primary cases, each executed once. Three actual native operations: two protected-canary attempts and one unrelated-target attempt. All four case expectations passed.

Independent HTTP/2 client outcomes — same complete 8,192-byte fixture body offered in every case
CaseEvidenceClient body bytesClient result
E1 / matching during holdGenuine AppArmor denial accepted in time0No response headers or DATA; RST_STREAM / INTERNAL_ERROR
E2 / no denialNo native operation or denial8,192HTTP 200, exact body, END_STREAM; released unverified
E3 / unrelated denialGenuine backend denial rejected as unrelated8,192HTTP 200, exact body, END_STREAM
E4 / late matching denialGenuine matching denial accepted after delivery8,192HTTP 200, exact body, END_STREAM; no retroactive retraction
The response existed.
The kernel evidence arrived.
nginx stopped the stream.
The client received zero body bytes.E1: genuine evidence and independently measured HTTP/2 containment, within this single-stream experiment.
05 / THE DELIVERY BOUNDARY

Ready upstream.
Still withheld downstream.

In E1, nginx had parsed upstream HTTP 200 and preread 3,996 body bytes before entering the nominal 20 ms hold. The zero-byte result did not depend on an origin that had yet to produce its response.

E1 / TIMELY ACCEPTANCE

About 16.27 ms before the deadline.

Matching evidence was accepted approximately 16.27 ms before the nominal hold deadline. nginx aborted before downstream header/body filter entry. The independent client saw no response headers, no DATA and an INTERNAL_ERROR stream reset.

This is one observed margin, not a latency guarantee or a measured production tail distribution.

E4 / IRREVERSIBLE DELIVERY

The native operation happened later.

The client had received all 8,192 bytes before the protected native operation even began. Matching evidence was accepted approximately 31.72 ms after the nominal deadline. The completed stream was not reset.

Late evidence cannot retract delivered bytes. The hold can only contain output that has not yet crossed the delivery boundary.

Timing comparisons use same-boot monotonic actor timestamps and syscall brackets. Delayed parent logging and audit wall-clock identifiers are not treated as exact kernel-event creation times.

06 / LIMITS AND RESTORATION

Functional proof.
Open product questions.

This was a harmless, isolated single-stream fixture campaign. It establishes neither general exploit prevention nor concurrent request attribution, production latency bounds or acceptable operating cost.

COST / STILL UNRESOLVED

R1's CPU failure still stands.

R1 passed scoped synthetic containment but failed its CPU gate: +22.10% versus stock nginx against a +10% target. R3 is not a matched cost benchmark and does not repair that result.

Concurrent HTTP/2 attribution, other transports, hostile-worker behavior and receiver failure/restart behavior require independent validation.

ENGINEERING / CLEANUP ACCOUNTED FOR

Setup failures remain in the record.

Two zero-request engineering attempts preceded the primary cases: an invalid nginx configuration and an isolated helper-import failure. The initial cleanup deadline failure and subsequent successful cleanup remain separately documented. No completed primary case was repeated or tuned into success.

Final independent review and cleanup passed: experimental security state and runtime fixtures were removed, original audit settings restored, and recorded existing service identities and configurations preserved. These checks are not a full user-data or system-recovery guarantee.

Architecture remains open: R3's trusted receiver is an experimental component, not an adopted AppArmor product architecture. Direct BPF snapshots remain unvalidated; the shared ringbuffer's writable consumer cursor still matters. Protected snapshots versus a minimal trusted broker remain a comparison of integrity, authority and lifecycle costs. No production Gate C has been selected.

KISS remains the objective: minimal permanent components, narrow upstream patches, independent enforcement and explicit trust boundaries. A functional result earns a more precise question; it does not by itself earn a production component.

07 / FOLLOW-UP · 27 OCTOBER 2026

R3.1 — The Wrong Stream:
Attribution Has a Cost

One genuine denial, two concurrent requests sharing one backend process. Could the unchanged evidence interface select the affected HTTP/2 stream?

Three primary cases, each executed once — six HTTP/2 requests and two genuine AppArmor denials
CaseHTTP/2 Stream AHTTP/2 Stream B
C0 / no denial8,192 bytes, complete8,192 bytes, complete
C1 / A causes denial0 bytes, reset0 bytes, reset
C2 / B causes denial0 bytes, reset0 bytes, reset

Both requests ran in separate threads of the same backend process. Both nginx response holds were active before the kernel operation, and genuine authenticated evidence arrived before both nominal 20 ms deadlines. The unchanged Gate B applied its service/invocation alert to both matching requests. The legitimate stream therefore suffered collateral containment.

AppArmor audit supplied the shared thread-group PID, not the actual syscall TID. Thread names were task-controlled, and no trustworthy HTTP-request-specific or stream-specific evidence binding existed. The independent client observed two separate RST_STREAM / INTERNAL_ERROR outcomes with no response headers or DATA; a connection-wide shutdown or connection-scoped security policy was not established.

Collateral containment observed. Selective containment not demonstrated. The tested service-wide correlation is insufficient for precise containment of concurrent requests. This limits the current attribution and decision interface; AppArmor enforced both operations, and R3's single-stream functional result stands. Two resets do not by themselves establish the correct production response. Independent review and cleanup passed.
R3 proved that evidence can stop delivery.
R3.1 proved that evidence needs scope.

Next open direction: the actual PHP-CGI deployment.

Can nginx reliably associate a specific HTTP/2 upstream request with the PHP-CGI process actually executing it, using independently established kernel/socket identity rather than application-supplied claims?

The near-term target is the operator's actual PHP-CGI deployment. PHP-FPM process-management behavior is not presumed equivalent; other backend languages and runtimes are deferred. The exact launch mode, CGI versus persistent FastCGI operation, process lifecycle, worker exclusivity and socket ownership are not yet established. A future read-only source/configuration study must establish those facts before an experimental implementation is considered.

Research direction, no implementation: BPF remains a preferred candidate for investigation; no technology or production Gate C has been selected. No PHP-CGI correlation solution, BPF-to-nginx integration or kernel patch is implemented. R1's +22.10% CPU-budget failure and unproven production overhead remain constraints. The next research plan will be developed separately.