Caddy enforces a secure-by-default architecture for HTTP routing, TLS provisioning, and proxy handling, but requires explicit developer configuration to secure administrative APIs, sensitive internal proxies, and untrusted client inputs. Developers must assume that unconstrained listeners, missing proxy trust boundaries, and insecure credential storage will directly expose the server to remote compromise or data leakage. Security-sensitive surfaces include administrative endpoints, file traversal paths, reverse proxy upstreams, and authentication providers, all of which must fail closed when validation checks fail.
Essential implementation rules
Restrict Administrative API Access and Enforce Origin Checks
Bind administrative endpoints strictly to loopback addresses or secure Unix domain sockets with explicit octal mode bits. Set enforce_origin: true and specify explicit allowed origins to prevent unauthorized configuration modifications and cross-site requests.
Configure Trusted Upstream Proxies and Network Boundaries
Explicitly define trusted proxy CIDRs using trusted_proxies and restrict proxy_protocol listener sources to prevent IP spoofing and malicious header injection. Always validate client identities and enforce strict right-to-left header evaluation.
Use Constant-Time Comparisons and Argon2id for Passwords
Hash user credentials using the Argon2id algorithm with cryptographically secure salts. Ensure credential verifiers execute constant-time comparisons and invoke fake hash operations for non-existent accounts to mitigate timing side-channel attacks.
Enforce Strict Client Authentication and PKI Validation
Configure mutual TLS enforcement modes to require_and_verify and ensure custom client certificate verifiers explicitly return errors upon validation failure. Validate key pair consistency and supply complete intermediate certificate trust chains.
Sanitize File Paths and Restrict Document Roots
Map untrusted HTTP request paths to local filesystem destinations using caddyhttp.SanitizedPathJoin rather than standard library path join functions. Ensure document roots and script paths remain isolated within intended base directories to prevent traversal attacks.
Normalize Request Paths and Validate FastCGI Split Paths
Write path matchers using unescaped characters to rely on automatic path cleaning and normalization. Specify pure ASCII substrings for FastCGI split_path configurations to prevent Unicode equivalence and case folding misidentifications.
Enforce Strict Protocol Versioning and Proxy Transport Controls
Restrict minimum TLS protocol versions to tls1.2 or tls1.3 and configure reverse proxy transport layers to send PROXY protocol headers only to trusted upstream servers. Restrict non-idempotent HTTP methods on early data requests by responding with status code 425.
Encode Untrusted URI Components and Render Template Inputs Safely
Use URL-escaped placeholders such as http.request.uri_escaped when constructing dynamic configurations, headers, or redirects. Apply stripHTML or contextual escaping functions to untrusted input rendered within template responses.
Enforce Memory, Buffer, and Timeout Limits on HTTP Services
Configure positive byte bounds on request and response buffers in reverse proxy configurations, limit file browsing entry counts via file_limit, and set explicit read, header, and idle timeouts to prevent resource exhaustion and slowloris attacks.
Define Absolute Runtime Environment Variables for Storage
Explicitly set HOME, USERPROFILE, and XDG_* environment variables in systemd service or container manifests to prevent Caddy from storing sensitive cryptographic assets and state in working directory relative paths.
Load Secrets Dynamically and Redact Sensitive Log Fields
Supply sensitive keys, API tokens, and credentials dynamically using environment variable placeholders instead of hardcoding values in configuration files. Configure explicit log filters to automatically redact sensitive query parameters and cookie headers.
Enforce Explicit Directive Execution Order via Route Blocks
Wrap dependent directives in an explicit route block to override default pipeline sorting when security controls like authentication or header validation must execute before request rewrites or proxy forwarding.
caddy: All Security Cards
Approximately 4,943 tokens
On this card
Category: access control
Configure Explicit Access Control and Boundary Rules for Caddy Endpoints and Services
Use when
When defining server listeners, routing policies, forwarding authentication headers, and administrative API access boundaries to enforce authorization constraints.
Secure rules
Rule 1: Enforce explicit route path segment boundaries and origin checks when configuring remote administrative permissions and local admin API access.
When configuring RemoteAdmin permissions using AdminAccess rules, Caddy enforces path prefix checks strictly at path segment boundaries. Ensure path permissions rely on path-segment boundaries to restrict access to sensitive routes. Additionally, set enforce_origin: true and specify explicit allowed origins in origins on admin configuration to prevent cross-site requests or unauthorized configuration modifications.
Rule 2: Restrict client-supplied identity headers and enforce default-deny policies for certificate issuance and proxy forwarding.
When using forward_auth with copy_headers, rely on the directive to automatically strip client-supplied request headers matching copy_headers before proxying requests, preventing attackers from injecting arbitrary identity or role values. Furthermore, explicitly define allow rule sets for trusted domain names and IP ranges when configuring the ACME server certificate issuance policy to enforce default-deny behavior.
When configuring Unix domain socket addresses for Caddy listeners, append octal file mode bits using the pipe syntax to ensure that owner write permission bits are present and unauthorized local processes are prevented from interacting with socket listeners.
Configure Password Verification and Hashing with Constant-Time Comparison
Use when
When implementing or configuring user credential authentication and password verification mechanisms in Caddy HTTP authentication providers.
Secure rules
Rule 1: Supply pre-hashed password strings in Modular Crypt Format or bcrypt.
When configuring HTTP Basic Authentication, ensure password strings are properly hashed using Modular Crypt Format starting with ‘$’ or base64 encoding to prevent credential leakage in plain configuration files.
Rule 2: Execute constant-time comparisons and fake hashes against non-existent users.
When verifying user credentials or custom authentication modules, use Compare to execute constant-time key comparisons and execute a dummy comparison using FakeHash() when an account does not exist to prevent timing side-channel attacks.
var hasher caddyauth.Argon2idHashuser, found := userDB.Find(username)var hashToCompare []byteif found { hashToCompare = user.PasswordHash} else { hashToCompare = hasher.FakeHash()}valid, err := hasher.Compare(hashToCompare, []byte(suppliedPassword))if err != nil || !found || !valid { return errors.New("invalid username or password")}
Enforce Client Authentication and Verify Certificate Identity
Use when
When establishing mutual TLS (mTLS) authentication and verifying peer or client certificate credentials.
When configuring Mutual TLS via the client_auth block under the tls directive, set the enforcement mode to require_and_verify to guarantee that client certificates are cryptographically validated before granting access.
Rule 2: Propagate errors explicitly from custom client certificate verifiers.
When implementing custom ClientCertificateVerifier modules, ensure that any certificate validation failure explicitly returns a non-nil error so Caddy rejects unauthenticated connections during verifyConnection.
func (v *CustomCertVerifier) VerifyClientCertificate(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { if len(verifiedChains) == 0 { return errors.New("client certificate chain is required") } return nil}
Category: boundary control
Configure Trusted Proxies and Allowed Networks to Enforce Trust Boundaries
Use when
Configuring Caddy behind upstream load balancers, reverse proxies, or when accepting PROXY protocol connections from external sources.
When deploying Caddy behind upstream proxies or load balancers, explicitly set trusted_proxies to specific IP addresses or CIDR ranges. By default, Caddy does not trust client-supplied headers and will drop or overwrite them unless the request originates from a configured trusted proxy.
When configuring the proxy_protocol listener wrapper in Caddy to extract client connection metadata, explicitly restrict trusted proxy CIDRs using the allow property to prevent untrusted clients from injecting arbitrary PROXY headers and spoofing the remote client address.
Enforce secure HTTPS and authentication for remote configuration and certificate loaders
Use when
When loading dynamic Caddy configurations or root CA certificates over the network using remote endpoints.
Secure rules
Rule 1: Always use HTTPS endpoints and explicit TLS client/CA credentials when retrieving remote server configurations or dynamic CA certificates.
Prevent network attackers from altering configuration settings or injecting malicious root certificates by using secure https:// URLs and configuring TLS settings, such as RootCAPEMFiles, ClientCertificateFile, and ClientCertificateKeyFile, instead of unencrypted plain HTTP.
Configure Secure TLS Protocol Versions and Cipher Selection
Use when
Configuring TLS server protocols, minimum version thresholds, cipher suites, curves, and cryptographic parameters in Caddy.
Secure rules
Rule 1: Restrict minimum TLS protocol versions to secure standards and avoid weak cryptographic primitives.
When customizing TLS connection policies or protocol blocks, keep minimum protocol thresholds restricted to tls1.2 or tls1.3 to prevent downgrade attacks and cryptanalytic vulnerabilities.
example.com { tls { protocols tls1.2 tls1.3 }}
Hash Passwords Securely Using Argon2id and Cryptographically Secure Salts
Use when
Hashing user passwords for authentication configurations and implementing password verification comparers.
Secure rules
Rule 1: Use the Argon2id algorithm with cryptographically secure random salts and constant-time verification.
Prefer the Argon2id hashing algorithm over older algorithms when hashing user passwords, rely on crypto/rand for salt generation, and ensure custom hashing comparers use constant-time comparison operations.
Rule 1: Validate key pair consistency and ensure complete intermediate certificate chains are provided.
When configuring custom PKI key pairs or internal certificate authorities, ensure that private keys match lead certificate public components and supply complete intermediate certificate trust chains in a single PEM bundle.
Safely Join File Paths and Restrict Document Roots
Use when
When mapping untrusted HTTP request paths, FastCGI configurations, or template file operations to local filesystem paths.
Secure rules
Rule 1: Use sanitized path join functions and enforce document root isolation
When mapping untrusted HTTP request paths to local filesystem paths in custom Caddy HTTP modules, use caddyhttp.SanitizedPathJoin(root, reqPath) rather than standard library functions like filepath.Join or path.Join. Ensure root directories and FastCGI script destinations resolve to an intended base directory to prevent directory traversal attacks.
Validate and Restrict FastCGI SplitPath Configurations to ASCII
Use when
Configuring FastCGI script execution boundaries and split paths where untrusted input or Unicode characters could lead to boundary confusion.
Secure rules
Rule 1: Specify pure ASCII substrings for FastCGI split_path configurations.
When configuring split_path for FastCGI script execution, ensure you only specify pure ASCII substrings such as .php. Non-ASCII code points are rejected during module provisioning because Unicode equivalence and case folding can lead to misidentified script boundaries and potential remote code execution.
Canonicalize and Normalize Request Paths and Certificate PEM Blocks
Use when
When configuring HTTP path matchers, routing rules, or decoding certificate PEM structures in Caddy to ensure unambiguous input interpretation and prevent security bypasses.
Secure rules
Rule 1: Write path matchers using unescaped characters and standard wildcard patterns to rely on automatic path cleaning and normalization.
Caddy normalizes request paths including downcasing, slash merging, and converting Windows backslashes, operating in unescaped path space by default. Define standard path matchers using unescaped characters so that Caddy’s path cleaning protects against bypass attempts, and use %* only when explicitly targeting raw percent-encoded sequences.
When processing individual certificate PEM payloads, ensure the input buffer contains strictly one PEM block with the header block type CERTIFICATE and no trailing bytes or secondary blocks. For multi-certificate bundles, always use chain-aware parsing functions.
cert, err := pemDecodeCertificate(pemDER)if err != nil { // Handle multiple blocks, wrong PEM block type, or invalid DER data}
Category: interface protocol hardening
Enforce Strict Protocol and Header Validation for Upstream Proxy Transport
Use when
When configuring reverse proxy transport layers and proxy protocol parameters to communicate with upstream servers.
Secure rules
Rule 1: Configure reverse proxy transport to send PROXY protocol headers only to trusted upstream servers.
When forwarding client requests to upstream backends that rely on client network context, set the proxy_protocol setting to v1 or v2 on the transport. Ensure that upstream services accept PROXY protocol headers exclusively from trusted proxies on controlled network segments.
Restrict Non-Idempotent Requests During Early Data and Enforce Strict Framing
Use when
When configuring HTTP matching rules and transport settings to handle early data requests or protocol version restrictions safely.
Secure rules
Rule 1: Restrict non-idempotent HTTP methods when processing uncompleted TLS handshakes or early data.
When matching requests via MatchTLS, QUIC or TLS 1.3 0-RTT early data requests can be processed before handshakes are completed. Restrict non-idempotent HTTP methods by responding with status code 425 (Too Early) to mitigate replay attacks.
Rule 2: Configure HTTP/3 reverse proxy transport with exclusive version listing and explicit TLS configuration.
When specifying HTTP/3 (3) in the reverse proxy transport versions array, ensure that TLS is enabled via a non-nil tls block and that 3 is the sole version listed in the versions slice.
Restrict network boundaries and proxy listener access
Use when
Configuring network interfaces, proxy binding, and trusted client IP ranges across trust boundaries in Caddy.
Secure rules
Rule 1: Configure Caddy’s admin endpoint listener to bind strictly to loopback interfaces or Unix domain sockets.
Explicitly define the admin listener address to a restricted loopback address or Unix socket to prevent exposing the unauthenticated control interface to public networks.
Rule 2: Configure trusted proxy IP ranges when evaluating client IP addresses and headers.
Specify explicit upstream proxy IP ranges using trusted_proxies and enable strict right-to-left header evaluation to prevent header spoofing and unauthorized IP manipulation.
{ servers { trusted_proxies static 10.0.1.0/24 }}
Category: output encoding
Encode Untrusted URI Components and Template Inputs to Prevent Output Injection
Use when
When constructing dynamic Caddy configurations, headers, redirect targets, or rendering untrusted user input within Caddy template responses and markdown files.
Secure rules
Rule 1: Use URL-escaped placeholders when referencing HTTP URI components inside dynamic configurations, headers, or redirects.
When referencing HTTP URI components inside dynamic Caddy configurations, headers, or redirect targets, use URL-escaped placeholders such as http.request.uri_escaped, http.request.uri.path_escaped, and http.request.uri.query_escaped instead of raw unescaped values. This ensures special characters and control delimiters remain encoded and prevents HTTP response splitting, header injection, or query parameter ambiguity vulnerabilities.
Rule 2: Sanitize untrusted input using stripHTML and contextual escaping in template files.
Developers outputting untrusted user input within Caddy template responses should use stripHTML or contextual escaping to prevent cross-site scripting attacks. Pipe untrusted inputs through stripHTML or apply html escaping functions to dynamic content rendered via file and HTTP includes.
Enforce Memory and Buffer Limits on HTTP Requests, Responses, and File Browsing
Use when
Use when configuring Caddy servers, reverse proxies, and file servers to handle incoming client traffic and backend payloads securely without exhausting memory resources.
Secure rules
Rule 1: Set explicit positive bounds on request and response buffer sizes in reverse proxy configurations.
Avoid setting request_buffers or response_buffers to -1 or unconstrained values. Always specify positive byte limits to prevent malicious clients or upstreams from consuming excessive memory during payload handling.
Rule 2: Limit the maximum number of entries returned during directory browsing.
Explicitly configure file_limit in the file server browse configuration to cap the maximum number of directory entries loaded and rendered in memory per request, avoiding resource exhaustion from vast directory structures.
Rule 3: Configure explicit timeouts and header size limits on HTTP servers.
Set explicit read_timeout, read_header_timeout, and idle_timeout values on server configurations, and retain or define max_header_bytes to bound memory consumption and prevent slowloris connection exhaustion attacks.
Configure Explicit Home and XDG Environment Variables for Production Runtime Storage
Use when
Deploying Caddy as a system service or container manifest in production environments to ensure runtime storage resolves to secure absolute paths instead of falling back to working directories.
Secure rules
Rule 1: Explicitly define standard home and application data environment variables in deployment service files prior to execution.
Set environment variables such as HOME, USERPROFILE, XDG_DATA_HOME, XDG_CONFIG_HOME, and XDG_CACHE_HOME explicitly in systemd service definitions or container configurations. This prevents Caddy from falling back to storing sensitive cryptographic assets, private TLS keys, and internal state in a relative ./caddy folder within the current working directory.
[Service]Environment=HOME=/var/lib/caddyEnvironment=XDG_DATA_HOME=/var/lib/caddy/.local/shareExecStart=/usr/bin/caddy run --config /etc/caddy/Caddyfile
Category: secret handling
Load Credentials and Secrets Dynamically Using Environment Variables and Placeholders
Use when
Configuring issuers, certificates, and sensitive keys in Caddyfile or JSON configurations.
Secure rules
Rule 1: Use environment variable placeholders instead of hardcoding sensitive account keys and credentials in configuration files.
Supply private keys, MAC keys, and API credentials dynamically using environment variable placeholders such as {$ACME_ACCOUNT_KEY} or {env.ZEROSSL_API_KEY} in your configuration files to avoid exposing secrets in version control or backups.
Rule 2: Avoid passing plaintext passwords via command line flags when generating credentials or hashes.
Omit the --plaintext argument when using caddy hash-password so that Caddy interactively prompts for the password or receives it securely through standard input, preventing exposure in process listings and history files.
Redact and Filter Sensitive Data in Log Outputs and Storage
Use when
Configuring log filters, file storage permissions, and security-sensitive log options.
Secure rules
Rule 1: Configure explicit log filters to automatically redact sensitive query parameters and cookie headers from logs.
Use QueryFilter and CookieFilter log field filters in your logging configuration to purge or replace sensitive fields like access_token and session_id before logs are written.
Enforce explicit directive ordering with route blocks
Use when
Configuring Caddyfile directives where security controls like authentication or header validation depend on strict execution sequence relative to request rewrites or proxy handlers.
Secure rules
Rule 1: Wrap dependent directives in an explicit route block to override default pipeline sorting and enforce literal top-to-bottom execution.
Caddy sorts directives automatically according to a predefined pipeline where rewrites execute before authentication controls. When security controls must run before request modifications, use an explicit route block to ensure execution order and prevent authorization bypasses.
Configure Explicit Access Control and Boundary Rules for Caddy Endpoints and Services
Approximately 507 tokens
Use when
When defining server listeners, routing policies, forwarding authentication headers, and administrative API access boundaries to enforce authorization constraints.
Secure rules
Rule 1: Enforce explicit route path segment boundaries and origin checks when configuring remote administrative permissions and local admin API access.
When configuring RemoteAdmin permissions using AdminAccess rules, Caddy enforces path prefix checks strictly at path segment boundaries. Ensure path permissions rely on path-segment boundaries to restrict access to sensitive routes. Additionally, set enforce_origin: true and specify explicit allowed origins in origins on admin configuration to prevent cross-site requests or unauthorized configuration modifications.
Rule 2: Restrict client-supplied identity headers and enforce default-deny policies for certificate issuance and proxy forwarding.
When using forward_auth with copy_headers, rely on the directive to automatically strip client-supplied request headers matching copy_headers before proxying requests, preventing attackers from injecting arbitrary identity or role values. Furthermore, explicitly define allow rule sets for trusted domain names and IP ranges when configuring the ACME server certificate issuance policy to enforce default-deny behavior.
When configuring Unix domain socket addresses for Caddy listeners, append octal file mode bits using the pipe syntax to ensure that owner write permission bits are present and unauthorized local processes are prevented from interacting with socket listeners.
Configure Password Verification and Hashing with Constant-Time Comparison
Approximately 603 tokens
Use when
When implementing or configuring user credential authentication and password verification mechanisms in Caddy HTTP authentication providers.
Secure rules
Rule 1: Supply pre-hashed password strings in Modular Crypt Format or bcrypt.
When configuring HTTP Basic Authentication, ensure password strings are properly hashed using Modular Crypt Format starting with ‘$’ or base64 encoding to prevent credential leakage in plain configuration files.
Rule 2: Execute constant-time comparisons and fake hashes against non-existent users.
When verifying user credentials or custom authentication modules, use Compare to execute constant-time key comparisons and execute a dummy comparison using FakeHash() when an account does not exist to prevent timing side-channel attacks.
var hasher caddyauth.Argon2idHashuser, found := userDB.Find(username)var hashToCompare []byteif found { hashToCompare = user.PasswordHash} else { hashToCompare = hasher.FakeHash()}valid, err := hasher.Compare(hashToCompare, []byte(suppliedPassword))if err != nil || !found || !valid { return errors.New("invalid username or password")}
Enforce Client Authentication and Verify Certificate Identity
Use when
When establishing mutual TLS (mTLS) authentication and verifying peer or client certificate credentials.
When configuring Mutual TLS via the client_auth block under the tls directive, set the enforcement mode to require_and_verify to guarantee that client certificates are cryptographically validated before granting access.
Rule 2: Propagate errors explicitly from custom client certificate verifiers.
When implementing custom ClientCertificateVerifier modules, ensure that any certificate validation failure explicitly returns a non-nil error so Caddy rejects unauthenticated connections during verifyConnection.
func (v *CustomCertVerifier) VerifyClientCertificate(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { if len(verifiedChains) == 0 { return errors.New("client certificate chain is required") } return nil}
Configure Trusted Proxies and Allowed Networks to Enforce Trust Boundaries
Approximately 323 tokens
Use when
Configuring Caddy behind upstream load balancers, reverse proxies, or when accepting PROXY protocol connections from external sources.
When deploying Caddy behind upstream proxies or load balancers, explicitly set trusted_proxies to specific IP addresses or CIDR ranges. By default, Caddy does not trust client-supplied headers and will drop or overwrite them unless the request originates from a configured trusted proxy.
When configuring the proxy_protocol listener wrapper in Caddy to extract client connection metadata, explicitly restrict trusted proxy CIDRs using the allow property to prevent untrusted clients from injecting arbitrary PROXY headers and spoofing the remote client address.
Enforce secure HTTPS and authentication for remote configuration and certificate loaders
Approximately 323 tokens
Use when
When loading dynamic Caddy configurations or root CA certificates over the network using remote endpoints.
Secure rules
Rule 1: Always use HTTPS endpoints and explicit TLS client/CA credentials when retrieving remote server configurations or dynamic CA certificates.
Prevent network attackers from altering configuration settings or injecting malicious root certificates by using secure https:// URLs and configuring TLS settings, such as RootCAPEMFiles, ClientCertificateFile, and ClientCertificateKeyFile, instead of unencrypted plain HTTP.
Configure Secure TLS Protocol Versions and Cipher Selection
Approximately 480 tokens
Use when
Configuring TLS server protocols, minimum version thresholds, cipher suites, curves, and cryptographic parameters in Caddy.
Secure rules
Rule 1: Restrict minimum TLS protocol versions to secure standards and avoid weak cryptographic primitives.
When customizing TLS connection policies or protocol blocks, keep minimum protocol thresholds restricted to tls1.2 or tls1.3 to prevent downgrade attacks and cryptanalytic vulnerabilities.
example.com { tls { protocols tls1.2 tls1.3 }}
Hash Passwords Securely Using Argon2id and Cryptographically Secure Salts
Use when
Hashing user passwords for authentication configurations and implementing password verification comparers.
Secure rules
Rule 1: Use the Argon2id algorithm with cryptographically secure random salts and constant-time verification.
Prefer the Argon2id hashing algorithm over older algorithms when hashing user passwords, rely on crypto/rand for salt generation, and ensure custom hashing comparers use constant-time comparison operations.
Rule 1: Validate key pair consistency and ensure complete intermediate certificate chains are provided.
When configuring custom PKI key pairs or internal certificate authorities, ensure that private keys match lead certificate public components and supply complete intermediate certificate trust chains in a single PEM bundle.
Safely Join File Paths and Restrict Document Roots
Approximately 208 tokens
Use when
When mapping untrusted HTTP request paths, FastCGI configurations, or template file operations to local filesystem paths.
Secure rules
Rule 1: Use sanitized path join functions and enforce document root isolation
When mapping untrusted HTTP request paths to local filesystem paths in custom Caddy HTTP modules, use caddyhttp.SanitizedPathJoin(root, reqPath) rather than standard library functions like filepath.Join or path.Join. Ensure root directories and FastCGI script destinations resolve to an intended base directory to prevent directory traversal attacks.
Validate and Restrict FastCGI SplitPath Configurations to ASCII
Approximately 192 tokens
Use when
Configuring FastCGI script execution boundaries and split paths where untrusted input or Unicode characters could lead to boundary confusion.
Secure rules
Rule 1: Specify pure ASCII substrings for FastCGI split_path configurations.
When configuring split_path for FastCGI script execution, ensure you only specify pure ASCII substrings such as .php. Non-ASCII code points are rejected during module provisioning because Unicode equivalence and case folding can lead to misidentified script boundaries and potential remote code execution.
Canonicalize and Normalize Request Paths and Certificate PEM Blocks
Approximately 311 tokens
Use when
When configuring HTTP path matchers, routing rules, or decoding certificate PEM structures in Caddy to ensure unambiguous input interpretation and prevent security bypasses.
Secure rules
Rule 1: Write path matchers using unescaped characters and standard wildcard patterns to rely on automatic path cleaning and normalization.
Caddy normalizes request paths including downcasing, slash merging, and converting Windows backslashes, operating in unescaped path space by default. Define standard path matchers using unescaped characters so that Caddy’s path cleaning protects against bypass attempts, and use %* only when explicitly targeting raw percent-encoded sequences.
When processing individual certificate PEM payloads, ensure the input buffer contains strictly one PEM block with the header block type CERTIFICATE and no trailing bytes or secondary blocks. For multi-certificate bundles, always use chain-aware parsing functions.
cert, err := pemDecodeCertificate(pemDER)if err != nil { // Handle multiple blocks, wrong PEM block type, or invalid DER data}
Enforce Strict Protocol and Header Validation for Upstream Proxy Transport
Approximately 529 tokens
Use when
When configuring reverse proxy transport layers and proxy protocol parameters to communicate with upstream servers.
Secure rules
Rule 1: Configure reverse proxy transport to send PROXY protocol headers only to trusted upstream servers.
When forwarding client requests to upstream backends that rely on client network context, set the proxy_protocol setting to v1 or v2 on the transport. Ensure that upstream services accept PROXY protocol headers exclusively from trusted proxies on controlled network segments.
Restrict Non-Idempotent Requests During Early Data and Enforce Strict Framing
Use when
When configuring HTTP matching rules and transport settings to handle early data requests or protocol version restrictions safely.
Secure rules
Rule 1: Restrict non-idempotent HTTP methods when processing uncompleted TLS handshakes or early data.
When matching requests via MatchTLS, QUIC or TLS 1.3 0-RTT early data requests can be processed before handshakes are completed. Restrict non-idempotent HTTP methods by responding with status code 425 (Too Early) to mitigate replay attacks.
Rule 2: Configure HTTP/3 reverse proxy transport with exclusive version listing and explicit TLS configuration.
When specifying HTTP/3 (3) in the reverse proxy transport versions array, ensure that TLS is enabled via a non-nil tls block and that 3 is the sole version listed in the versions slice.
Restrict network boundaries and proxy listener access
Approximately 240 tokens
Use when
Configuring network interfaces, proxy binding, and trusted client IP ranges across trust boundaries in Caddy.
Secure rules
Rule 1: Configure Caddy’s admin endpoint listener to bind strictly to loopback interfaces or Unix domain sockets.
Explicitly define the admin listener address to a restricted loopback address or Unix socket to prevent exposing the unauthenticated control interface to public networks.
Rule 2: Configure trusted proxy IP ranges when evaluating client IP addresses and headers.
Specify explicit upstream proxy IP ranges using trusted_proxies and enable strict right-to-left header evaluation to prevent header spoofing and unauthorized IP manipulation.
{ servers { trusted_proxies static 10.0.1.0/24 }}
Encode Untrusted URI Components and Template Inputs to Prevent Output Injection
Approximately 358 tokens
Use when
When constructing dynamic Caddy configurations, headers, redirect targets, or rendering untrusted user input within Caddy template responses and markdown files.
Secure rules
Rule 1: Use URL-escaped placeholders when referencing HTTP URI components inside dynamic configurations, headers, or redirects.
When referencing HTTP URI components inside dynamic Caddy configurations, headers, or redirect targets, use URL-escaped placeholders such as http.request.uri_escaped, http.request.uri.path_escaped, and http.request.uri.query_escaped instead of raw unescaped values. This ensures special characters and control delimiters remain encoded and prevents HTTP response splitting, header injection, or query parameter ambiguity vulnerabilities.
Rule 2: Sanitize untrusted input using stripHTML and contextual escaping in template files.
Developers outputting untrusted user input within Caddy template responses should use stripHTML or contextual escaping to prevent cross-site scripting attacks. Pipe untrusted inputs through stripHTML or apply html escaping functions to dynamic content rendered via file and HTTP includes.
Enforce Memory and Buffer Limits on HTTP Requests, Responses, and File Browsing
Approximately 403 tokens
Use when
Use when configuring Caddy servers, reverse proxies, and file servers to handle incoming client traffic and backend payloads securely without exhausting memory resources.
Secure rules
Rule 1: Set explicit positive bounds on request and response buffer sizes in reverse proxy configurations.
Avoid setting request_buffers or response_buffers to -1 or unconstrained values. Always specify positive byte limits to prevent malicious clients or upstreams from consuming excessive memory during payload handling.
Rule 2: Limit the maximum number of entries returned during directory browsing.
Explicitly configure file_limit in the file server browse configuration to cap the maximum number of directory entries loaded and rendered in memory per request, avoiding resource exhaustion from vast directory structures.
Rule 3: Configure explicit timeouts and header size limits on HTTP servers.
Set explicit read_timeout, read_header_timeout, and idle_timeout values on server configurations, and retain or define max_header_bytes to bound memory consumption and prevent slowloris connection exhaustion attacks.
Configure Explicit Home and XDG Environment Variables for Production Runtime Storage
Approximately 234 tokens
Use when
Deploying Caddy as a system service or container manifest in production environments to ensure runtime storage resolves to secure absolute paths instead of falling back to working directories.
Secure rules
Rule 1: Explicitly define standard home and application data environment variables in deployment service files prior to execution.
Set environment variables such as HOME, USERPROFILE, XDG_DATA_HOME, XDG_CONFIG_HOME, and XDG_CACHE_HOME explicitly in systemd service definitions or container configurations. This prevents Caddy from falling back to storing sensitive cryptographic assets, private TLS keys, and internal state in a relative ./caddy folder within the current working directory.
[Service]Environment=HOME=/var/lib/caddyEnvironment=XDG_DATA_HOME=/var/lib/caddy/.local/shareExecStart=/usr/bin/caddy run --config /etc/caddy/Caddyfile
Load Credentials and Secrets Dynamically Using Environment Variables and Placeholders
Approximately 415 tokens
Use when
Configuring issuers, certificates, and sensitive keys in Caddyfile or JSON configurations.
Secure rules
Rule 1: Use environment variable placeholders instead of hardcoding sensitive account keys and credentials in configuration files.
Supply private keys, MAC keys, and API credentials dynamically using environment variable placeholders such as {$ACME_ACCOUNT_KEY} or {env.ZEROSSL_API_KEY} in your configuration files to avoid exposing secrets in version control or backups.
Rule 2: Avoid passing plaintext passwords via command line flags when generating credentials or hashes.
Omit the --plaintext argument when using caddy hash-password so that Caddy interactively prompts for the password or receives it securely through standard input, preventing exposure in process listings and history files.
Redact and Filter Sensitive Data in Log Outputs and Storage
Use when
Configuring log filters, file storage permissions, and security-sensitive log options.
Secure rules
Rule 1: Configure explicit log filters to automatically redact sensitive query parameters and cookie headers from logs.
Use QueryFilter and CookieFilter log field filters in your logging configuration to purge or replace sensitive fields like access_token and session_id before logs are written.
Enforce explicit directive ordering with route blocks
Approximately 206 tokens
Use when
Configuring Caddyfile directives where security controls like authentication or header validation depend on strict execution sequence relative to request rewrites or proxy handlers.
Secure rules
Rule 1: Wrap dependent directives in an explicit route block to override default pipeline sorting and enforce literal top-to-bottom execution.
Caddy sorts directives automatically according to a predefined pipeline where rewrites execute before authentication controls. When security controls must run before request modifications, use an explicit route block to ensure execution order and prevent authorization bypasses.