✓ProveIt
Examples / Report #887462 Saved analysis

CVE-2020-8177: curl overwrite local file with -J

curl · 2020-05-3021.0s analysis · $0.020 in model calls

What the report claims

curl allows server-controlled local file override via Content-disposition filename when using -OJi, bypassing verification and potentially enabling RCE.

Compare with curl's recorded outcome

Known vulnerability

A real vulnerability: CVE-2020-8177 curl overwrite local file with -J

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?
  • Claim C3 (asymmetric -iJ vs -Ji handling) is supported by the verified quoted option-parsing logic.
  • The core vulnerability claims (C1, C4, C6) depend on src/tool_cb_hdr.c and src/tool_cb_wrt.c, which are not included in the provided source excerpts. The deterministic checks confirm the report's quoted snippets exist in the repository, but the surrounding context (existence checks, code paths reachable via -OJi) is missing.
  • External sources do not explicitly confirm the claim about the standard forbidding opening existing files.
  • This is a known CVE (CVE-2020-8177), but the provided materials are insufficient to independently verify the exploit path.
What still needs checking
  • src/tool_cb_hdr.c (header callback implementation, especially the Content-disposition handling and rename logic)
  • src/tool_cb_wrt.c (standard file-opening flow with existence check)
How this analysis ran 6 claims · 0 citations verified

Checked against curl master on 2020-05-30 (fc55c723c4ec). 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
partially grounded
no model · 6 references checked out, 2 did not
2 · Claims
NVIDIA-Nemotron-3-Nano-30B-A3B
6 claims · 1781 tokens · $0.0002
3 · Evidence
2 code snippets
real curl source at fc55c723c4ec · 3 docs via Tavily
4 · Judgment
Nemotron-3-Ultra-550b-a55b
9009 tokens · 18.1s · $0.0195
5 · Receipts
0 of 1 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 asymmetric handling of -iJ vs -Ji (claim C3) is confirmed by the option-parsing logic. However, to evaluate the core file-overwrite claims (C1, C4, C6), we need the full src/tool_cb_hdr.c and src/tool_cb_wrt.c files from the relevant revision. The provided excerpts do not include these files. Could you confirm the exact code paths in tool_cb_hdr.c that are reached when using -OJi, and whether the standard flow in tool_cb_wrt.c performs an existence check that the -OJi path skips?

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

Report claims

C1flaw not verifiable

curl does not verify that the filename= argument does not exist before opening it

Read the reasoning

The claim references src/tool_cb_hdr.c line 196, but this file is not provided in the curl_source section. The deterministic checks confirm the report's quoted code block exists in the repository, but the surrounding context needed to verify whether a filename existence check is missing is not available in the provided materials.

C2flaw not verifiable

The standard Content-disposition handling flow does not allow opening existing files

Read the reasoning

The claim references src/tool_cb_wrt.c line 54, but this file is not provided. The external sources (E1, E2, E3) discuss RFC 6266 but do not explicitly state that the standard 'does not allow opening existing files'; they state recipients 'MUST NOT be able to write into any location other than one to which they are specifically entitled' (E3), which is a different requirement. The deciding curl code is not provided.

C3flaw supported

curl -Ji is available but curl -iJ is not supported

Read the reasoning

The report quotes the option-parsing code for 'i' and 'J' flags. The deterministic checks confirm this quoted code exists in the repository. The logic shows: 'i' sets config->show_headers; 'J' checks if config->show_headers is set and returns PARAM_BAD_USE if so. Therefore -iJ fails (i runs first, sets show_headers, then J errors), while -Ji succeeds (J runs first, sets content_disposition, then i sets show_headers). This confirms the asymmetry.

deterministic check
C4flaw not verifiable

Using -OJi allows overriding a local file with response headers without verification

Read the reasoning

The claim depends on the header callback flow in src/tool_cb_hdr.c, which is not provided. The deterministic checks confirm the quoted rename block exists, but the conditions that reach this code (specifically whether -OJi bypasses the normal existence check) cannot be verified without the full file.

C5flaw not verifiable

The implementation falsely claims that .bashrc was refused to be overwritten

Read the reasoning

The claim about a false warning message requires examining the warning logic in the header callback, which is in src/tool_cb_hdr.c (not provided).

C6flaw not verifiable

Server can override arbitrary local files without path traversal when curl runs in specific directories

Read the reasoning

This claim synthesizes C1, C4, and C5. The deciding code (the header callback path reachable via -OJi) is in src/tool_cb_hdr.c, which is not provided. The quoted rename snippet shows a rename without an explicit existence check, but reachability and the attacker-controlled filename path cannot be confirmed from provided materials.

Deterministic checks that failed

  • line none of warnf, fclose, rename, strerror appear near line 54 at bc677a8f16a5; it reads: 'base = slash + 1;'
  • line none of warnf, fclose, rename, strerror appear near line 196 at bc677a8f16a5; it reads: ''

What the report says about other projects

not addressed The standard Content-disposition handling flow does not allow opening existing files

Read the original report (excerpt)

Full report on HackerOne ↗

## Summary: curl supports the `Content-disposition` header, including the `filename=` option. By design, curl does not allow server-provided local file override by verifying that the `filename=` argument does not exist before opening it. However, the implementation contains 2 minor logical bugs that allow a server to override an arbitrary local file (without path traversal) when running curl with specific command line args (-OJi) This bug can trigger a logical RCE when curl is used from the user's home dir (or other specific directories), by overriding specific files (e.g. ".bashrc"), while keeping the user completely uninformed of the side effects. The 2 bugs are: 1. `curl -iJ` is not supported however `curl -Ji` is available - 2. The standard `Content-disposition` handling flow does not allow opening existing files: https://github.com/curl/curl/blob/master/src/tool_cb_wrt.c#L54, however by using `-OJi` it is possible to reach a flow that overrides a local file with the response headers, without verification: https://github.com/curl/curl/blob/master/src/tool_cb_hdr.c#L196 ## Steps To Reproduce: 1. Return the following http response form a server : ``` HTTP/1.1 200 OK <PAYLOAD> Content-disposition: attachment; filename=".bashrc" ``` Where `<PAYLOAD>` is the bash payload, e.g. `echo pwn` 2. Run `curl -OJi` from the user's home dir **Note that curl falsely claims that `.bashrc` was refused to be overwritten.** ## Supporting Material/References: First bug: ```c case 'i': config->show_headers = toggle; /* show the headers as well in the general output stream */ break; ... case 'J': /* --remote-header-name */ if(config->show_headers) { warnf(global, "--include and --remote-header-name cannot be combined.\n"); return PARAM_BAD_USE; } config->content_disposition = toggle; break; ``` Second bug: ```c if(filename) { if(outs->stream) { int rc; /* already opened and possibly written to */ if(outs->fopened) fclose(outs->stream); outs->stream = NULL; /* rename the initial file name to the new file name */ rc = rename(outs->filename, filename); if(rc != 0) { warnf(per->config->global, "Failed to rename %s -> %s: %s\n", ou …

Source code

lib/memdebug.hlines 171–172 · definition of Curl_safefree
171#define Curl_safefree(ptr) \
172 do { free((ptr)); (ptr) = NULL;} while(0)
src/tool_msgs.clines 100–106 · definition of warnf
100void warnf(struct GlobalConfig *config, const char *fmt, ...)
101{
102 va_list ap;
103 va_start(ap, fmt);
104 voutf(config, WARN_PREFIX, fmt, ap);
105 va_end(ap);
106}