Nicolas Seriot

Computation > How curl was accidentally Turing-complete for nine months

29th October 2026

From curl 8.12 through 8.16, config files could slice variable values and include other config files without an explicit depth cap. Together, these features let curl simulate any two-counter Minsky program. Under the usual idealization of unbounded strings and resources, this construction was Turing-complete.

Curl 8.17.0 added a five-level include cap that breaks this reduction.

Minsky 2-Counter Reduction

A counter value n is represented by n copies of x.

Each instruction state uses one or more config files, with file names acting as labels, and expand-config selecting the next file.

Syntax:

Minsky Curl config
Register R Variable r (R is the number of x bytes)
INC(R) expand-variable = "r={{r}}x"
DEC(R) expand-variable = "r[1-]={{r}}"
JZ(R, _, _x) expand-variable = "t[0-0]={{r}}"
expand-config = "state_{{t}}.conf"
JMP(S) expand-config = "S.conf"
Halt No further expand-config

With that, we can compile any two-counter program into curl config files.

PoC: Adding 2 + 3

Four files in curl_addition.zip compute 2 + 3.

Build a local curl 8.12.0 binary if needed:

mkdir -p /tmp/curl-tc-build
cd /tmp/curl-tc-build
curl -fsSLO https://curl.se/download/curl-8.12.0.tar.gz
tar -xzf curl-8.12.0.tar.gz
cd curl-8.12.0
./configure --without-ssl --disable-shared --disable-manual --disable-docs
make -j4

Then, from the addition/ directory, run:

/tmp/curl-tc-build/curl-8.12.0/src/curl -q -s -K main.conf

Expected output:

A=xxxxx B=

Runtime Bounds

The reduction assumes unbounded counters and unbounded steps. The real binary has neither:

History and Version Support

The pull request says the cap prevents a config file from including itself indefinitely. Its regression test does exactly that and expects an error. The public explanation does not discuss Turing completeness or why the cap is five.

A Bash while loop can complement bounded curl by invoking a config once per step and carrying the counters and instruction label between invocations. The repetition then comes from Bash, so this is a composition rather than curl-alone Turing completeness.

Security impact

None.