Open-Source Wikis

/

Pingora

/

Security

cloudflare/pingora

Security

Pingora's "reasons to use" list opens with security: a memory-safe alternative to C/C++ proxies. This page covers what that means in practice, plus the trust boundaries and security hygiene the codebase enforces.

Memory safety

Pingora is 100% safe Rust except for narrow unsafe blocks in:

  • TLS backend FFI (pingora-openssl, pingora-boringssl, pingora-s2n) — calls into C TLS libraries
  • Low-level POSIX syscalls (pingora-core/src/server/transfer_fd/) — SCM_RIGHTS FD passing

The unsafe surface is small enough to audit in an afternoon. The TLS library choice is the largest unmanaged-memory dependency.

Trust boundaries

graph LR
    Untrusted["Untrusted: client TCP/TLS"]
    Listener["Listener<br/>(pingora-core/src/listeners)"]
    Filter["ConnectionFilter<br/>(optional)"]
    TLS["TLS handshake"]
    Session["HTTP session<br/>(pingora-core)"]
    Proxy["ProxyHttp impl<br/>(user code)"]
    Connector["Upstream connector<br/>(pingora-core)"]
    Upstream["Upstream<br/>(semi-trusted)"]

    Untrusted --> Listener --> Filter --> TLS --> Session --> Proxy --> Connector --> Upstream

The clear trust boundary is between the L4 listener and the application code. Everything below Filter is treated as adversarial; everything above is application logic.

Connection filtering

The connection_filter cargo feature lets a ConnectionFilter reject connections before TLS handshake based on remote IP, peer address, or any other L4-visible attribute. Useful for IP blocklists, geo-rejection, or rate limiting at the edge of the trust boundary. See TLS options.

Input validation

The HTTP/1 parser (pingora-core/src/protocols/http/v1/server.rs) uses httparse (workspace dependency, version 1). The 0.8.0 release added stricter validation:

  • Reject invalid Content-Length on HTTP/1 requests to eliminate ambiguous request framing.
  • Validate Content-Length on HTTP/1 responses by default; remove Content-Length when Transfer-Encoding is also present (RFC compliance).

The HTTP/2 implementation uses the h2 crate (workspace dependency, >=0.4.11). The version pin floor exists because h2 versions before 0.4.11 had RST_STREAM handling bugs.

CONNECT method

In 0.8.0, CONNECT proxying is disabled by default. Servers had been seeing it used as an attack vector (HTTP smuggling). Enable it explicitly via server options if your service intentionally supports CONNECT.

Timeouts

Untrusted-input handling needs timeouts. Pingora applies them at:

  • TCP accept (configurable via listeners)
  • TLS handshake (tls_handshake_timeout per peer)
  • HTTP/1 read (read_timeout per session)
  • HTTP/1 write (write_timeout per session) — used consistently on H2 body writes as of 0.7.0
  • H2 application read (sends RST_STREAM CANCEL on application read timeouts as of 0.7.0)

If you don't set timeouts, defaults apply. They are not "infinite."

TLS

  • Pre-set cipher lists. TlsSettings::intermediate and TlsSettings::modern use the Mozilla-recommended cipher lists.
  • Cert verification on by default for upstreams. Set verify_cert: false on HttpPeer.options only if you mean it.
  • Hostname verification is separate from cert verification. Both are recommended.
  • mTLS support is built in (0.7.0). See TLS options.
  • Client cert verification for mTLS configuration was added in 0.8.0.

Secret handling

Pingora doesn't manage secrets itself. The Sentry integration is configured via the YAML config; if your DSN contains a secret, your config file is sensitive. The TLS keys are loaded from disk paths you supply.

The codebase carefully avoids logging request headers wholesale. Custom proxy code that logs headers should redact Authorization, Cookie, and similar.

Dependency security

  • .github/workflows/audit.yml runs cargo audit on every push.
  • .github/workflows/semgrep.yml (added Apr 2026) runs Semgrep OSS rules.
  • The 0.7.0 release upgraded lru to >=0.16.3 because of RUSTSEC-2026-0002.
  • The 0.7.0 release also removed atty (RUSTSEC).
  • Workspace deps pin h2 = ">=0.4.11" to dodge known HTTP/2 vulns.

Sandboxing and process privilege

The YAML config supports user: and group: to drop privileges after binding listening ports. Useful when you need to bind low ports but don't want to run as root.

Reporting vulnerabilities

The README and CONTRIBUTING file point at opensource@cloudflare.com for general questions. Cloudflare runs a HackerOne program for vulnerability reports — the README doesn't link directly but the parent cloudflare/.github org repository has the canonical security policy.

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

Security – Pingora wiki | Factory