Open-Source Wikis

/

curl

/

Security

curl/curl

Security

curl is a security-critical project. It runs untrusted input through dozens of parsers, talks to arbitrary servers, manages credentials and trust roots, and is embedded in billions of devices. The project takes this seriously — there is a published vulnerability disclosure policy, a HackerOne-administered bug bounty, and a long history of CVE handling.

Reporting a vulnerability

Do not open a public GitHub issue or mailing-list message for a suspected security flaw.

The disclosure policy lives in docs/VULN-DISCLOSURE-POLICY.md. The headline points:

  • 90-day standard embargo
  • Maintainer-coordinated disclosure with CNA assignment via curl's CNA scope
  • Reports triaged within 24 hours by the security team
  • Advisories published with patches at https://curl.se/docs/security.html

Trust boundaries

Boundary What is on each side
Application ↔ libcurl Application sets options, libcurl receives bytes from arbitrary servers
libcurl ↔ network peer Server-controlled bytes flow through every parser in lib/
libcurl ↔ proxy Even authenticated proxies can inject arbitrary headers
libcurl ↔ TLS backend Backend has its own attack surface; curl validates certificates and pins keys
libcurl ↔ resolver DNS responses (or DoH responses) can be untrusted
Application user ↔ filesystem Cookie jar, HSTS file, alt-svc file, .netrc are written and read

The defaults assume the network is hostile, the server is untrusted, and the resolver may be lying.

Defensive practices in the codebase

  • Memory tracking: lib/memdebug.c wraps every allocation in debug builds; the test suite injects allocation failures via torture mode (tests/runtests.pl -t) to exercise error paths.
  • Fuzzing: OSS-Fuzz has run libcurl since July 2017. Harnesses are under tests/fuzz/.
  • CI sanitizers: AddressSanitizer, UndefinedBehaviorSanitizer, MemorySanitizer in .github/workflows/linux.yml. CodeQL in .github/workflows/codeql.yml.
  • Strict format checks: mprintf.c is curl's own printf implementation that handles 64-bit args portably and is checked by scripts/checksrc.pl.
  • Bounded parsing: lib/curlx/strparse.c is the project's non-allocating tokeniser; new parsers should use it rather than ad-hoc loops.
  • Style enforcement: scripts/checksrc.pl blocks risky idioms (e.g. strcpy, strcat, unbounded format strings).
  • Public Suffix List: cookies are scoped via libpsl in lib/psl.c to prevent setting a cookie for .com or .co.uk.
  • .onion refusal: curl refuses to resolve .onion hostnames by default to avoid DNS leak (since May 2023). Override via CURLOPT_DOH_URL or routing through a SOCKS proxy.
  • HSTS: persisted between runs via CURLOPT_HSTS.
  • Multiple TLS backends mean multiple sets of trust-root quirks. See TLS backends.
  • The Mozilla CA bundle generator scripts/mk-ca-bundle.pl produces a curl-friendly PEM file from certdata.txt.
  • Pinning is supported via CURLOPT_PINNEDPUBLICKEY and --pinnedpubkey and is back-end agnostic.
  • Cipher suite naming is portable across backends via lib/vtls/cipher_suite.c.
  • TLS session tickets are cached in lib/vtls/vtls_scache.c and shareable via the share interface.

Authentication considerations

  • Credentials may come from CURLOPT_USERPWD, ~/.netrc, or per-protocol options. They are never logged in trace output (the trace output redacts headers).
  • The connection cache does use credential-affecting options as part of the connection key — two requests with different users do not share a connection.
  • NTLM and Negotiate are connection-bound: a connection authenticated as user A is not reused for user B.

Specific risks called out in the docs

docs/KNOWN_RISKS.md enumerates accepted risks (truncated list):

  • HTTP redirect to FILE/SCP/SFTP can leak local data (mitigated by CURLOPT_REDIR_PROTOCOLS_STR).
  • TLS handshake error messages may leak internal state.
  • Long-running connections can outlive their security context.
  • Reading .netrc is line-based; do not store anything but credentials there.

CVE history

curl publishes detailed advisories at https://curl.se/docs/security.html. The release-notes file RELEASE-NOTES includes a security-fix bullet for every advisory shipped with that release. The repo also keeps .git-blame-ignore-revs to keep git blame accurate across mass formatting changes — an indirect aid to security review.

Threat model for new code

When adding code that touches the network, ask:

  1. What is the attacker-controlled input? Headers, body bytes, DNS responses, certificate fields, redirect URLs.
  2. Where is the trust boundary? Usually before the first allocation or string copy.
  3. Is there a length cap? If you are reading until a delimiter, the cap is on the total amount of bytes you are willing to allocate.
  4. Is the result being mixed with subsequent unauthenticated bytes? If yes, ensure invariants for the next layer.
  5. Is there a similar parser elsewhere? Reuse lib/curlx/strparse.c and lib/dynhds.c rather than rolling a new tokenizer.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Security – curl wiki | Factory