HexBrain

curl · Report #3970650

Stacked --proto modifiers leave denied protocol enabled

Informativestatus
lowseverity
3upvotes
28 Aug 2026disclosed

How it was found

Summary

proto2num() (line 431–447) consumes only one leading modifier character via a switch statement. The documentation says entries may be "prefixed by zero or more modifiers." Before commit 86ac471d, a loop consumed all modifiers. The replacement switch reads only the first character.

--proto '+-ftp' reads + (action=allow), then passes -ftp to proto_token() (line 466). -ftp is not a recognized protocol name → warning emitted, FTP stays in the default set. --silent suppresses the warning entirely.

The same parser handles --proto-redir, so redirect protocol restrictions are equally bypassable.

Reproduction

python3 poc_proto_bypass.py <sha>
# Denied correctly:
curl --proto '-file' file:///etc/hostname    # exit 1 (protocol denied)

# Bypass:
curl --proto '+-file' file:///etc/hostname   # exit 0 — reads the file!
curl --silent --proto '+-file' file:///etc/hostname  # no warning shown

Root cause

// src/tool_paramhlp.c:431-447
switch(*str++) {        // ← consumes ONE character only
case '=': action = set;   break;
case '-': action = deny;  break;
case '+': action = allow; break;
default:  str--; plen++;  break;
}
// str now points to "-ftp", which proto_token() doesn't recognize

Impact

A trusted wrapper or script that uses the documented stacked-modifier syntax (e.g. --proto '+-ftp' intending to deny FTP after first allowing all) silently leaves the denied protocol enabled. An untrusted party who controls the URL or a redirect target can then reach a protocol the wrapper explicitly tried to block. --proto-redir is equally affected, so a server-controlled 3xx redirect can escalate to file://, gopher://, or ftp:// reads despite the wrapper's restrictions. --silent suppresses the only visible indicator (the "unrecognized protocol" warning). Direct libcurl API callers are not affected — the bug is in the CLI argument parser only.

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original