✓ProveIt
Examples / Report #3459636 Saved analysis

Stack Buffer Overflow in cURL wolfSSL Backend (lib/vtls/wolfssl.c)

curl · 2025-12-0915.1s analysis · $0.015 in model calls

What the report claims

A stack-based buffer overflow exists in the wssl_strerror function of cURL's wolfSSL TLS backend due to an unsafe strcpy call that ignores buffer size when DEBUGASSERT is disabled in release builds.

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 code defect is real: in release builds, wssl_strerror uses strcpy without bounds checking, relying solely on a DEBUGASSERT that is compiled out.
  • The provided source does not include the callers of wssl_strerror, so it cannot be determined whether an attacker can cause a buffer smaller than 13 bytes to be passed.
  • The project policy does not categorically exclude this type of flaw (it exists in release builds, not debug-only), but exploitability must be established.
  • A human maintainer should audit the call sites in lib/vtls/wolfssl.c to see if any path from network input can reach wssl_strerror with an undersized buffer.
What still needs checking
  • Callers of wssl_strerror in lib/vtls/wolfssl.c (not provided in the source snippet)
  • Evidence that a buffer ≤ 12 bytes can be passed from attacker-influenced code paths
How this analysis ran 5 claims · 7 citations verified

Checked against curl master on 2025-12-09 (a7c974e03857). Test evaluation split. Citation verification checks that a referenced line was in the evidence; it does not prove the model interpreted it correctly.

1 · Grounding
grounded
no model · 4 references checked out, 0 did not
2 · Claims
NVIDIA-Nemotron-3-Nano-30B-A3B
5 claims · 1651 tokens · $0.0002
3 · Evidence
3 code snippets
real curl source at a7c974e03857
4 · Judgment
Nemotron-3-Ultra-550b-a55b
7864 tokens · 12.4s · $0.0152
5 · Receipts
7 of 8 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 report. The code confirms that wssl_strerror uses strcpy without a bounds check in release builds (DEBUGASSERT is disabled). However, the provided source does not show the function's callers. To assess exploitability, we need to know whether any code path from network input can call wssl_strerror with a buffer smaller than 13 bytes. Could you provide the call chain or point to the specific caller(s) in lib/vtls/wolfssl.c that pass the buffer and size arguments?

Inspect all claims and source code 5 claims · 3 code excerpts

Report claims

C1flaw supported

The function wssl_strerror uses an unsafe strcpy call that does not respect the buffer size parameter, leading to a stack-based buffer overflow when DEBUGASSERT is disabled.

Read the reasoning

In release builds DEBUGASSERT is a no-op, so the strcpy at line 1552 executes with no bounds check. The function's contract (size > 40) is enforced only in debug builds.

C2location supported

The flaw occurs in the wssl_strerror function at lines 1542-1556 of lib/vtls/wolfssl.c, specifically at line 1552 where strcpy(buf, msg) is executed.

Read the reasoning

The provided source snippet confirms the function location and the exact line of the strcpy call.

C3trigger supported

The vulnerability is triggered when the function is called with a buffer size of 40 bytes or less, or more specifically when a buffer of 12 bytes is passed and the error string "Unknown error" (13 bytes including null terminator) is copied.

Read the reasoning

The code shows that when wolfSSL_ERR_error_string_n writes nothing (buf[0] == '\0'), the fallback string is copied unconditionally. A buffer of 12 bytes is too small for "Unknown error" (needs 13), so overflow occurs. The report's '40 bytes or less' refers to the DEBUGASSERT threshold; the actual overflow threshold is 13 bytes for non-zero error.

C4impact not verifiable

The overflow corrupts adjacent stack memory, potentially leading to denial of service or arbitrary code execution.

Read the reasoning

The provided code does not show callers of wssl_strerror. Whether an attacker can cause a small buffer to be passed depends on the call chain, which is not in the provided source. The impact claim (DoS or code execution) is plausible for a stack overflow but not demonstrated as reachable in curl.

C5reproduction supported

A test program compiled with AddressSanitizer demonstrates the overflow by writing 14 bytes into a 12-byte stack buffer via the strcpy call in wssl_strerror.

Read the reasoning

The PoC code (provided in the report) correctly models the vulnerable logic and demonstrates the overflow with AddressSanitizer. However, the PoC is a standalone simulation, not a curl test case.

poc.c:0
Read the original report

Full report on HackerOne ↗

**Summary:** A stack-based buffer overflow exists in the wssl_strerror function of cURL's wolfSSL TLS backend. The function uses an unsafe strcpy call, relying solely on a DEBUGASSERT macro for boundary checking. This macro is disabled in production release builds (-DNDEBUG), allowing memory corruption when the function is called with a buffer size parameter of 40 bytes or less. **Affected Component:** File: lib/vtls/wolfssl.c Function: wssl_strerror (lines 1542-1556) Vulnerable Code: Line 1552: strcpy(buf, msg); Proof of Concept: The vulnerability is confirmed by compiling and executing the following test program, which simulates the function in a release build context: Create the test file poc.c: #include <stdio.h> #include <string.h> // Simulates wssl_strerror in a RELEASE build (DEBUGASSERT is a no-op) static char *wssl_strerror(unsigned long error, char *buf, unsigned long size) { *buf = '\0'; // Simulate wolfSSL_ERR_error_string_n writing nothing to the buffer if(!*buf) { const char *msg = error ? "Unknown error" : "No error"; strcpy(buf, msg); // VULNERABLE CALL: ignores `size` } return buf; } int main() { // This buffer is too small for "Unknown error" + null terminator (needs 13 bytes) char small_buffer[12]; wssl_strerror(1, small_buffer, 12); // This will overflow printf("Result: %s\n", small_buffer); return 0; } **Compile with AddressSanitizer to detect memory corruption:** gcc -fsanitize=address -g -o poc poc.c **Execute the program to trigger the overflow:** ./poc **Observed Result:** The program terminates due to a stack-buffer-overflow detected by AddressSanitizer. The diagnostic output shows a 14-byte write overflowing a 12-byte stack buffer, with the trace leading directly to the strcpy call inside wssl_strerror. ## Impact ## Summary: This buffer overflow corrupts adjacent stack memory. As the wssl_strerror function is part of cURL's TLS error handling path, which processes data influenced by external network communication, this vulnerability could potentially lead to: Denial of Service: Application crash. Arbitrary Code Execution: Under specific conditions, an attacker could exploit the memory corruption to hijack control flow. The severity is heightened because libcurl is a ubiquitous library embedded in countless applications and devices.

Source code

lib/vtls/wolfssl.clines 1542–1556 · definition of wssl_strerror
1542static char *wssl_strerror(unsigned long error, char *buf, unsigned long size)
C2: Function definition starts at line 1542
1543{
1544 DEBUGASSERT(size > 40);
C1: DEBUGASSERT(size > 40) only active in debug builds; in release builds (-DNDEBUG) it expands to nothing
1545 *buf = '\0';
1546
1547 wolfSSL_ERR_error_string_n(error, buf, size);
1548
1549 if(!*buf) {
1550 const char *msg = error ? "Unknown error" : "No error";
C3: msg = error ? "Unknown error" : "No error"; "Unknown error" is 12 chars + NUL = 13 bytes
1551 /* the string fits because the assert above assures this */
C1: Comment acknowledges the assert is the only guarantee: 'the string fits because the assert above assures this'
1552 strcpy(buf, msg);
C1: strcpy(buf, msg) copies without checking the 'size' parameter; msg is "Unknown error" (13 bytes with NUL) or "No error" (8 bytes with NUL)
C2: strcpy(buf, msg) at line 1552
C3: strcpy writes the full string including NUL regardless of 'size'
1553 }
1554
1555 return buf;
1556}
lib/vtls/wolfssl.c@curl-8_17_0lines 1527–1542 · definition of wssl_strerror as in release curl-8_17_0; differs from master; commits that changed it since: 2253bc330f lib/subdirs: fix formatting nits
1527static char *wssl_strerror(unsigned long error, char *buf,
1528 unsigned long size)
1529{
1530 DEBUGASSERT(size > 40);
1531 *buf = '\0';
1532
1533 wolfSSL_ERR_error_string_n(error, buf, size);
1534
1535 if(!*buf) {
1536 const char *msg = error ? "Unknown error" : "No error";
1537 /* the string fits because the assert above assures this */
1538 strcpy(buf, msg);
1539 }
1540
1541 return buf;
1542}
src/curlinfo.clines 248–260 · definition of main
Show 13 lines (not cited by the judge)
248int main(int argc, char **argv)
249{
250 size_t i;
251
252 (void)argc;
253 (void)argv;
254
255 for(i = 0; i < CURL_ARRAYSIZE(disabled); i++)
256 /* !checksrc! disable BANNEDFUNC 1 */
257 printf("%s\n", disabled[i]);
258
259 return 0;
260}