CodeVetter
← All unpacks
CodeVetter · Repo Unpack evidence

curl/curl

Scanned commit c362f03469 dated 2026-09-22 — last upstream commit. Generated by codevetter 1.12.0 on 2026-09-22.

github.com/curl/curl ↗ · 4000 files · 14.1 MB · scan capped

| | | | \| | / | | | | |) | | | (| || | <| | \|\/|| \\| README Curl is a command line tool for transferring data specified with URL syntax.

Deep analysis by claude-opus-5 via the claude CLI on 2026-09-22 (590s) — every claim below links to its cited source files.

Overview

This is the curl project at 8.23.0-DEV: a C89-portable transfer library (libcurl, `lib/`, ~393 files) plus the `curl` command-line tool (`src/`, ~96 files) that is a thin client of that library. libcurl speaks ~25 URI schemes (HTTP/1-2-3, FTP(S), SMTP/IMAP/POP3, SCP/SFTP, LDAP, MQTT, RTSP, TFTP, DICT, Gopher, Telnet, WS(S), file) through a scheme registry of `struct Curl_scheme` records, and layers transport concerns (happy-eyeballs, SOCKS, HTTP proxy, HAProxy, TLS, QUIC, HTTP/2) as a stackable chain of connection filters rather than protocol-specific socket code. What is distinctive is the amount of pluggability compiled in: six TLS backends, two QUIC backends, two SSH backends, three DNS resolver strategies, ~50 `CURL_DISABLE_*` build knobs, and a ~2,100-case integration test suite driven by in-tree protocol servers. The audience is everyone from distro maintainers embedding libcurl to contributors adding a protocol or a command-line option.

System map

Two build artefacts share one repo: `lib/` builds libcurl, `src/` builds the `curl` tool on top of the public headers in `include/curl/`. The tool owns argv parsing, output files, globbing and retries; libcurl owns URL parsing, connection reuse, the multi state machine, and the filter chain that actually moves bytes. Backends live in `lib/vtls` (TLS), `lib/vquic` (QUIC/HTTP3), `lib/vssh` (SCP/SFTP), `lib/vauth` (SASL/NTLM/Kerberos), `lib/vdns` (resolvers + DoH), with `lib/curlx/` as the portability/utility layer shared by both. There is no database — persistence is flat files (cookie jar, HSTS, alt-svc, TLS session cache) plus whatever the user redirects output to. Two parallel build systems (autotools via `configure.ac`/`Makefile.am` and CMake via a 93KB `CMakeLists.txt`) are both first-class and CI-verified against each other.

All 15 system map claims →

Feature catalog

User-facing surface splits in two. The `curl` tool exposes ~298 documented command-line options plus higher-level conveniences: URL globbing, parallel transfers, retry policies, ETag compare/store, `--write-out` templating (including JSON), config files, user-defined `--variable` expansion, `--libcurl` source generation, and xattr metadata. libcurl exposes ~91 documented API functions and ~422 documented options, covering the easy, multi, share, URL, header, mime, and WebSocket APIs. Protocol coverage is the headline feature: HTTP/1.1, HTTP/2, HTTP/3, FTP(S), SFTP/SCP, SMTP/IMAP/POP3, LDAP(S), MQTT, RTSP, TFTP, DICT, Gopher, Telnet, WS(S), and local `file`. Authentication and proxying are each their own subsystem with many interchangeable mechanisms.

All 15 feature catalog claims →

Data flow

Input boundaries are argv, `.curlrc`/`-K` config files, environment variables, `.netrc`, stdin uploads, and the network. argv is normalised into a linked list of `struct OperationConfig` (one per `--next`), which `config2setopts.c` translates wholesale into `curl_easy_setopt()` calls; from there the state owner is `struct Curl_easy` (`data->set` for user intent, `data->state`/`data->req` for per-request state). The URL becomes a `CURLU` via lib/urlapi.c, resolves to a `struct Curl_scheme`, and is matched against the connection pool before a filter chain is built. Bytes in from the network flow up through `Curl_xfer_write_resp()` → `Curl_client_write()` → an ordered writer stack → `CURLOPT_WRITEFUNCTION`; bytes out flow down through the mirror-image client reader chain. Output boundaries are the write callbacks (which the tool points at files or stdout), the header callback, the progress callback, and the file-backed caches flushed at cleanup.

All 15 data flow claims →

Behavior traces

Three flows explain most of the codebase: tool startup, a single serial transfer, and the multi state machine that both serial and parallel modes ultimately run on. The tool never calls sockets directly — it builds `per_transfer` records, sets options, and calls `curl_easy_perform()` (serial) or feeds a `CURLM` (parallel). Inside libcurl, `curl_easy_perform()` is itself a multi loop, so every transfer walks `MSTATE_INIT` → … → `MSTATE_MSGSENT` in `multi_runsingle()`. Connection establishment is a re-entrant loop inside one filter (`cf_setup_connect`) that appends the next filter and restarts the sub-chain connect until the whole stack is up.

All 15 behavior traces claims →

Testing signals

curl's testing is unusually broad and almost entirely in-tree. The centre of gravity is `tests/data/` — 2,119 XML-ish test-case files run by `tests/runtests.pl` against protocol servers curl itself ships (sws, socksd, tftpd, mqttd, rtspd, dnsd, plus Perl/Python FTP/TFTP/RTSP/DICT/telnet servers). Around that sit 80 C unit tests for library internals, 6 `tunit` tests for tool-only code, 273 `libtest` programs exercising the public API, and 31 pytest modules that test HTTP/2, HTTP/3, proxying, SSL and WebSockets against real nghttpx/caddy/vsftpd. Each run can be repeated in torture mode (fail every allocation in turn), under valgrind, or event-based. Coverage gaps are structural rather than accidental: platform-specific code (Windows/VMS/AmigaOS/MSDOS branches) and the rarer TLS/QUIC backend combinations can only be exercised by the matching CI job.

All 15 testing signals claims →

Risk map

curl's risk profile is dominated by the fact that it parses hostile input (URLs, headers, server responses, redirect targets) in C, on every platform, across dozens of optional backends. The highest-attention paths are credential handling (.netrc, `-u`, redirects that must drop auth), filename derivation from server-controlled `Content-Disposition`, the redirect/protocol allowlist, and the TLS/QUIC backend glue. Structurally, the biggest fragility is combinatorial: ~50 `CURL_DISABLE_*` knobs times six TLS backends times two QUIC backends times platform `#ifdef`s means many buildable configurations that no single CI job exercises. Blast-radius hotspots are the few central files every protocol funnels through — lib/multi.c, lib/url.c, lib/sendf.c, lib/cfilters.c — where a regression is not protocol-local.

All 15 risk map claims →

Extension points

curl is extended by adding a record to a table, not by subclassing. New URI schemes are `struct Curl_scheme` records pointing at a `struct Curl_protocol` vtable; new transport behaviour is a `struct Curl_cftype` inserted into the filter chain; new response processing is a `struct Curl_cwtype` registered at a phase; new TLS/SSH/DNS backends are entries in a backend array guarded by a `USE_*` define. On the tool side, a new command-line option means one row in the alphabetical `aliases[]` table, one `C_*` enum value, one case in `getparameter()`, and one curldown page. Several of these tables are additionally mirrored by generated files or documentation that CI verifies.

All 15 extension points claims →

Contributor handoff

Treat this repo as two coupled codebases with one very strict style contract. Read the internals docs before the code — docs/internals/ explains the four architectural ideas (connection filters, client writers, client readers, the multi state machine) that the code assumes you already know. Style is machine-enforced: `scripts/checksrc.pl` runs in CI and by default in debug builds, and a style violation fails the build before your logic is ever reviewed. Anything user-visible needs a matching curldown doc and usually a test case, and several files are generated and must not be hand-edited. The safest edits are additive table rows; the riskiest are changes to lib/multi.c, lib/url.c, lib/sendf.c, or lib/cfilters.c, which every protocol depends on.

All 16 contributor handoff claims →

Languages

LanguageFilesShare of source
C104392%
Markdown930docs/config
Python515%
Shell303%
YAML30docs/config
C++20%
TOML20%
JSON1docs/config

Start reading here

Probable source entrypoint: lib/ — inferred from the directory tree and manifest, not the upstream docs.

Source roots

lib/ (393 files) src/ (96 files)

Repository structure

Top-level pathFiles
tests/2178
docs/1070
lib/393
src/96
projects/74
.github/53
scripts/40
CMake/31

Docs found: READMEREADME.mddocs/ALTSVC.mddocs/BINDINGS.mddocs/BUG-BOUNTY.mddocs/BUGS.mddocs/CIPHERS-TLS12.mddocs/CIPHERS.mddocs/CODE_OF_CONDUCT.mddocs/CODE_REVIEW.md

CI & config entrypoints

Structural health signals

Average score 10/10 across 0 analyzed source files; 0 hotspots surfaced.

These are deterministic review leads — size, churn, and structural signals — not proof of a bug in this project.

Recent history