Stained-glass internet streams branching into isolated lifecycle stores

HTTP/2 server push allows a server to offer an additional resource before the client explicitly requests it. Most proxy data-collection jobs do not need this feature, but applications that deliberately enable push must manage the parent transfer, accepted push handles, shared connection caches, and cleanup order as one lifecycle.

This guide provides a controlled way to audit that lifecycle. It is informed by CVE-2026-18924, published by the curl project on September 2, 2026. The low-severity issue could cause a use-after-free during cleanup when a specific combination of HTTP/2 push and shared connections was active. curl 8.22.0 contains the fix.

The goal is not to send unusual traffic to public sites. Build a small authorized fixture, prove whether your application can reach the affected path, upgrade precisely, and preserve enough evidence to prevent a regression.

Confirm all trigger conditions

The official advisory requires all of these conditions:

  1. a libcurl application enables HTTP/2 push with CURLMOPT_PUSHFUNCTION;
  2. the application shares connections using CURL_LOCK_DATA_CONNECT;
  3. the transfer uses HTTPS and negotiates HTTP/2;
  4. the server sends an HTTP/2 push;
  5. the callback accepts that push.

The curl command-line tool is not affected. A libcurl application that never enables a push callback is outside this exact trigger. So is a client that rejects every push, never shares connections, or only negotiates HTTP/1.1.

Affected curl versions are 7.44.0 through 8.21.0. curl 8.22.0 and later are fixed. Inventory runtime behavior instead of inferring exposure from an HTTP/2 library, proxy plan, or package name.

Why proxy teams should still test

Proxies add routing and pooling layers that can obscure the negotiated protocol and ownership of a connection. A request may use HTTP/2 to the origin through an HTTP CONNECT tunnel, HTTP/2 to a proxy, or a different protocol on each hop. Server push belongs to the HTTP/2 peer that offered it, not to the residential exit identity.

An accurate audit separates:

  • client-to-proxy protocol;
  • proxy-to-origin behavior when visible to the client;
  • origin HTTP version after tunneling;
  • parent easy handle and accepted push handle;
  • shared connection cache identity;
  • callback decision and cleanup result.

Changing proxy exits is not a remediation for a local memory-lifecycle bug. Upgrade the affected client and validate the exact code path.

Build an isolated fixture

Use a disposable test process, an HTTPS endpoint owned by your organization, and harmless static resources. Configure the endpoint to offer one small push when the client requests a parent document. Give every run a unique case identifier.

Prepare four baseline modes:

  • HTTP/1.1 without push;
  • HTTP/2 with no push callback;
  • HTTP/2 with a callback that rejects the push;
  • HTTP/2 with a callback that accepts the push.

Run each mode first without connection sharing, then with a correctly synchronized share handle using CURL_LOCK_DATA_CONNECT. This matrix identifies which feature transition introduces the relevant lifecycle.

Do not test against an unrelated public server. Do not attempt to induce crashes in production. Keep the fixture content non-sensitive, rate-limited, and isolated from downstream ingestion.

Instrument ownership before testing

Assign stable internal identifiers to:

  • the multi handle;
  • each easy handle;
  • the share handle;
  • the parent transfer;
  • every offered push;
  • the accepted push handle;
  • the connection-cache entry;
  • the cleanup phase.

Log state transitions, not secrets. Useful fields include timestamp, case ID, parent ID, push ID, callback decision, HTTP version, proxy route class, new-or-reused connection, result code, and cleanup completion.

Never record proxy passwords, authorization headers, cookies, private URLs, response bodies, or raw memory contents.

Execute the lifecycle matrix

For every mode:

  1. start a fresh test process and create the share and multi handles;
  2. attach the required lock callbacks before sharing connection data;
  3. issue the parent HTTPS request;
  4. record the negotiated HTTP version and connection identity;
  5. when a push is offered, record the callback decision;
  6. allow accepted parent and push transfers to complete normally;
  7. remove completed handles in a documented order;
  8. destroy easy handles, multi handle, and share handle according to application ownership;
  9. confirm the process exits cleanly and every expected destructor event occurs once;
  10. repeat under a debug or memory-safety build in an isolated CI job.

The advisory notes that a debug build can provide strong hints and assertions for the affected sequence. Use sanitizers and debug builds only in a controlled environment; they may change timing and are not substitutes for a production upgrade.

Add concurrency and failure cases

After the single-push baseline passes, add bounded cases one at a time:

  • parent completes before the accepted push;
  • push completes before the parent;
  • callback rejects one push and accepts another;
  • transfer is canceled during response processing;
  • proxy tunnel closes cleanly after completion;
  • network timeout occurs before cleanup;
  • connection is eligible for reuse by another handle;
  • multi loop pauses and resumes;
  • application shuts down with no active transfers.

Keep concurrency low and deterministic. The objective is lifecycle coverage, not load testing. A high request rate makes ownership bugs harder to attribute and can violate endpoint or proxy limits.

Compare direct and proxy routes

Run the same fixture through:

  • direct authorized access as a control;
  • one HTTP proxy route;
  • one HTTPS CONNECT proxy route;
  • each HTTP/2-capable proxy mode your application explicitly supports.

The callback and cleanup outcome should be consistent. If server push disappears on one route, record that as protocol behavior rather than declaring the code safe. You still need a route that actually reaches every trigger condition.

Use the HTTP/2 proxy connection reuse audit to verify pool boundaries, and the proxy latency attribution guide to separate handshake, tunnel, origin, and application timing.

Upgrade and rollout

The preferred response is curl 8.22.0 or later. If that cannot be deployed immediately, the advisory recommends avoiding HTTP/2 server push or avoiding the affected connection-sharing pattern. Disabling unused push is usually the simpler temporary control.

For rollout:

  1. update the library through the normal dependency process;
  2. confirm the runtime loads the intended build, not a bundled older copy;
  3. restart long-lived workers;
  4. run established shared pools;
  5. rerun the complete acceptance matrix;
  6. compare error rate, process restarts, memory-safety findings, and connection reuse;
  7. canary the change before fleet-wide deployment.

Do not claim remediation from a package lockfile alone. Record the runtime curl version and build identity from the process that serves the workload.

Acceptance checklist

  • [ ] The runtime curl/libcurl version is recorded.
  • [ ] Push callback use is confirmed or ruled out.
  • [ ] Shared connection data use is confirmed or ruled out.
  • [ ] HTTPS and negotiated HTTP/2 are observed in the fixture.
  • [ ] Accepted and rejected push paths are both tested.
  • [ ] Parent and child ownership is explicit.
  • [ ] Each handle and cache object is cleaned up exactly once.
  • [ ] Debug or sanitizer tests finish without relevant findings.
  • [ ] Direct and approved proxy routes are compared.
  • [ ] Production workers load curl 8.22.0 or a verified patched build.
  • [ ] Logs exclude credentials and sensitive content.
  • [ ] Disabled push remains disabled unless there is a documented business need.

FAQ

Is every HTTP/2 client affected?

No. The advisory requires a specific libcurl combination: enabled and accepted server push, shared connection data, HTTPS, and HTTP/2. Confirm each condition.

Is curl command line affected?

No. The curl project states that this issue affects libcurl applications, not the command-line tool.

Will rotating the proxy IP prevent the problem?

No. Rotation changes network routing or exits. It does not correct handle ownership and cleanup inside the client process.

Should a collector enable server push?

Only with a documented need, clear ownership, tests, and observability. If the application does not use pushed resources, rejecting or disabling push reduces complexity.

Source and responsible-use note

Internal research basis: curl Project Security Advisory, “HTTP/2 server push UAF,” CVE-2026-18924, published September 2, 2026; curl 8.22.0 release information. External research URLs are retained only in the internal operations record; this public article contains no external links.

Test only applications, endpoints, proxy accounts, and networks you own or are authorized to assess. Respect destination terms, provider limits, privacy requirements, and organizational change-control procedures.