CVE-2026-33630: Verified Reproduction
CVE-2026-33630: c-ares CVE-2026-33630 RCE primitive construction from confirmed remote UAF
CVE-2026-33630 is verified against c-ares/c-ares · c. Affected versions: >1.32.3 through 1.34.6. Fixed in 1.34.7. Vulnerability class: RCE. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00263.
What Is CVE-2026-33630?
CVE-2026-33630 is a high-severity, remotely reachable use-after-free/double-free (CWE-416) in c-ares's query-completion handling, triggerable through the public ares_getaddrinfo() API over TCP DNS. Pruva reproduced it as a vulnerable-only control-flow hijack marker (reproduction REPRO-2026-00263).
CVE-2026-33630 Severity
CVE-2026-33630 is rated high severity.
High — serious impact or readily exploitable. Prioritize remediation.
Affected c-ares/c-ares Versions
c-ares/c-ares · c versions >1.32.3 through 1.34.6 are affected.
How to Reproduce CVE-2026-33630
pruva-verify REPRO-2026-00263 curl -O https://www.pruva.dev/api/v1/reproductions/REPRO-2026-00263/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh Proof of Reproduction for CVE-2026-33630
- reached the target end-to-end
- full exploit chain demonstrated
- on the real production code path
- high confidence
- the upstream fix blocks the same trigger
malicious TCP DNS server responses (FORMERR without OPT, duplicate same-qid NXDOMAIN, TCP reset) plus deterministic heap-reclaim payload supplied through c-ares public allocator API to model attacker-controlled reclaimed heap content
- ares_getaddrinfo(AF_INET) over TCP
- read_answers() deferred ENDQUERY flush
- host_callback() reentrant next_lookup/end_hquery after TCP reset
- hquery_free()
- stale host_callback consumes forged host_query
- callback/arg and executes sentinel
reproduction_steps.sh How the agent worked
Root Cause and Exploit Chain for CVE-2026-33630
CVE-2026-33630 in c-ares is a remotely reachable use-after-free/double-free in query-completion handling that can be triggered through the public ares_getaddrinfo() API over TCP DNS. In c-ares v1.34.6, deferred ENDQUERY processing invokes a query callback while the query remains linked in the channel lookup tables. A malicious TCP DNS peer can drive a reentrant completion path that frees the associated host_query; subsequent stale use can consume reclaimed attacker-shaped fields. This run demonstrates a vulnerable-only benign control-flow hijack marker: under the real TCP DNS trigger and a deterministic public allocator-hook heap reclaim, v1.34.6 executes a sentinel callback from a forged reclaimed host_query, while v1.34.7 never executes the marker.
- Package/component affected: c-ares, specifically
src/lib/ares_process.cdeferred requeue/endquery handling andsrc/lib/ares_getaddrinfo.chost_querycallback completion state. - Affected versions: reproduced on c-ares v1.34.6 (
3ac47ee46edd8ea40370222f91613fc16c434853). - Fixed version/control: c-ares v1.34.7 (
d63b7de3a3568d14ab1351374b205365aed51cca), which contains fix commitd823199b688052dcdc1646f2ab4cb8c16b1c644a. - Risk level and consequences: high. A malicious DNS/TCP peer can drive the vulnerable completion timing through a real resolver API. This run demonstrates that reclaimed
host_querycallback fields can be consumed as control flow in the vulnerable build, which is equivalent to a code-execution primitive in-process when heap content is controlled.
Impact Parity
- Disclosed/claimed maximum impact: code execution/RCE primitive construction from the confirmed remote c-ares UAF/double-free.
- Reproduced impact from this run: vulnerable-only sentinel function execution (
SENTINEL EXECUTION MARKER FIRED) through a forged reclaimedhost_queryobject after a real malicious TCP DNS peer drivesares_getaddrinfo(). - Parity:
full. - Not demonstrated: no shell command execution or external payload execution was attempted. The proof uses a benign in-process sentinel callback as the code-execution/control-flow marker, which the ticket explicitly allowed as an acceptable safe proof form.
Root Cause
In v1.34.6, read_answers() accumulates deferred ENDQUERY entries in a requeue array and later flushes them by looking up the query by QID, invoking query->callback(query->arg, ...), and only then freeing/detaching the query with ares_free_query(query). Because the query remains visible in the channel's queries_by_qid/all_queries structures while its callback is running, callback-driven reentrant resolver activity can find and complete/free related state before the outer completion path has finished. For the ares_getaddrinfo() path, host_callback() may call end_hquery()/hquery_free() during this reentrant sequence, then later stale code continues to operate on the freed host_query pointer.
The fixed code introduces centralized ares_flush_requeue() handling and detaches the query before invoking the callback. In the fixed implementation, the ENDQUERY drain performs ares_detach_query(query) before query->callback(...), so reentrant cancellation/completion cannot rediscover and free the same query or drive the stale host_query consumption window. The reproduction anchors the negative control to v1.34.7, which contains fix commit d823199b688052dcdc1646f2ab4cb8c16b1c644a.
Reproduction Steps
- Use
bundle/repro/reproduction_steps.sh. - The script reuses or clones c-ares into the prepared project cache, checks out v1.34.6 and v1.34.7, verifies that only the fixed checkout contains
ares_flush_requeue, builds static non-sanitizedlibcares.afor both, and compilesbundle/repro/rce_reclaim_harness.cagainst each build. - The harness calls public
ares_getaddrinfo(AF_INET)and sends traffic through a real localhost TCP DNS socket to a malicious peer. The peer sends FORMERR without OPT, a duplicate same-QID NXDOMAIN, observes the follow-on search-domain DNS query, and resets the TCP connection. - The harness uses the public
ares_library_init_mem()allocator hooks to deterministically retain and rewrite freed 144-bytehost_querychunks with a forged callback/arg/addrinfo layout. Success is counted only when c-ares later consumes the forged callback and fires the sentinel. - The script runs 30 vulnerable attempts and 10 fixed attempts. Expected evidence is at least two vulnerable sentinel executions and zero fixed sentinel executions, with TCP DNS boundary evidence in both builds.
Evidence
Key artifacts:
bundle/repro/reproduction_steps.sh— self-contained reproducer.bundle/repro/rce_reclaim_harness.c— C harness using real c-ares public APIs and real TCP DNS peer.bundle/logs/reproduction_steps.log— aggregate build/run/proof log.bundle/logs/rce_reclaim_vuln_attempt*.log— vulnerable attempt logs.bundle/logs/rce_reclaim_fixed_attempt*.log— fixed negative-control logs.bundle/repro/runtime_manifest.json— runtime evidence manifest.bundle/repro/validation_verdict.json— structured verdict.
The latest verified run ended with:
[repro] counts: vuln_boundary_count=30 fixed_boundary_count=10 vuln_forge_count=30 rce_marker_count=4 fixed_marker_count=0
[repro] wrote validation_verdict.json: claim_outcome=confirmed observed_impact_class=code_execution
[repro] proof summary: rce_marker_fired=1 rce_marker_count=4 fixed_marker=0 fixed_marker_count=0 vuln_boundary=1 fixed_boundary=1 controlled_reclaim=1 vuln_runs_ok=1 fixed_runs_ok=1
[repro] SUCCESS: vulnerable-only sentinel code execution marker fired through reclaimed host_query over real TCP DNS path
Representative vulnerable marker evidence:
[server] accepted TCP DNS connection on 127.0.0.1:40863
[server] sending FORMERR without OPT for qid=22298
[server] sending second response with duplicate qid=22298 (NXDOMAIN, no OPT)
[server] observed follow-on search-domain query qid=22298 qtype=1 length=33
[server] resetting TCP connection with SO_LINGER zero
[allocator] FORGED_RECLAIM host_query ptr=0x5588b747d020 callback@24=0x55888b4cbcf9 arg@32=0x7ffeddcb4bc8 ai@112=0x5588b7490e30 remaining@128=1
[RCE] *** SENTINEL EXECUTION MARKER FIRED *** arg=0x7ffeddcb4bc8 status=11 timeouts=0 callback=0x55888b4cbcf9
[result] done=1 status=11 accepted=1 follow_on_seen=1 normal_callbacks=1 forged_host_query=1 forged_callback_consumed=1 rce_marker_fired=1
Representative fixed negative-control evidence shows the same DNS boundary and allocator-forge opportunity but no stale consumption:
[server] accepted TCP DNS connection on 127.0.0.1:42041
[server] sending FORMERR without OPT for qid=24413
[server] sending second response with duplicate qid=24413 (NXDOMAIN, no OPT)
[server] observed follow-on search-domain query qid=24413 qtype=1 length=33
[server] resetting TCP connection with SO_LINGER zero
[allocator] FORGED_RECLAIM host_query ptr=0x55d50d23f020 callback@24=0x55d4d3286cb9 arg@32=0x7fff28da4f38 ai@112=0x55d50d2536f0 remaining@128=1
[result] done=1 status=11 accepted=1 follow_on_seen=1 normal_callbacks=1 forged_host_query=1 forged_callback_consumed=0 rce_marker_fired=0
Environment and source identity captured by the script:
vulnerable checkout v1.34.6 -> 3ac47ee46edd8ea40370222f91613fc16c434853
fixed checkout v1.34.7 -> d63b7de3a3568d14ab1351374b205365aed51cca
vulnerable ares_flush_requeue count: 0
fixed ares_flush_requeue count: 5
Recommendations / Next Steps
- Upgrade c-ares deployments to v1.34.7 or later.
- Preserve the fix pattern: detach queries from all lookup structures before invoking user callbacks, and centralize deferred requeue/endquery draining so callback reentrancy cannot rediscover pending query objects.
- Add regression tests that exercise malicious TCP DNS peers, duplicate-QID/deferred ENDQUERY flows, TCP reset after follow-on query, and callback reentrancy.
- Add allocator-assisted and sanitizer-backed tests that verify no stale
host_queryorares_queryfields are consumed after callback-driven reentrant cleanup.
Additional Notes
- Idempotency confirmation:
bundle/repro/reproduction_steps.shwas run successfully twice consecutively. The first successful full run observed 7 vulnerable marker firings out of 30 and 0 fixed marker firings out of 10. The second successful full run observed 4 vulnerable marker firings out of 30 and 0 fixed marker firings out of 10. - The vulnerable marker is probabilistic because it depends on the exact reentrant stale-use timing, so the script runs multiple bounded attempts and requires at least two vulnerable marker firings while ensuring the fixed build has zero marker firings.
- The proof intentionally uses a benign in-process sentinel callback instead of executing an external command. No sanitizer is used for the primary code-execution proof.
CVE-2026-33630 Reproduction Transcript
The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.
Full session Replay every step — scrub the timeline or play it back.
Artifacts and Evidence for CVE-2026-33630
Scripts, logs, diffs, and output captured during the reproduction.
How to Fix CVE-2026-33630
Upgrade c-ares/c-ares · c to 1.34.7 or later.
FAQ: CVE-2026-33630
How does the c-ares exploitability demonstration work?
Which c-ares versions are affected by CVE-2026-33630, and where is it fixed?
How severe is CVE-2026-33630, and is it a confirmed RCE?
How can I reproduce CVE-2026-33630?
References for CVE-2026-33630
Authoritative sources for CVE-2026-33630 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.