Exploitable Format String Vulnerability in curl_mfprintf Function
What the report claims
The curl_mfprintf function in curl_printf.h contains a format string vulnerability that allows an attacker to inject arbitrary format specifiers, potentially leading to memory disclosure, crashes, or sensitive data leakage.
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
The code provides evidence against the report's central claim. Review the cited lines before deciding.
curl policy: API misuseWhy this finding?
- curl_mfprintf is a printf-family variadic function designed to accept a trusted format string and matching arguments
- The reported behavior only occurs when an application passes user-controlled input as the format string — a clear case of API misuse
- The project policy explicitly lists 'API misuse' as not a security issue: 'If a reported issue only triggers by an application using the API in a way that is not documented to work or even documented to not work, it is probably not going to be considered a security problem.'
- The reporter's own test code demonstrates the misuse: passing a format string with specifiers (%x) but no corresponding variadic arguments
How this analysis ran 6 claims · 8 citations verified
Checked against curl master on 2024-11-04 (3a35901a115e). Dev evaluation split. Citation verification checks that a referenced line was in the evidence; it does not prove the model interpreted it correctly.
Review a draft reply to the reporter
Edit and verify before sending.
Thank you for the report. The curl_mfprintf function is a printf-style variadic function where the format string is expected to be a trusted/constant string provided by the caller, not user-controlled input. The behavior you demonstrate occurs only when an application misuses the API by passing attacker-controlled data as the format string without supplying matching arguments. Per curl's security policy, API misuse is explicitly not considered a security vulnerability. If you believe there is a case where curl itself passes untrusted data as the format string to curl_mfprintf, please provide the specific code path.
Inspect all claims and source code 6 claims · 2 code excerpts
Report claims
curl_mfprintf function contains a format string vulnerability that allows an attacker to inject arbitrary format specifiers
Read the reasoning
The function behaves as a standard printf-family function. The 'vulnerability' only manifests when an application misuses the API by passing user-controlled input as the format string without providing corresponding variadic arguments. This is API misuse, not a flaw in curl_mfprintf itself.
The function allows injection of arbitrary format specifiers
Read the reasoning
The function allows format specifiers in the format string by design — that is its documented purpose. The claim frames intended behavior as a vulnerability.
This can lead to unauthorized access to memory content
Read the reasoning
The function does not read arbitrary memory on its own; any memory exposure requires the application to misuse the API by providing a malicious format string without corresponding arguments.
Potential application crashes
Read the reasoning
A crash from mismatched format specifiers and arguments is a consequence of incorrect API usage, not a vulnerability in the function.
Leakage of sensitive data
Read the reasoning
Same as C3 and C4: the risk only materializes through API misuse, which the project policy explicitly excludes from security issues.
Exploitable format string vulnerability in curl_mfprintf function
Read the reasoning
The claim summarizes the preceding points. The function has no flaw; the reporter's test case demonstrates API misuse by passing user input as the format string with no matching arguments.
Read the original report
Source code
| 1193 | int curl_mfprintf(FILE *whereto, const char *format, ...) |
| C1: curl_mfprintf is a variadic printf-style function that takes a format string and corresponding arguments; the format string is expected to be a trusted/constant string, not user-controlled input | |
| C2: Function signature shows it accepts a format string followed by variadic arguments matching the format specifiers | |
| C3: Unauthorized memory access would only occur if the caller passes a format string with specifiers but fails to supply matching arguments — a caller bug, not a curl bug | |
| C4: Crashes would only result from API misuse (e.g., format string expecting arguments that are not provided) | |
| C5: Data leakage would require the application to pass a user-controlled format string — an API misuse scenario | |
| C6: The function is a standard printf variant; the reported 'exploitable vulnerability' is the function working as designed when misused | |
| 1194 | { |
| 1195 | int retcode; |
| 1196 | va_list ap_save; /* argument pointer */ |
| 1197 | va_start(ap_save, format); |
| 1198 | retcode = formatf(whereto, fputc_wrapper, format, ap_save); |
| C1: The function passes the format string directly to formatf, which is the intended design for a printf-family function | |
| C2: formatf processes the format string with the provided va_list; if the caller passes a user-controlled format string without matching arguments, that is caller error | |
| 1199 | va_end(ap_save); |
| 1200 | return retcode; |
| 1201 | } |
| 227 | int main(int argc, char *argv[]) |
| 228 | #endif |
| 229 | { |
| 230 | CURLcode result = CURLE_OK; |
| 231 | struct GlobalConfig global; |
| 232 | memset(&global, 0, sizeof(global)); |
| 233 | |
| 234 | tool_init_stderr(); |
| 235 | |
| 236 | #ifdef _WIN32 |
| 237 | /* Undocumented diagnostic option to list the full paths of all loaded |
| 238 | modules. This is purposely pre-init. */ |
| 239 | if(argc == 2 && !_tcscmp(argv[1], _T("--dump-module-paths"))) { |
| 240 | struct curl_slist *item, *head = GetLoadedModulePaths(); |
| 241 | for(item = head; item; item = item->next) |
| 242 | printf("%s\n", item->data); |
| 243 | curl_slist_free_all(head); |
| 244 | return head ? 0 : 1; |
| 245 | } |
| 246 | /* win32_init must be called before other init routines. */ |
| 247 | result = win32_init(); |
| 248 | if(result) { |
| 249 | errorf(&global, "(%d) Windows-specific init failed", result); |
| 250 | return (int)result; |
| 251 | } |
| 252 | #endif |
| 253 | |
| 254 | if(main_checkfds()) { |
| 255 | errorf(&global, "out of file descriptors"); |
| 256 | return CURLE_FAILED_INIT; |
| 257 | } |
| 258 | |
| 259 | #if defined(HAVE_SIGNAL) && defined(SIGPIPE) |
| 260 | (void)signal(SIGPIPE, SIG_IGN); |
| 261 | #endif |
| 262 | |
| 263 | /* Initialize memory tracking */ |
| 264 | memory_tracking_init(); |
| 265 | |
| 266 | /* Initialize the curl library - do not call any libcurl functions before |
| 267 | this point */ |
| 268 | result = main_init(&global); |
| 269 | if(!result) { |
| 270 | /* Start our curl operation */ |
| 271 | result = operate(&global, argc, argv); |
| 272 | |
| 273 | /* Perform the main cleanup */ |
| 274 | main_free(&global); |
| 275 | } |
| 276 | |
| 277 | #ifdef _WIN32 |
| 278 | /* Flush buffers of all streams opened in write or update mode */ |
| 279 | fflush(NULL); |
| 280 | #endif |
| 281 | |
| 282 | #ifdef __VMS |
| 283 | vms_special_exit(result, vms_show); |
| 284 | #else |
| 285 | return (int)result; |
| 286 | #endif |
| 287 | } |