NewN-Day-BenchView benchmark
winfunc
Research

ENDGINX - 6 CVEs in NGINX with open models

We pointed GLM-5.1 and GLM-5.2 at NGINX. The result was six separately documented security findings represented by five CVE identifiers. Here are the code paths, agent traces, and proof conditions.

Published July 23, 2026Updated July 23, 202619 min read
nginxvulnerability-researchopen-modelsagents
ENDGINX - 6 CVEs in NGINX with open models
Contents

We wanted to know how good open models had become at finding vulnerabilities in hardened software.

So we picked NGINX.

NGINX is old, small by modern infrastructure standards, aggressively reviewed, and deployed close enough to the network that mistakes tend to have consequences. Its C code is also full of the kind of reasoning traps that make vulnerability research interesting: two-pass encoders, compact binary protocols, shared request state, configuration-dependent control flow, and hand-sized buffers whose safety depends on an invariant established 200 lines earlier.

We ran Winfunc with GLM-5.1 and GLM-5.2 from Z.AI. The public result is six separately documented NGINX findings with CVE badges:

  • two heap overflows in HTTP/2 upstream request builders;
  • one heap overflow in the rewrite engine;
  • one heap overflow in the stream scripting engine;
  • one HTTP/2 frame-injection bug; and
  • one mTLS authorization bypass where a revoked certificate was accepted.

There are five unique CVE identifiers, not six. The gRPC and HTTP/2 proxy findings are different reachable implementations of the same HPACK accounting flaw, so they were fixed under the same CVE. We count them separately because the entry points, builders, configurations, traces, and proofs are separate. NGINX and F5 grouped the underlying defect.

A note on the traces

The technical storylines below were reconstructed from persisted traces across multiple NGINX scans. We rerun targets as the agent and models change, and those databases include runs through more than one provider. They show how the system navigated and falsified each hypothesis; they are not a model leaderboard or proof that one particular model was first to each CVE. The experiment described here used GLM-5.1 and GLM-5.2, but we do not manufacture per-CVE model attribution from mixed rerun data.

The source-navigation agents had read-only repository tools. They produced evidence and proof plans, not shell sessions. The AddressSanitizer and live-service results cited below were produced later in separate build-and-reproduction environments and are preserved on the public Hacktivity pages.

Why NGINX

There are easier ways to make an automated security system look good.

You can scan a large application with hundreds of endpoints and count every missing rate limit. You can run a known-vulnerability corpus where the affected function is already isolated. You can include dependency CVEs. You can let the model write plausible reports without requiring a build or a concrete failure. All of these produce impressive-looking numbers. None answers the question we cared about.

Can a generally capable open model read mature systems code, form a new vulnerability hypothesis, follow the real control flow, reject the obvious false-positive conditions, and leave behind enough evidence for a maintainer to act on?

NGINX is a useful target because its abstractions are economical. That economy is great for a web server and unforgiving for an auditor. A field called len may mean the number of bytes available, the number of bytes already serialized, the size before escaping, or a 24-bit wire value depending on which part of a module you are in. A script is often evaluated twice: once to allocate and once to copy. A request header may be normalized in one configuration and intentionally retained in another. HTTP, stream, gRPC, and upstream HTTP/2 can share helpers without sharing enforcement.

Most files look correct in isolation. The bugs appear when two correct-looking decisions disagree.

All six findings came from disagreements at those seams.

What we pointed at the code

A useful public description of the Winfunc harness does not require us to publish the prompts, target-specific mission plans, ranking heuristics, or model routing.

It starts before a model reads an interesting function.

An initialization pass maps the repository and records the security context needed to judge impact: exposed entry points, authentication model, trust boundaries, important configuration surfaces, and what an attacker can plausibly control. A planner converts that into bounded attack-surface missions. For NGINX, a useful mission is not “find a buffer overflow.” It is closer to “find places where attacker-sized data crosses a wire-format width, encoding expansion, or two-pass allocation boundary.”

Discovery then runs in two lanes. A cheap, recall-biased gate can select source files for a file-level hunter. In parallel, mission agents follow hypotheses across files and modules. Both lanes emit raw signals. Those signals are clustered and deduplicated before a judge sees them.

The judge must reconstruct an evidence packet: attacker control, source, trigger path, violated invariant, sink, realistic prerequisites, and a concrete failure mode. A reporter independently rereads the code. A primitive with no standalone impact can be retained as a gadget, but it is not promoted into a vulnerability report. Confirmed findings and useful gadgets become inputs to a later chain-composition pass.

The diagram below is an intentionally public view. Select a stage to see what crosses each boundary.

winfunc-agent / public system view
GLM-5.1GLM-5.2
Map target: Build repository-scoped context around modules, entry points, configuration surfaces, and trust boundaries before asking for bugs.
Init
Map target
Input
Source tree + operator focus
Output
Target brief + scan policy

Build repository-scoped context around modules, entry points, configuration surfaces, and trust boundaries before asking for bugs.

All file access stays inside the target sandbox.

Stage 1 / 6Evidence moves right

The important split is visible in the first two stages. Compute is spent deciding where to look and what kind of invariant to test before expensive vulnerability reasoning begins. The rest of the harness mostly makes evidence survive concurrency, retries, deduplication, and skeptical rereading.

Now to the bugs.

Six findings, five CVE numbers

The six findings touch four distinct failure classes. The interactive view below is a compact source-to-proof map. The detailed sections that follow are the version for people who want the code path.

Six paths / five CVE identifiers
Select a finding
CVE-2026-28755: Revoked client certificate accepted by stream mTLS
CVE-2026-28755Medium · 5.4
Revoked client certificate accepted by stream mTLS
ngx_stream_ssl_module
Full report
Attacker control

A revoked client certificate and its private key

Broken invariant

The stream path ran OCSP but never enforced the stored revocation result

Observed proof

OCSP logged revoked; the TLS handshake still returned application data

Source
ngx_stream_ssl_handler()
Sink
missing ngx_ssl_ocsp_get_status()
Fixed by
NGINX 1.28.3 / 1.29.7

1. OCSP ran. The stream module ignored the answer.

CVE-2026-28755

Medium · CVSS 3.1 5.4 · ngx_stream_ssl_module

This finding started with a comparison.

The agent searched for ngx_ssl_ocsp_get_status, the helper NGINX uses to retrieve the result of client-certificate OCSP validation. The HTTP TLS path called it while deciding whether a request should proceed. The stream TLS path did not.

An absent call is not yet a vulnerability. The check could have been centralized in the common handshake code, enforced by OpenSSL, or performed in a later stream phase. The trace followed all three possibilities.

First it read the HTTP enforcement path to understand the expected contract. Then it followed where NGINX stores OCSP state during the handshake. It inspected the shared SSL callback, searched the stream module for another status check, and compared the mail TLS path. Finally it traced ngx_stream_ssl_handler() into the stream phase engine to confirm that a successful return actually exposed the configured upstream application.

The stream handler did check the ordinary certificate verification result:

C
/* Reduced to the relevant decisions. */
if (SSL_get_verify_result(ssl) != X509_V_OK) {
    reject_connection();
}

if (client_certificate_required && no_peer_certificate(ssl)) {
    reject_connection();
}

/* The stored OCSP result was not consulted here. */
continue_stream_session();

That distinction matters. OpenSSL can complete certificate-chain verification while NGINX's asynchronous OCSP machinery separately determines that the leaf certificate has been revoked. In HTTP, NGINX consumed that second result. In stream, it performed the work and then continued as if the result did not exist.

The practical preconditions were narrow and real:

  • NGINX was terminating stream TLS;
  • ssl_verify_client on and ssl_ocsp on were configured; and
  • the attacker retained a revoked client certificate and its private key.

Under those conditions, the revoked identity could still complete stream mTLS and reach the protected upstream until the certificate expired. Follow-up validation observed OCSP identify the certificate as revoked while the connection still received application data.

This is a useful example of why the trace did not stop at a missing function call. The agent explicitly ruled out common enforcement, implicit OpenSSL failure, and a later phase check. Only then did it preserve the finding.

NGINX Open Source 1.27.2 through 1.29.6 was affected. The fixes shipped in 1.28.3 and 1.29.7. F5 assigned CVSS 3.1 5.4 and credits Mufeed VH. The full Winfunc report contains the configuration and proof; the F5 advisory contains the supported-version matrix.

2. A size_t body met a 24-bit frame.

CVE-2026-42926

Medium · CVSS 3.1 5.8 · HTTP/2 upstream proxy

The next trace began at three assignments:

C
header->length_0 = (u_char) (body_len >> 16);
header->length_1 = (u_char) (body_len >> 8);
header->length_2 = (u_char) body_len;

HTTP/2 frame payload lengths are 24 bits. The largest valid value is 16,777,215. NGINX held the generated proxy_set_body length in a size_t, copied only its lower 24 bits into a DATA-frame header, and then placed the entire generated body after that header.

The agent did not assume an attacker could reach the assignment. It traced how proxy_set_body is compiled as a complex value, how request variables can influence its output, and which upstream path is selected by proxy_http_version 2. It compared the gRPC DATA-frame builder, found the protocol constant defining the maximum frame size, and searched the proxy-v2 code for a body-length cap or a loop that split the buffer into bounded frames.

There was neither.

The broken wire invariant is easier to see with numbers:

TEXT
generated body length      0x01000009  (16,777,225 bytes)
encoded 24-bit length         0x000009  (9 bytes)
bytes actually transmitted  16,777,225

The upstream reads nine bytes as the DATA payload. The next bytes are no longer inside that frame. They are parsed as another HTTP/2 frame header, followed by an attacker-influenced payload. By arranging the generated body around the wrap point, an attacker can inject frames into the NGINX-to-upstream connection.

This is not a worker heap overflow. It is a protocol-boundary failure with integrity impact on the upstream HTTP/2 session. Keeping that distinction in the report made the claim stronger, not weaker.

The vulnerable configuration combined proxy_http_version 2 with a proxy_set_body value that could exceed the frame limit. NGINX Open Source 1.29.4 through 1.30.0 was affected. Versions 1.30.1 and 1.31.0 route generated bodies through the normal bounded DATA-frame output path. The fix is commit c24fb259.

The full finding walks through the frame layout. F5 scores it 5.8 under CVSS 3.1 and 6.3 under CVSS 4.0 in its advisory.

3. $1 and $2 were different names for the same bytes.

CVE-2026-9256

High in Hacktivity · CVSS 3.1 8.1 · HTTP rewrite engine

NGINX's rewrite engine compiles a directive into small length and copy programs. The length program determines how much memory to allocate. The copy program writes the result. Every optimization in a two-pass system has one obligation: the two programs must agree.

The trace started around dup_capture, a flag that appeared to protect against duplicated regex captures. It followed the rewrite compiler's capture-only fast path and noticed that exact capture-aware length bytecode could be discarded. That looked dangerous, but only if the generic size calculation and runtime copy could diverge.

The agent then followed the request flags that decide whether a URI needs escaping, including plus_in_uri and quoted_uri. It read the escape routine to calculate expansion, traced the request-pool allocation, and constructed the interesting shape: two distinct capture numbers whose byte ranges overlap.

A representative rewrite looks like this:

NGINX
rewrite ^/((.*))$ http://127.0.0.1:18081/$1$2 redirect;

$1 and $2 are different captures, so a simple duplicate-capture guard does not fire. They refer to overlapping bytes from the same URI. When those bytes contain characters that require escaping, the fast length path charges for the URI's escape expansion once. The copy path escapes the bytes referenced by $1 and then escapes the overlapping bytes referenced by $2.

In reduced form:

TEXT
allocated = base + escaped_length(uri)
written   = base + escaped_length(capture_1)
                + escaped_length(capture_2)

For overlapping captures, written can be larger than allocated. A URI full of + characters made the difference concrete. Follow-up AddressSanitizer validation caught the copy running past a 4,096-byte request-pool allocation in ngx_http_script_copy_capture_code().

The false-positive checks here were mostly about compiler state. Did dup_capture catch nested groups? No, because the groups had different indices. Did the slow length path remain installed? Not in the optimized shape. Could request parsing normalize away the bytes responsible for expansion? The traced flags preserved the relevant condition into rewrite execution.

The fix makes sizing account for each capture exactly as the copy program will emit it. It shipped through NGINX PR #1395 and commit ca4f92a, in versions 1.30.2 and 1.31.1. F5 assigned CVSS 3.1 8.1 and CVSS 4.0 9.2.

The complete trigger and ASan trace are in the Winfunc report and affected-version details are in the F5 advisory.

4. Four bytes reserved, five bytes written: gRPC.

CVE-2026-42055

High in Hacktivity · CVSS 3.1 8.1 · ngx_http_grpc_module

HPACK encodes integers with a variable number of bytes. NGINX's gRPC upstream request builder sized its temporary buffer as if four bytes were always enough for the encoded length of a forwarded header name or value. The serializer used the real HPACK integer encoder. For a raw field above NGX_HTTP_V2_MAX_FIELD, that encoder can require five.

One missing byte would be interesting. Many oversized headers made it exploitable.

The agent first read the HPACK constants and integer writer rather than guessing from the request builder. It then traced client header parsing and the effect of large_client_header_buffers. Default NGINX settings prevent the exact oversized input, which is an important false-positive condition. The trace found the configuration that deliberately retains otherwise invalid raw headers and raises the buffer limit:

NGINX
ignore_invalid_headers off;
large_client_header_buffers 8 5m;

location / {
    grpc_pass grpc://backend;
}

The exact sizes are operator-controlled; what matters is allowing a forwarded raw name or value large enough to cross the HPACK integer-width boundary.

Next the agent confirmed that those retained headers reach ngx_http_grpc_create_request(), that the gRPC module is actually selected for the location, and that no outgoing NGX_HTTP_V2_MAX_FIELD check occurs before allocation. It compared the sizing expression with the encoder byte for byte.

The invariant failure was:

TEXT
buffer budget per oversized raw length = 4 bytes
HPACK serialization requirement        = 5 bytes
deficit across N forwarded fields      = N bytes

As the builder added HTTP/2 CONTINUATION frames, the accumulated deficit crossed the end of the temporary request buffer. Follow-up AddressSanitizer validation confirmed an out-of-bounds write while constructing the upstream gRPC request.

We reported the demonstrated primitive as unauthenticated worker memory corruption under a non-default configuration. We did not turn “heap overflow” into “reliable remote code execution” by punctuation. F5 notes conditional code-execution impact if address-space randomization is disabled or bypassed; that is a condition, not something our proof claimed to have solved.

The gRPC finding page contains the full configuration, field construction, and sanitizer evidence.

5. The same invariant broke in the HTTP/2 proxy builder.

CVE-2026-42055

High in Hacktivity · CVSS 3.1 8.1 · HTTP/2 upstream proxy

The gRPC builder was not the only code that budgeted four bytes and later called the variable-length encoder.

A separate trace searched for the HPACK constants and write helpers across the HTTP/2 upstream proxy implementation. It established feature reachability through proxy_http_version 2, traced how ordinary HTTP/1.x client headers are retained and forwarded, and repeated the large-header configuration checks. Then it followed raw-versus-Huffman encoding selection to ensure the five-byte path could really be chosen.

The sibling bug lived in ngx_http_proxy_v2_create_request().

The strongest proof-backed sink was the in-place ngx_memmove() loop used to insert CONTINUATION-frame headers. The buffer was already undersized by one byte per over-limit field. Moving the serialized block to make room for frame headers pushed bytes beyond the temporary allocation.

This deserves a separate finding even though it shares a CVE with the gRPC path. A user can enable one upstream mode without the other. The vulnerable builders are different. The source-to-sink traces are different. The concrete overwrite happens during different request construction logic. From a patching perspective, however, the root mistake and remediation were shared: reject forwarded field names and values that exceed the supported HTTP/2 field limit before the buffer is sized.

Both paths were fixed by NGINX PR #1474 and commit 26d824e. The gRPC path dates back to 1.13.10, while the HTTP/2 upstream proxy path only exists in the newer 1.29.x line. The precise mainline, stable, and NGINX Plus ranges differ; Open Source fixes shipped in 1.30.3 and 1.31.2. F5 scores CVE-2026-42055 at 8.1 under CVSS 3.1 and 9.2 under CVSS 4.0.

The proxy-v2 finding and gRPC finding preserve their separate proofs. F5's CVE-2026-42055 advisory correctly covers both.

6. The capture changed between counting and copying.

CVE-2026-42533

High in Hacktivity · CVSS 3.1 8.1 · stream scripting engine

The last bug is my favorite because no integer overflows and no single operation is obviously unsafe. Time is the missing dimension.

Like HTTP rewrite values, NGINX stream complex values can run a length program and then a copy program. Both passes read regex captures stored on the stream session. The contract is implicit: capture state must not change between the two passes.

The trace began by searching for the mutable session fields captures, ncaptures, and captures_data, then listing every place stream regex execution could update them. It followed complex-value evaluation through the stream map module, the return module, variable expansion, preread, and TLS SNI extraction.

That produced a small but unpleasant expression:

NGINX
return "$1$m";

Here $m represents a variable backed by a regex map over attacker-controlled SNI. At the start of the length pass, $1 has no capture and contributes zero bytes. Evaluating $m runs the map regex and mutates the session's shared capture state. The pass allocates only what it observed at that time.

The copy pass restarts the expression. It sees the newly populated $1 and copies it.

TEXT
length pass:
    len($1) = 0
    eval($m) -> regex matches SNI, session captures change
    allocation = 1 byte

copy pass:
    copy($1) -> capture now references attacker SNI
    copy 12,000 bytes into the one-byte allocation

Follow-up AddressSanitizer validation caught a 12,000-byte write in ngx_stream_script_copy_capture_code().

The agent spent most of the trace proving that the state mutation could sit between the two observations. It read the map lookup path to establish its side effect, checked that the source was attacker-controlled SNI, traced the pool allocation, and compared the HTTP script implementation for the same unbounded capture-copy shape. The finding was not “shared mutable state is scary.” It was a precise ordering: empty during sizing, populated during a later variable evaluation, non-empty during copying.

NGINX fixed the issue with centralized bounds checks that make capture copying fail closed rather than trusting the stale size. Mainline changes landed through PR #1561, with stable backports in PR #1563. NGINX Open Source 0.9.6 through 1.31.2 was affected; fixes are in 1.30.4 and 1.31.3.

F5 scores the issue 8.1 under CVSS 3.1 and 9.2 under CVSS 4.0. That CVSS 4.0 score maps to Critical in F5's advisory; Hacktivity keeps the finding labeled High. The full Winfunc analysis includes the reproducer and sanitizer output, while the F5 advisory contains the product matrix.

What the traces actually tell us

The interesting part of these runs was not that a model could recognize a dangerous C function.

Across the six traces, the decisive actions were comparisons and failed alternatives:

FindingInitial leadWhat had to be ruled out
Stream OCSPHTTP consumed an OCSP result that stream did notcommon-handshake enforcement, OpenSSL failure, later stream rejection
Frame injectiona size_t entered a 24-bit fieldframe splitting, generated-body bounds, unreachable HTTP/2 upstream path
Rewrite overflowcapture fast path discarded exact sizingduplicate-capture guard, URI normalization, slow length bytecode
gRPC HPACKfour-byte budget met a variable encoderdefault input limits, header rejection, outgoing max-field enforcement
Proxy HPACKsibling builder shared the budgetfeature dispatch, Huffman selection, forwarded-header normalization
Stream capturestwo passes read mutable regex stateevaluation order, session ownership, attacker-controlled SNI reachability

Across providers, the recurring loop was the same: form a hypothesis, identify its strongest disqualifier, then spend read-only tool calls trying to prove that disqualifier. That is the part of the traces worth preserving.

It also explains why raw reasoning transcripts are a poor way to evaluate a security agent. A trace can be articulate and wrong. We care about the surviving artifact: the exact source, reachable configuration, invariant, sink, proof, and disqualifying conditions. In these cases, the artifacts survived maintainer review and became patches.

The harness doesn't really matter

I mean this in a narrower and more provocative way than the heading suggests.

The harness still matters operationally. It keeps repository access bounded. It provides concurrency and backpressure. It persists work, retries failed jobs, deduplicates sibling observations, separates a raw hypothesis from a confirmed report, and gives us something auditable when a scan runs for days. Removing those pieces would make the system unreliable and unpleasant to operate.

But the harness increasingly does not need to manufacture the vulnerability reasoning.

Earlier versions of this system required a much more elaborate decomposition. Tell the model which function to read. Tell it which source is attacker-controlled. Ask it to list sinks. Remind it to check reachability. Give it a vulnerability taxonomy. Ask another model to criticize the first. The scaffolding was doing a meaningful share of the intellectual work.

Current models need much less of that scaffolding. They can hold the relevant state, navigate unfamiliar C, notice an implicit invariant, and decide what would falsify a hypothesis. Raw hypotheses are still noisy. The useful change is downstream: after the judge and reporter evidence checks, the report stream is low-noise enough that a researcher can review reports instead of triaging raw guesses.

The six investigations also went beyond signatures. The OCSP bug required comparing sibling authorization paths. The $1$m bug required tracking capture state across two evaluations. The rewrite overflow required recognizing that distinct capture numbers could refer to overlapping bytes. The agents assembled those arguments from the code they read.

So where does the remaining advantage come from?

Direction.

A large codebase contains more plausible questions than any finite compute budget can investigate. “Audit NGINX” is not a direction. Even “look for memory corruption” is weak. A useful threat model asks which inputs cross trust boundaries, which configurations expose them, which parsers or encoders transform them, which subsystems duplicate security-sensitive logic, and where a compact representation can disagree with an in-memory size.

Winfunc spends a lot of compute before the attack phase on two questions:

  1. Where should the model look? Rank reachable modules, protocol boundaries, security decisions, stateful interpreters, and recent or high-risk code paths for this target.
  2. What should it look for there? Produce target-specific hypotheses grounded in deployment, attacker control, trust boundaries, and the invariants that this particular code must preserve.

That requires domain knowledge. In NGINX, it helps to know that configuration is part of reachability, that the same request can be re-encoded into multiple upstream protocols, that length/copy VMs are common, and that TLS verification results can be split across OpenSSL and NGINX state. On a database, browser, identity provider, or payment service, the useful hypotheses are different.

This is the part of the harness we keep investing in: not more choreography around the model, but a better target model and a better set of questions. Once pointed at the right boundary, the open models are increasingly capable of doing the vulnerability research themselves.

The remaining evidence gates are intentionally dull. They are there because confidence is not proof.

Why these six bugs belong together

At first glance, a revoked-certificate bypass and an HPACK heap overflow have little in common. At the code level, they share one pattern: one stage reasoned about data in one representation, while a later stage consumed a different representation under the assumption that both still agreed.

  • OCSP produced a revocation result; the stream authorization path consumed only the ordinary verification result.
  • proxy_set_body produced a size_t; the wire header consumed only 24 bits.
  • Rewrite sizing reasoned about a URI; the writer consumed overlapping captures.
  • The HPACK builders reserved a fixed allowance; the encoder consumed a variable-width integer.
  • Stream sizing read one capture state; copying consumed a later capture state.

Every bug is a disagreement across a boundary.

That suggests a useful way to direct future scans. Do not only search for unsafe calls. Search for pairs of operations that are supposed to agree: count and copy, validate and authorize, parse and forward, store and serialize, normalize and compare. Then ask what mutable state, configuration, encoding expansion, or integer width can sit between them.

This is also why hardened targets remain worth scanning. Mature code has fewer isolated mistakes. It still has seams.

What Winfunc has found beyond NGINX

At the time of publication, Winfunc Hacktivity contains 28 public findings across 12 projects, with 19 distinct CVE identifiers. The public set includes 4 Critical, 11 High, and 13 Medium findings.

We were behind the recent CVEs in React and Node.js (one of each). Three additional Chromium CVEs are visible there in redacted form and are not included in those public-detail totals until the original reports are publicly disclosed by the Chromium team.

NGINX is one row in a much stranger table:

ProjectRepresentative Winfunc findingSeverity / status
NGINXThe six findings in this post, plus DAV path overlap and SCGI truncationHigh / Medium
ChromiumV8 type confusion (CVE-2026-10910), ANGLE uninitialized use (CVE-2026-10994), and ANGLE integer overflow (CVE-2026-10019)High / Medium · reports redacted
serovalPromise resolver type confusion during deserializationCritical
ReactRSC $K FormData amplificationHigh
Node.jsPermission Model bypass through Unix-domain socketsMedium
AnthropicFastMCP custom routes skip authenticationCritical
SupabaseQueue-name SQL injectionCritical
BunExponential YAML merge-key denial of serviceHigh
GumroadZero-click account takeover through an authorization bypassCritical
MattermostOversized-password login denial of service, among ten public findingsHigh
Better-AuthForged multi-session cookie revocationMedium
ActixCL.TE request smugglingMedium
HoppscotchCLI sandbox escapeHigh

Every public entry was surfaced autonomously by Winfunc, then reproduced, reviewed, and responsibly disclosed. Autonomy does not remove the human work around coordinated disclosure. Maintainers still deserve a precise report, a stable proof, careful severity language, and time to ship a fix.

The bottleneck has moved upstream: choosing the target, modeling how attackers reach it, and spending finite compute on the seams where two components have to agree.

The public page is behind the private queue. We have additional 0-days in coordinated disclosure now. They are not listed until the affected maintainers have fixed them.

Soon.

And readers, please challenge us to find 0-days in other hardened targets (literally any target we could read the code of). We'll pick them one-by-one, responsibly disclose them, and with their permission, write a detailed report on how we (as in, Winfunc) discovered them.

END_OF_FILE