1
0
Fork 0

Merge branch v2.11 into v3.6

This commit is contained in:
romain 2026-01-14 11:28:12 +01:00
commit 8479d66d18
23 changed files with 266 additions and 224 deletions

View file

@ -1,3 +1,10 @@
## [v2.11.35](https://github.com/traefik/traefik/tree/v2.11.35) (2026-01-14)
[All Commits](https://github.com/traefik/traefik/compare/v2.11.34...v2.11.35)
**Bug fixes:**
- **[acme]** Add timeout to ACME-TLS/1 challenge handshake ([#12516](https://github.com/traefik/traefik/pull/12516) by [LBF38](https://github.com/LBF38))
- **[server]** Make encoded character options opt-in ([#12540](https://github.com/traefik/traefik/pull/12540) by [gndz07](https://github.com/gndz07))
## [v3.6.6](https://github.com/traefik/traefik/tree/v3.6.6) (2025-12-29) ## [v3.6.6](https://github.com/traefik/traefik/tree/v3.6.6) (2025-12-29)
[All Commits](https://github.com/traefik/traefik/compare/v3.6.5...v3.6.6) [All Commits](https://github.com/traefik/traefik/compare/v3.6.5...v3.6.6)

View file

@ -97,10 +97,10 @@ func runCmd(staticConfiguration *static.Configuration) error {
return fmt.Errorf("setting up logger: %w", err) return fmt.Errorf("setting up logger: %w", err)
} }
// Display warning to advertise for new behavior of rejecting encoded characters in the request path. log.Warn().Msg("Traefik can reject some encoded characters in the request path." +
// Deprecated: this has to be removed in the next minor/major version. "When your backend is not fully compliant with [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986)," +
log.Warn().Msg("Starting with v3.6.4, Traefik now rejects some encoded characters in the request path by default. " + "it is recommended to set these options to `false` to avoid split-view situation." +
"Refer to the documentation for more details: https://doc.traefik.io/traefik/migrate/v3/#encoded-characters-in-request-path") "Refer to the documentation for more details: https://doc.traefik.io/traefik/v3.6/migrate/v3/#encoded-characters-configuration-default-values")
http.DefaultTransport.(*http.Transport).Proxy = http.ProxyFromEnvironment http.DefaultTransport.(*http.Transport).Proxy = http.ProxyFromEnvironment

View file

@ -2,3 +2,13 @@
(function(hljs) { (function(hljs) {
hljs.initHighlightingOnLoad(); hljs.initHighlightingOnLoad();
})(hljs); })(hljs);
/* Scarf Analytics - cookieless, anonymous company-level intelligence */
(function() {
var img = document.createElement('img');
img.src = 'https://static.scarf.sh/a.png?x-pxid=1a49232a-b165-4015-8ed2-a1092f1f0d83';
img.referrerPolicy = 'no-referrer-when-downgrade';
img.loading = 'eager';
img.style.cssText = 'visibility:hidden;position:absolute;width:1px;height:1px;';
document.body.appendChild(img);
})();

View file

@ -576,3 +576,30 @@ Here is the list of the encoded characters that are rejected by default, along w
| `%23` | `#` (hash) | `entryPoints.<name>.`<br/>`.http.encodedCharacters`<br/>`.allowEncodedHash` | | `%23` | `#` (hash) | `entryPoints.<name>.`<br/>`.http.encodedCharacters`<br/>`.allowEncodedHash` |
Please check out the entrypoint [encodedCharacters option](../reference/install-configuration/entrypoints.md#opt-http-encodedCharacters) documentation for more details. Please check out the entrypoint [encodedCharacters option](../reference/install-configuration/entrypoints.md#opt-http-encodedCharacters) documentation for more details.
## v3.6.7
### Encoded Characters Configuration Default Values
Since `v3.6.7`, the options for encoded characters now have a `true` default value.
This means that Traefik will not reject requests with a path containing a specific set of encoded characters by default.
It is now up to the users to configure the security hardening of encoded characters.
Here is the list of the encoded characters that can be configured to `false` to disallow them:
| Encoded Character | Character | Config options | Default value |
|-------------------|-------------------------|--------------------------------------------------------------------------------------|---------------|
| `%2f` or `%2F` | `/` (slash) | `entryPoints.<name>`<br/>`.http.encodedCharacters`<br/>`.allowEncodedSlash` | `true` |
| `%5c` or `%5C` | `\` (backslash) | `entryPoints.<name>.`<br/>`.http.encodedCharacters`<br/>`.allowEncodedBackSlash` | `true` |
| `%00` | `NULL` (null character) | `entryPoints.<name>.`<br/>`.http.encodedCharacters`<br/>`.allowEncodedNullCharacter` | `true` |
| `%3b` or `%3B` | `;` (semicolon) | `entryPoints.<name>.`<br/>`.http.encodedCharacters`<br/>`.allowEncodedSemicolon` | `true` |
| `%25` | `%` (percent) | `entryPoints.<name>.`<br/>`.http.encodedCharacters`<br/>`.allowEncodedPercent` | `true` |
| `%3f` or `%3F` | `?` (question mark) | `entryPoints.<name>.`<br/>`.http.encodedCharacters`<br/>`.allowEncodedQuestionMark` | `true` |
| `%23` | `#` (hash) | `entryPoints.<name>.`<br/>`.http.encodedCharacters`<br/>`.allowEncodedHash` | `true` |
Note: This check is not done against query parameters,
but only against the request path as defined
in [RFC3986 section-3](https://datatracker.ietf.org/doc/html/rfc3986#section-3).
Please check out the entrypoint [encodedCharacters option](../routing/entrypoints.md#encoded-characters) documentation
for more details.

View file

@ -85,13 +85,13 @@ THIS FILE MUST NOT BE EDITED BY HAND
| <a id="opt-entrypoints-name-forwardedheaders-insecure" href="#opt-entrypoints-name-forwardedheaders-insecure" title="#opt-entrypoints-name-forwardedheaders-insecure">entrypoints._name_.forwardedheaders.insecure</a> | Trust all forwarded headers. | false | | <a id="opt-entrypoints-name-forwardedheaders-insecure" href="#opt-entrypoints-name-forwardedheaders-insecure" title="#opt-entrypoints-name-forwardedheaders-insecure">entrypoints._name_.forwardedheaders.insecure</a> | Trust all forwarded headers. | false |
| <a id="opt-entrypoints-name-forwardedheaders-trustedips" href="#opt-entrypoints-name-forwardedheaders-trustedips" title="#opt-entrypoints-name-forwardedheaders-trustedips">entrypoints._name_.forwardedheaders.trustedips</a> | Trust only forwarded headers from selected IPs. | | | <a id="opt-entrypoints-name-forwardedheaders-trustedips" href="#opt-entrypoints-name-forwardedheaders-trustedips" title="#opt-entrypoints-name-forwardedheaders-trustedips">entrypoints._name_.forwardedheaders.trustedips</a> | Trust only forwarded headers from selected IPs. | |
| <a id="opt-entrypoints-name-http" href="#opt-entrypoints-name-http" title="#opt-entrypoints-name-http">entrypoints._name_.http</a> | HTTP configuration. | | | <a id="opt-entrypoints-name-http" href="#opt-entrypoints-name-http" title="#opt-entrypoints-name-http">entrypoints._name_.http</a> | HTTP configuration. | |
| <a id="opt-entrypoints-name-http-encodedcharacters-allowencodedbackslash" href="#opt-entrypoints-name-http-encodedcharacters-allowencodedbackslash" title="#opt-entrypoints-name-http-encodedcharacters-allowencodedbackslash">entrypoints._name_.http.encodedcharacters.allowencodedbackslash</a> | Defines whether requests with encoded back slash characters in the path are allowed. | false | | <a id="opt-entrypoints-name-http-encodedcharacters-allowencodedbackslash" href="#opt-entrypoints-name-http-encodedcharacters-allowencodedbackslash" title="#opt-entrypoints-name-http-encodedcharacters-allowencodedbackslash">entrypoints._name_.http.encodedcharacters.allowencodedbackslash</a> | Defines whether requests with encoded back slash characters in the path are allowed. | true |
| <a id="opt-entrypoints-name-http-encodedcharacters-allowencodedhash" href="#opt-entrypoints-name-http-encodedcharacters-allowencodedhash" title="#opt-entrypoints-name-http-encodedcharacters-allowencodedhash">entrypoints._name_.http.encodedcharacters.allowencodedhash</a> | Defines whether requests with encoded hash characters in the path are allowed. | false | | <a id="opt-entrypoints-name-http-encodedcharacters-allowencodedhash" href="#opt-entrypoints-name-http-encodedcharacters-allowencodedhash" title="#opt-entrypoints-name-http-encodedcharacters-allowencodedhash">entrypoints._name_.http.encodedcharacters.allowencodedhash</a> | Defines whether requests with encoded hash characters in the path are allowed. | true |
| <a id="opt-entrypoints-name-http-encodedcharacters-allowencodednullcharacter" href="#opt-entrypoints-name-http-encodedcharacters-allowencodednullcharacter" title="#opt-entrypoints-name-http-encodedcharacters-allowencodednullcharacter">entrypoints._name_.http.encodedcharacters.allowencodednullcharacter</a> | Defines whether requests with encoded null characters in the path are allowed. | false | | <a id="opt-entrypoints-name-http-encodedcharacters-allowencodednullcharacter" href="#opt-entrypoints-name-http-encodedcharacters-allowencodednullcharacter" title="#opt-entrypoints-name-http-encodedcharacters-allowencodednullcharacter">entrypoints._name_.http.encodedcharacters.allowencodednullcharacter</a> | Defines whether requests with encoded null characters in the path are allowed. | true |
| <a id="opt-entrypoints-name-http-encodedcharacters-allowencodedpercent" href="#opt-entrypoints-name-http-encodedcharacters-allowencodedpercent" title="#opt-entrypoints-name-http-encodedcharacters-allowencodedpercent">entrypoints._name_.http.encodedcharacters.allowencodedpercent</a> | Defines whether requests with encoded percent characters in the path are allowed. | false | | <a id="opt-entrypoints-name-http-encodedcharacters-allowencodedpercent" href="#opt-entrypoints-name-http-encodedcharacters-allowencodedpercent" title="#opt-entrypoints-name-http-encodedcharacters-allowencodedpercent">entrypoints._name_.http.encodedcharacters.allowencodedpercent</a> | Defines whether requests with encoded percent characters in the path are allowed. | true |
| <a id="opt-entrypoints-name-http-encodedcharacters-allowencodedquestionmark" href="#opt-entrypoints-name-http-encodedcharacters-allowencodedquestionmark" title="#opt-entrypoints-name-http-encodedcharacters-allowencodedquestionmark">entrypoints._name_.http.encodedcharacters.allowencodedquestionmark</a> | Defines whether requests with encoded question mark characters in the path are allowed. | false | | <a id="opt-entrypoints-name-http-encodedcharacters-allowencodedquestionmark" href="#opt-entrypoints-name-http-encodedcharacters-allowencodedquestionmark" title="#opt-entrypoints-name-http-encodedcharacters-allowencodedquestionmark">entrypoints._name_.http.encodedcharacters.allowencodedquestionmark</a> | Defines whether requests with encoded question mark characters in the path are allowed. | true |
| <a id="opt-entrypoints-name-http-encodedcharacters-allowencodedsemicolon" href="#opt-entrypoints-name-http-encodedcharacters-allowencodedsemicolon" title="#opt-entrypoints-name-http-encodedcharacters-allowencodedsemicolon">entrypoints._name_.http.encodedcharacters.allowencodedsemicolon</a> | Defines whether requests with encoded semicolon characters in the path are allowed. | false | | <a id="opt-entrypoints-name-http-encodedcharacters-allowencodedsemicolon" href="#opt-entrypoints-name-http-encodedcharacters-allowencodedsemicolon" title="#opt-entrypoints-name-http-encodedcharacters-allowencodedsemicolon">entrypoints._name_.http.encodedcharacters.allowencodedsemicolon</a> | Defines whether requests with encoded semicolon characters in the path are allowed. | true |
| <a id="opt-entrypoints-name-http-encodedcharacters-allowencodedslash" href="#opt-entrypoints-name-http-encodedcharacters-allowencodedslash" title="#opt-entrypoints-name-http-encodedcharacters-allowencodedslash">entrypoints._name_.http.encodedcharacters.allowencodedslash</a> | Defines whether requests with encoded slash characters in the path are allowed. | false | | <a id="opt-entrypoints-name-http-encodedcharacters-allowencodedslash" href="#opt-entrypoints-name-http-encodedcharacters-allowencodedslash" title="#opt-entrypoints-name-http-encodedcharacters-allowencodedslash">entrypoints._name_.http.encodedcharacters.allowencodedslash</a> | Defines whether requests with encoded slash characters in the path are allowed. | true |
| <a id="opt-entrypoints-name-http-encodequerysemicolons" href="#opt-entrypoints-name-http-encodequerysemicolons" title="#opt-entrypoints-name-http-encodequerysemicolons">entrypoints._name_.http.encodequerysemicolons</a> | Defines whether request query semicolons should be URLEncoded. | false | | <a id="opt-entrypoints-name-http-encodequerysemicolons" href="#opt-entrypoints-name-http-encodequerysemicolons" title="#opt-entrypoints-name-http-encodequerysemicolons">entrypoints._name_.http.encodequerysemicolons</a> | Defines whether request query semicolons should be URLEncoded. | false |
| <a id="opt-entrypoints-name-http-maxheaderbytes" href="#opt-entrypoints-name-http-maxheaderbytes" title="#opt-entrypoints-name-http-maxheaderbytes">entrypoints._name_.http.maxheaderbytes</a> | Maximum size of request headers in bytes. | 1048576 | | <a id="opt-entrypoints-name-http-maxheaderbytes" href="#opt-entrypoints-name-http-maxheaderbytes" title="#opt-entrypoints-name-http-maxheaderbytes">entrypoints._name_.http.maxheaderbytes</a> | Maximum size of request headers in bytes. | 1048576 |
| <a id="opt-entrypoints-name-http-middlewares" href="#opt-entrypoints-name-http-middlewares" title="#opt-entrypoints-name-http-middlewares">entrypoints._name_.http.middlewares</a> | Default middlewares for the routers linked to the entry point. | | | <a id="opt-entrypoints-name-http-middlewares" href="#opt-entrypoints-name-http-middlewares" title="#opt-entrypoints-name-http-middlewares">entrypoints._name_.http.middlewares</a> | Default middlewares for the routers linked to the entry point. | |

View file

@ -84,8 +84,8 @@ additionalArguments:
## Configuration Options ## Configuration Options
| Field | Description | Default | Required | | Field | Description | Default | Required |
|:----------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------------|:---------| |:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------------|:---------|
| <a id="opt-address" href="#opt-address" title="#opt-address">`address`</a> | Define the port, and optionally the hostname, on which to listen for incoming connections and packets.<br /> It also defines the protocol to use (TCP or UDP).<br /> If no protocol is specified, the default is TCP. The format is:`[host]:port[/tcp\|/udp] | - | Yes | | <a id="opt-address" href="#opt-address" title="#opt-address">`address`</a> | Define the port, and optionally the hostname, on which to listen for incoming connections and packets.<br /> It also defines the protocol to use (TCP or UDP).<br /> If no protocol is specified, the default is TCP. The format is:`[host]:port[/tcp\|/udp] | - | Yes |
| <a id="opt-asDefault" href="#opt-asDefault" title="#opt-asDefault">`asDefault`</a> | Mark the `entryPoint` to be in the list of default `entryPoints`.<br /> `entryPoints`in this list are used (by default) on HTTP and TCP routers that do not define their own `entryPoints` option.<br /> More information [here](#asdefault). | false | No | | <a id="opt-asDefault" href="#opt-asDefault" title="#opt-asDefault">`asDefault`</a> | Mark the `entryPoint` to be in the list of default `entryPoints`.<br /> `entryPoints`in this list are used (by default) on HTTP and TCP routers that do not define their own `entryPoints` option.<br /> More information [here](#asdefault). | false | No |
| <a id="opt-forwardedHeaders-trustedIPs" href="#opt-forwardedHeaders-trustedIPs" title="#opt-forwardedHeaders-trustedIPs">`forwardedHeaders.trustedIPs`</a> | Set the IPs or CIDR from where Traefik trusts the forwarded headers information (`X-Forwarded-*`). | - | No | | <a id="opt-forwardedHeaders-trustedIPs" href="#opt-forwardedHeaders-trustedIPs" title="#opt-forwardedHeaders-trustedIPs">`forwardedHeaders.trustedIPs`</a> | Set the IPs or CIDR from where Traefik trusts the forwarded headers information (`X-Forwarded-*`). | - | No |
@ -95,16 +95,16 @@ additionalArguments:
| <a id="opt-http-redirections-entryPoint-permanent" href="#opt-http-redirections-entryPoint-permanent" title="#opt-http-redirections-entryPoint-permanent">`http.redirections.`<br />`entryPoint.permanent`</a> | Enable permanent redirecting of all incoming requests on an entry point to another one changing the scheme. <br /> The target element, it can be an entry point name (ex: `websecure`), or a port (`:443`). | false | No | | <a id="opt-http-redirections-entryPoint-permanent" href="#opt-http-redirections-entryPoint-permanent" title="#opt-http-redirections-entryPoint-permanent">`http.redirections.`<br />`entryPoint.permanent`</a> | Enable permanent redirecting of all incoming requests on an entry point to another one changing the scheme. <br /> The target element, it can be an entry point name (ex: `websecure`), or a port (`:443`). | false | No |
| <a id="opt-http-redirections-entryPoint-priority" href="#opt-http-redirections-entryPoint-priority" title="#opt-http-redirections-entryPoint-priority">`http.redirections.`<br />`entryPoint.priority`</a> | Default priority applied to the routers attached to the `entryPoint`. | MaxInt32-1 (2147483646) | No | | <a id="opt-http-redirections-entryPoint-priority" href="#opt-http-redirections-entryPoint-priority" title="#opt-http-redirections-entryPoint-priority">`http.redirections.`<br />`entryPoint.priority`</a> | Default priority applied to the routers attached to the `entryPoint`. | MaxInt32-1 (2147483646) | No |
| <a id="opt-http-encodedCharacters" href="#opt-http-encodedCharacters" title="#opt-http-encodedCharacters">`http.encodedCharacters`</a> | Defines which encoded characters are allowed in the request path. More information [here](#encoded-characters). | false | No | | <a id="opt-http-encodedCharacters" href="#opt-http-encodedCharacters" title="#opt-http-encodedCharacters">`http.encodedCharacters`</a> | Defines which encoded characters are allowed in the request path. More information [here](#encoded-characters). | false | No |
| <a id="opt-http-encodedCharacters-allowEncodedSlash" href="#opt-http-encodedCharacters-allowEncodedSlash" title="#opt-http-encodedCharacters-allowEncodedSlash">`http.encodedCharacters.`<br />`allowEncodedSlash`</a> | Defines whether requests with encoded slash characters in the path are allowed. | false | No | | <a id="opt-http-encodedCharacters-allowEncodedSlash" href="#opt-http-encodedCharacters-allowEncodedSlash" title="#opt-http-encodedCharacters-allowEncodedSlash">`http.encodedCharacters.`<br />`allowEncodedSlash`</a> | Defines whether requests with encoded slash characters in the path are allowed. | true | No |
| <a id="opt-http-encodedCharacters-allowEncodedBackSlash" href="#opt-http-encodedCharacters-allowEncodedBackSlash" title="#opt-http-encodedCharacters-allowEncodedBackSlash">`http.encodedCharacters.`<br />`allowEncodedBackSlash`</a> | Defines whether requests with encoded back slash characters in the path are allowed. | false | No | | <a id="opt-http-encodedCharacters-allowEncodedBackSlash" href="#opt-http-encodedCharacters-allowEncodedBackSlash" title="#opt-http-encodedCharacters-allowEncodedBackSlash">`http.encodedCharacters.`<br />`allowEncodedBackSlash`</a> | Defines whether requests with encoded back slash characters in the path are allowed. | true | No |
| <a id="opt-http-encodedCharacters-allowEncodedNullCharacter" href="#opt-http-encodedCharacters-allowEncodedNullCharacter" title="#opt-http-encodedCharacters-allowEncodedNullCharacter">`http.encodedCharacters.`<br />`allowEncodedNullCharacter`</a> | Defines whether requests with encoded null characters in the path are allowed. | false | No | | <a id="opt-http-encodedCharacters-allowEncodedNullCharacter" href="#opt-http-encodedCharacters-allowEncodedNullCharacter" title="#opt-http-encodedCharacters-allowEncodedNullCharacter">`http.encodedCharacters.`<br />`allowEncodedNullCharacter`</a> | Defines whether requests with encoded null characters in the path are allowed. | true | No |
| <a id="opt-http-encodedCharacters-allowEncodedSemicolon" href="#opt-http-encodedCharacters-allowEncodedSemicolon" title="#opt-http-encodedCharacters-allowEncodedSemicolon">`http.encodedCharacters.`<br />`allowEncodedSemicolon`</a> | Defines whether requests with encoded semicolon characters in the path are allowed. | false | No | | <a id="opt-http-encodedCharacters-allowEncodedSemicolon" href="#opt-http-encodedCharacters-allowEncodedSemicolon" title="#opt-http-encodedCharacters-allowEncodedSemicolon">`http.encodedCharacters.`<br />`allowEncodedSemicolon`</a> | Defines whether requests with encoded semicolon characters in the path are allowed. | true | No |
| <a id="opt-http-encodedCharacters-allowEncodedPercent" href="#opt-http-encodedCharacters-allowEncodedPercent" title="#opt-http-encodedCharacters-allowEncodedPercent">`http.encodedCharacters.`<br />`allowEncodedPercent`</a> | Defines whether requests with encoded percent characters in the path are allowed. | false | No | | <a id="opt-http-encodedCharacters-allowEncodedPercent" href="#opt-http-encodedCharacters-allowEncodedPercent" title="#opt-http-encodedCharacters-allowEncodedPercent">`http.encodedCharacters.`<br />`allowEncodedPercent`</a> | Defines whether requests with encoded percent characters in the path are allowed. | true | No |
| <a id="opt-http-encodedCharacters-allowEncodedQuestionMark" href="#opt-http-encodedCharacters-allowEncodedQuestionMark" title="#opt-http-encodedCharacters-allowEncodedQuestionMark">`http.encodedCharacters.`<br />`allowEncodedQuestionMark`</a> | Defines whether requests with encoded question mark characters in the path are allowed. | false | No | | <a id="opt-http-encodedCharacters-allowEncodedQuestionMark" href="#opt-http-encodedCharacters-allowEncodedQuestionMark" title="#opt-http-encodedCharacters-allowEncodedQuestionMark">`http.encodedCharacters.`<br />`allowEncodedQuestionMark`</a> | Defines whether requests with encoded question mark characters in the path are allowed. | true | No |
| <a id="opt-http-encodedCharacters-allowEncodedHash" href="#opt-http-encodedCharacters-allowEncodedHash" title="#opt-http-encodedCharacters-allowEncodedHash">`http.encodedCharacters.`<br />`allowEncodedHash`</a> | Defines whether requests with encoded hash characters in the path are allowed. | false | No | | <a id="opt-http-encodedCharacters-allowEncodedHash" href="#opt-http-encodedCharacters-allowEncodedHash" title="#opt-http-encodedCharacters-allowEncodedHash">`http.encodedCharacters.`<br />`allowEncodedHash`</a> | Defines whether requests with encoded hash characters in the path are allowed. | true | No |
| <a id="opt-http-encodeQuerySemicolons" href="#opt-http-encodeQuerySemicolons" title="#opt-http-encodeQuerySemicolons">`http.encodeQuerySemicolons`</a> | Enable query semicolons encoding. <br /> Use this option to avoid non-encoded semicolons to be interpreted as query parameter separators by Traefik. <br /> When using this option, the non-encoded semicolons characters in query will be transmitted encoded to the backend.<br /> More information [here](#encodequerysemicolons). | false | No | | <a id="opt-http-encodeQuerySemicolons" href="#opt-http-encodeQuerySemicolons" title="#opt-http-encodeQuerySemicolons">`http.encodeQuerySemicolons`</a> | Enable query semicolons encoding. <br /> Use this option to avoid non-encoded semicolons to be interpreted as query parameter separators by Traefik. <br /> When using this option, the non-encoded semicolons characters in query will be transmitted encoded to the backend.<br /> More information [here](#encodequerysemicolons). | false | No |
| <a id="opt-http-sanitizePath" href="#opt-http-sanitizePath" title="#opt-http-sanitizePath">`http.sanitizePath`</a> | Defines whether to enable the request path sanitization.<br /> More information [here](#sanitizepath). | false | No | | <a id="opt-http-sanitizePath" href="#opt-http-sanitizePath" title="#opt-http-sanitizePath">`http.sanitizePath`</a> | Defines whether to enable the request path sanitization.<br /> More information [here](#sanitizepath). | false | No |
| <a id="opt-http-maxHeaderBytes" href="#opt-http-maxHeaderBytes" title="#opt-http-maxHeaderBytes">`http.maxHeaderBytes`</a> | Set the maximum size of request headers in bytes. | 1048576 | No | | <a id="opt-http-maxHeaderBytes" href="#opt-http-maxHeaderBytes" title="#opt-http-maxHeaderBytes">`http.maxHeaderBytes`</a> | Set the maximum size of request headers in bytes. | 1048576 | No |
| <a id="opt-http-middlewares" href="#opt-http-middlewares" title="#opt-http-middlewares">`http.middlewares`</a> | Set the list of middlewares that are prepended by default to the list of middlewares of each router associated to the named entry point. <br />More information [here](#httpmiddlewares). | - | No | | <a id="opt-http-middlewares" href="#opt-http-middlewares" title="#opt-http-middlewares">`http.middlewares`</a> | Set the list of middlewares that are prepended by default to the list of middlewares of each router associated to the named entry point. <br />More information [here](#httpmiddlewares). | - | No |
| <a id="opt-http-tls" href="#opt-http-tls" title="#opt-http-tls">`http.tls`</a> | Enable TLS on every router attached to the `entryPoint`. <br /> If no certificate are set, a default self-signed certificate is generated by Traefik. <br /> We recommend to not use self signed certificates in production. | - | No | | <a id="opt-http-tls" href="#opt-http-tls" title="#opt-http-tls">`http.tls`</a> | Enable TLS on every router attached to the `entryPoint`. <br /> If no certificate are set, a default self-signed certificate is generated by Traefik. <br /> We recommend to not use self signed certificates in production. | - | No |
| <a id="opt-http-tls-options" href="#opt-http-tls-options" title="#opt-http-tls-options">`http.tls.options`</a> | Apply TLS options on every router attached to the `entryPoint`. <br /> The TLS options can be overidden per router. <br /> More information in the [dedicated section](../../routing/providers/kubernetes-crd.md#kind-tlsoption). | - | No | | <a id="opt-http-tls-options" href="#opt-http-tls-options" title="#opt-http-tls-options">`http.tls.options`</a> | Apply TLS options on every router attached to the `entryPoint`. <br /> The TLS options can be overidden per router. <br /> More information in the [dedicated section](../../routing/providers/kubernetes-crd.md#kind-tlsoption). | - | No |
@ -220,16 +220,22 @@ it can lead to unsafe routing when the `sanitizePath` option is set to `false`.
### Encoded Characters ### Encoded Characters
You can configure Traefik to control the handling of encoded characters in request paths for security purposes. You can configure Traefik to control the handling of encoded characters in request paths for security purposes.
By default, Traefik rejects requests containing certain encoded characters that could be used in path traversal or other security attacks. By default, Traefik do not reject requests with path containing certain encoded characters that could be used in path traversal or other security attacks.
!!! warning "Security Considerations" !!! info
Allowing certain encoded characters may expose your application to security vulnerabilities. This check is not done against the request query parameters,
but only against the request path as defined in [RFC3986 section-3](https://datatracker.ietf.org/doc/html/rfc3986#section-3).
!!! info "Security Considerations"
When your backend is not fully compliant with [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986) and notably decode encoded reserved characters in the requets path,
it is recommended to set these options to `false` to avoid split-view situation and helps prevent path traversal attacks or other malicious attempts to bypass security controls.
Here is the list of the encoded characters that are rejected by default: Here is the list of the encoded characters that are rejected by default:
| Encoded Character | Character | | Encoded Character | Character |
|-------------------|-------------------------| |------------------------------------------------------------------------------------|-------------------------|
| <a id="opt-2f-or-2F" href="#opt-2f-or-2F" title="#opt-2f-or-2F">`%2f` or `%2F`</a> | `/` (slash) | | <a id="opt-2f-or-2F" href="#opt-2f-or-2F" title="#opt-2f-or-2F">`%2f` or `%2F`</a> | `/` (slash) |
| <a id="opt-5c-or-5C" href="#opt-5c-or-5C" title="#opt-5c-or-5C">`%5c` or `%5C`</a> | `\` (backslash) | | <a id="opt-5c-or-5C" href="#opt-5c-or-5C" title="#opt-5c-or-5C">`%5c` or `%5C`</a> | `\` (backslash) |
| <a id="opt-00" href="#opt-00" title="#opt-00">`%00`</a> | `NULL` (null character) | | <a id="opt-00" href="#opt-00" title="#opt-00">`%00`</a> | `NULL` (null character) |

View file

@ -238,25 +238,25 @@ Trust only forwarded headers from selected IPs.
HTTP configuration. HTTP configuration.
`--entrypoints.<name>.http.encodedcharacters.allowencodedbackslash`: `--entrypoints.<name>.http.encodedcharacters.allowencodedbackslash`:
Defines whether requests with encoded back slash characters in the path are allowed. (Default: ```false```) Defines whether requests with encoded back slash characters in the path are allowed. (Default: ```true```)
`--entrypoints.<name>.http.encodedcharacters.allowencodedhash`: `--entrypoints.<name>.http.encodedcharacters.allowencodedhash`:
Defines whether requests with encoded hash characters in the path are allowed. (Default: ```false```) Defines whether requests with encoded hash characters in the path are allowed. (Default: ```true```)
`--entrypoints.<name>.http.encodedcharacters.allowencodednullcharacter`: `--entrypoints.<name>.http.encodedcharacters.allowencodednullcharacter`:
Defines whether requests with encoded null characters in the path are allowed. (Default: ```false```) Defines whether requests with encoded null characters in the path are allowed. (Default: ```true```)
`--entrypoints.<name>.http.encodedcharacters.allowencodedpercent`: `--entrypoints.<name>.http.encodedcharacters.allowencodedpercent`:
Defines whether requests with encoded percent characters in the path are allowed. (Default: ```false```) Defines whether requests with encoded percent characters in the path are allowed. (Default: ```true```)
`--entrypoints.<name>.http.encodedcharacters.allowencodedquestionmark`: `--entrypoints.<name>.http.encodedcharacters.allowencodedquestionmark`:
Defines whether requests with encoded question mark characters in the path are allowed. (Default: ```false```) Defines whether requests with encoded question mark characters in the path are allowed. (Default: ```true```)
`--entrypoints.<name>.http.encodedcharacters.allowencodedsemicolon`: `--entrypoints.<name>.http.encodedcharacters.allowencodedsemicolon`:
Defines whether requests with encoded semicolon characters in the path are allowed. (Default: ```false```) Defines whether requests with encoded semicolon characters in the path are allowed. (Default: ```true```)
`--entrypoints.<name>.http.encodedcharacters.allowencodedslash`: `--entrypoints.<name>.http.encodedcharacters.allowencodedslash`:
Defines whether requests with encoded slash characters in the path are allowed. (Default: ```false```) Defines whether requests with encoded slash characters in the path are allowed. (Default: ```true```)
`--entrypoints.<name>.http.encodequerysemicolons`: `--entrypoints.<name>.http.encodequerysemicolons`:
Defines whether request query semicolons should be URLEncoded. (Default: ```false```) Defines whether request query semicolons should be URLEncoded. (Default: ```false```)

View file

@ -247,25 +247,25 @@ HTTP/3 configuration. (Default: ```false```)
UDP port to advertise, on which HTTP/3 is available. (Default: ```0```) UDP port to advertise, on which HTTP/3 is available. (Default: ```0```)
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDBACKSLASH`: `TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDBACKSLASH`:
Defines whether requests with encoded back slash characters in the path are allowed. (Default: ```false```) Defines whether requests with encoded back slash characters in the path are allowed. (Default: ```true```)
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDHASH`: `TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDHASH`:
Defines whether requests with encoded hash characters in the path are allowed. (Default: ```false```) Defines whether requests with encoded hash characters in the path are allowed. (Default: ```true```)
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDNULLCHARACTER`: `TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDNULLCHARACTER`:
Defines whether requests with encoded null characters in the path are allowed. (Default: ```false```) Defines whether requests with encoded null characters in the path are allowed. (Default: ```true```)
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDPERCENT`: `TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDPERCENT`:
Defines whether requests with encoded percent characters in the path are allowed. (Default: ```false```) Defines whether requests with encoded percent characters in the path are allowed. (Default: ```true```)
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDQUESTIONMARK`: `TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDQUESTIONMARK`:
Defines whether requests with encoded question mark characters in the path are allowed. (Default: ```false```) Defines whether requests with encoded question mark characters in the path are allowed. (Default: ```true```)
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDSEMICOLON`: `TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDSEMICOLON`:
Defines whether requests with encoded semicolon characters in the path are allowed. (Default: ```false```) Defines whether requests with encoded semicolon characters in the path are allowed. (Default: ```true```)
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDSLASH`: `TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDSLASH`:
Defines whether requests with encoded slash characters in the path are allowed. (Default: ```false```) Defines whether requests with encoded slash characters in the path are allowed. (Default: ```true```)
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEQUERYSEMICOLONS`: `TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEQUERYSEMICOLONS`:
Defines whether request query semicolons should be URLEncoded. (Default: ```false```) Defines whether request query semicolons should be URLEncoded. (Default: ```false```)

View file

@ -131,13 +131,13 @@ They can be defined by using a file (YAML or TOML) or CLI arguments.
- "192.168.0.1" - "192.168.0.1"
http: http:
encodedCharacters: encodedCharacters:
allowEncodedSlash: true allowEncodedSlash: false
allowEncodedBackSlash: true allowEncodedBackSlash: false
allowEncodedNullCharacter: true allowEncodedNullCharacter: false
allowEncodedSemicolon: true allowEncodedSemicolon: false
allowEncodedPercent: true allowEncodedPercent: false
allowEncodedQuestionMark: true allowEncodedQuestionMark: false
allowEncodedHash: true allowEncodedHash: false
``` ```
```toml tab="File (TOML)" ```toml tab="File (TOML)"
@ -166,13 +166,13 @@ They can be defined by using a file (YAML or TOML) or CLI arguments.
insecure = true insecure = true
trustedIPs = ["127.0.0.1", "192.168.0.1"] trustedIPs = ["127.0.0.1", "192.168.0.1"]
[entryPoints.name.http.encodedCharacters] [entryPoints.name.http.encodedCharacters]
allowEncodedSlash = true allowEncodedSlash = false
allowEncodedBackSlash = true allowEncodedBackSlash = false
allowEncodedNullCharacter = true allowEncodedNullCharacter = false
allowEncodedSemicolon = true allowEncodedSemicolon = false
allowEncodedPercent = true allowEncodedPercent = false
allowEncodedQuestionMark = true allowEncodedQuestionMark = false
allowEncodedHash = true allowEncodedHash = false
``` ```
```bash tab="CLI" ```bash tab="CLI"
@ -191,13 +191,13 @@ They can be defined by using a file (YAML or TOML) or CLI arguments.
--entryPoints.name.proxyProtocol.trustedIPs=127.0.0.1,192.168.0.1 --entryPoints.name.proxyProtocol.trustedIPs=127.0.0.1,192.168.0.1
--entryPoints.name.forwardedHeaders.insecure=true --entryPoints.name.forwardedHeaders.insecure=true
--entryPoints.name.forwardedHeaders.trustedIPs=127.0.0.1,192.168.0.1 --entryPoints.name.forwardedHeaders.trustedIPs=127.0.0.1,192.168.0.1
--entryPoints.name.http.encodedCharacters.allowEncodedSlash=true --entryPoints.name.http.encodedCharacters.allowEncodedSlash=false
--entryPoints.name.http.encodedCharacters.allowEncodedBackSlash=true --entryPoints.name.http.encodedCharacters.allowEncodedBackSlash=false
--entryPoints.name.http.encodedCharacters.allowEncodedNullCharacter=true --entryPoints.name.http.encodedCharacters.allowEncodedNullCharacter=false
--entryPoints.name.http.encodedCharacters.allowEncodedSemicolon=true --entryPoints.name.http.encodedCharacters.allowEncodedSemicolon=false
--entryPoints.name.http.encodedCharacters.allowEncodedPercent=true --entryPoints.name.http.encodedCharacters.allowEncodedPercent=false
--entryPoints.name.http.encodedCharacters.allowEncodedQuestionMark=true --entryPoints.name.http.encodedCharacters.allowEncodedQuestionMark=false
--entryPoints.name.http.encodedCharacters.allowEncodedHash=true --entryPoints.name.http.encodedCharacters.allowEncodedHash=false
``` ```
### Address ### Address
@ -1180,20 +1180,21 @@ entryPoints:
### Encoded Characters ### Encoded Characters
You can configure Traefik to control the handling of encoded characters in request paths for security purposes. You can configure Traefik to control the handling of encoded characters in request paths for security purposes.
By default, Traefik rejects requests with path containing certain encoded characters that could be used in path traversal or other security attacks. By default, Traefik do not reject requests with path containing certain encoded characters that could be used in path traversal or other security attacks.
!!! info !!! info
This check is not done against the request query parameters, This check is not done against the request query parameters,
but only against the request path as defined in [RFC3986 section-3](https://datatracker.ietf.org/doc/html/rfc3986#section-3). but only against the request path as defined in [RFC3986 section-3](https://datatracker.ietf.org/doc/html/rfc3986#section-3).
!!! warning "Security Considerations" !!! info "Security Considerations"
Allowing certain encoded characters may expose your application to security vulnerabilities. When your backend is not fully compliant with [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986) and notably decode encoded reserved characters in the requets path,
it is recommended to set these options to `false` to avoid split-view situation and helps prevent path traversal attacks or other malicious attempts to bypass security controls.
??? info "`encodedCharacters.allowEncodedSlash`" ??? info "`encodedCharacters.allowEncodedSlash`"
_Optional, Default=false_ _Optional, Default=true_
Controls whether requests with encoded slash characters (`%2F` or `%2f`) in the path are allowed. Controls whether requests with encoded slash characters (`%2F` or `%2f`) in the path are allowed.
@ -1204,7 +1205,7 @@ By default, Traefik rejects requests with path containing certain encoded charac
address: ":80" address: ":80"
http: http:
encodedCharacters: encodedCharacters:
allowEncodedSlash: true allowEncodedSlash: false
``` ```
```toml tab="File (TOML)" ```toml tab="File (TOML)"
@ -1214,18 +1215,18 @@ By default, Traefik rejects requests with path containing certain encoded charac
address = ":80" address = ":80"
[entryPoints.web.http.encodedCharacters] [entryPoints.web.http.encodedCharacters]
allowEncodedSlash = true allowEncodedSlash = false
``` ```
```bash tab="CLI" ```bash tab="CLI"
## Static configuration ## Static configuration
--entryPoints.web.address=:80 --entryPoints.web.address=:80
--entryPoints.web.http.encodedCharacters.allowEncodedSlash=true --entryPoints.web.http.encodedCharacters.allowEncodedSlash=false
``` ```
??? info "`encodedCharacters.allowEncodedBackSlash`" ??? info "`encodedCharacters.allowEncodedBackSlash`"
_Optional, Default=false_ _Optional, Default=true_
Controls whether requests with encoded back slash characters (`%5C` or `%5c`) in the path are allowed. Controls whether requests with encoded back slash characters (`%5C` or `%5c`) in the path are allowed.
@ -1236,7 +1237,7 @@ By default, Traefik rejects requests with path containing certain encoded charac
address: ":80" address: ":80"
http: http:
encodedCharacters: encodedCharacters:
allowEncodedBackSlash: true allowEncodedBackSlash: false
``` ```
```toml tab="File (TOML)" ```toml tab="File (TOML)"
@ -1246,18 +1247,18 @@ By default, Traefik rejects requests with path containing certain encoded charac
address = ":80" address = ":80"
[entryPoints.web.http.encodedCharacters] [entryPoints.web.http.encodedCharacters]
allowEncodedBackSlash = true allowEncodedBackSlash = false
``` ```
```bash tab="CLI" ```bash tab="CLI"
## Static configuration ## Static configuration
--entryPoints.web.address=:80 --entryPoints.web.address=:80
--entryPoints.web.http.encodedCharacters.allowEncodedBackSlash=true --entryPoints.web.http.encodedCharacters.allowEncodedBackSlash=false
``` ```
??? info "`encodedCharacters.allowEncodedNullCharacter`" ??? info "`encodedCharacters.allowEncodedNullCharacter`"
_Optional, Default=false_ _Optional, Default=true_
Controls whether requests with encoded null characters (`%00`) in the path are allowed. Controls whether requests with encoded null characters (`%00`) in the path are allowed.
@ -1268,7 +1269,7 @@ By default, Traefik rejects requests with path containing certain encoded charac
address: ":80" address: ":80"
http: http:
encodedCharacters: encodedCharacters:
allowEncodedNullCharacter: true allowEncodedNullCharacter: false
``` ```
```toml tab="File (TOML)" ```toml tab="File (TOML)"
@ -1278,18 +1279,18 @@ By default, Traefik rejects requests with path containing certain encoded charac
address = ":80" address = ":80"
[entryPoints.web.http.encodedCharacters] [entryPoints.web.http.encodedCharacters]
allowEncodedNullCharacter = true allowEncodedNullCharacter = false
``` ```
```bash tab="CLI" ```bash tab="CLI"
## Static configuration ## Static configuration
--entryPoints.web.address=:80 --entryPoints.web.address=:80
--entryPoints.web.http.encodedCharacters.allowEncodedNullCharacter=true --entryPoints.web.http.encodedCharacters.allowEncodedNullCharacter=false
``` ```
??? info "`encodedCharacters.allowEncodedSemicolon`" ??? info "`encodedCharacters.allowEncodedSemicolon`"
_Optional, Default=false_ _Optional, Default=true_
Controls whether requests with encoded semicolon characters (`%3B` or `%3b`) in the path are allowed. Controls whether requests with encoded semicolon characters (`%3B` or `%3b`) in the path are allowed.
@ -1300,7 +1301,7 @@ By default, Traefik rejects requests with path containing certain encoded charac
address: ":80" address: ":80"
http: http:
encodedCharacters: encodedCharacters:
allowEncodedSemicolon: true allowEncodedSemicolon: false
``` ```
```toml tab="File (TOML)" ```toml tab="File (TOML)"
@ -1310,18 +1311,18 @@ By default, Traefik rejects requests with path containing certain encoded charac
address = ":80" address = ":80"
[entryPoints.web.http.encodedCharacters] [entryPoints.web.http.encodedCharacters]
allowEncodedSemicolon = true allowEncodedSemicolon = false
``` ```
```bash tab="CLI" ```bash tab="CLI"
## Static configuration ## Static configuration
--entryPoints.web.address=:80 --entryPoints.web.address=:80
--entryPoints.web.http.encodedCharacters.allowEncodedSemicolon=true --entryPoints.web.http.encodedCharacters.allowEncodedSemicolon=false
``` ```
??? info "`encodedCharacters.allowEncodedPercent`" ??? info "`encodedCharacters.allowEncodedPercent`"
_Optional, Default=false_ _Optional, Default=true_
Controls whether requests with encoded percent characters (`%25`) in the path are allowed. Controls whether requests with encoded percent characters (`%25`) in the path are allowed.
@ -1332,7 +1333,7 @@ By default, Traefik rejects requests with path containing certain encoded charac
address: ":80" address: ":80"
http: http:
encodedCharacters: encodedCharacters:
allowEncodedPercent: true allowEncodedPercent: false
``` ```
```toml tab="File (TOML)" ```toml tab="File (TOML)"
@ -1342,18 +1343,18 @@ By default, Traefik rejects requests with path containing certain encoded charac
address = ":80" address = ":80"
[entryPoints.web.http.encodedCharacters] [entryPoints.web.http.encodedCharacters]
allowEncodedPercent = true allowEncodedPercent = false
``` ```
```bash tab="CLI" ```bash tab="CLI"
## Static configuration ## Static configuration
--entryPoints.web.address=:80 --entryPoints.web.address=:80
--entryPoints.web.http.encodedCharacters.allowEncodedPercent=true --entryPoints.web.http.encodedCharacters.allowEncodedPercent=false
``` ```
??? info "`encodedCharacters.allowEncodedQuestionMark`" ??? info "`encodedCharacters.allowEncodedQuestionMark`"
_Optional, Default=false_ _Optional, Default=true_
Controls whether requests with encoded question mark characters (`%3F` or `%3f`) in the path are allowed. Controls whether requests with encoded question mark characters (`%3F` or `%3f`) in the path are allowed.
@ -1364,7 +1365,7 @@ By default, Traefik rejects requests with path containing certain encoded charac
address: ":80" address: ":80"
http: http:
encodedCharacters: encodedCharacters:
allowEncodedQuestionMark: true allowEncodedQuestionMark: false
``` ```
```toml tab="File (TOML)" ```toml tab="File (TOML)"
@ -1374,18 +1375,18 @@ By default, Traefik rejects requests with path containing certain encoded charac
address = ":80" address = ":80"
[entryPoints.web.http.encodedCharacters] [entryPoints.web.http.encodedCharacters]
allowEncodedQuestionMark = true allowEncodedQuestionMark = false
``` ```
```bash tab="CLI" ```bash tab="CLI"
## Static configuration ## Static configuration
--entryPoints.web.address=:80 --entryPoints.web.address=:80
--entryPoints.web.http.encodedCharacters.allowEncodedQuestionMark=true --entryPoints.web.http.encodedCharacters.allowEncodedQuestionMark=false
``` ```
??? info "`encodedCharacters.allowEncodedHash`" ??? info "`encodedCharacters.allowEncodedHash`"
_Optional, Default=false_ _Optional, Default=true_
Controls whether requests with encoded hash characters (`%23`) in the path are allowed. Controls whether requests with encoded hash characters (`%23`) in the path are allowed.
@ -1396,7 +1397,7 @@ By default, Traefik rejects requests with path containing certain encoded charac
address: ":80" address: ":80"
http: http:
encodedCharacters: encodedCharacters:
allowEncodedHash: true allowEncodedHash: false
``` ```
```toml tab="File (TOML)" ```toml tab="File (TOML)"
@ -1406,13 +1407,13 @@ By default, Traefik rejects requests with path containing certain encoded charac
address = ":80" address = ":80"
[entryPoints.web.http.encodedCharacters] [entryPoints.web.http.encodedCharacters]
allowEncodedHash = true allowEncodedHash = false
``` ```
```bash tab="CLI" ```bash tab="CLI"
## Static configuration ## Static configuration
--entryPoints.web.address=:80 --entryPoints.web.address=:80
--entryPoints.web.http.encodedCharacters.allowEncodedHash=true --entryPoints.web.http.encodedCharacters.allowEncodedHash=false
``` ```
### SanitizePath ### SanitizePath

View file

@ -20,7 +20,7 @@ When Traefik receives an HTTP request, it processes the request path through sev
Traefik inspects the path for potentially dangerous encoded characters and rejects requests containing them unless explicitly allowed. Traefik inspects the path for potentially dangerous encoded characters and rejects requests containing them unless explicitly allowed.
Here is the list of the encoded characters that are rejected by default: Here is the list of the encoded characters that are allowed by default:
| Encoded Character | Character | | Encoded Character | Character |
|-------------------|-------------------------| |-------------------|-------------------------|
@ -87,7 +87,12 @@ Configure it in the [EntryPoints](../routing/entrypoints.md#encoded-characters)
This filtering occurs before path sanitization and catches attack attempts that use encoding to bypass other security controls. This filtering occurs before path sanitization and catches attack attempts that use encoding to bypass other security controls.
All encoded character filtering is enabled by default (`false` means encoded characters are rejected), providing maximum security: All encoded character filtering is disabled by default (`true` means encoded characters are allowed).
!!! info "Security Considerations"
When your backend is not fully compliant with [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986) and notably decode encoded reserved characters in the requets path,
it is recommended to set these options to `false` to avoid split-view situation and helps prevent path traversal attacks or other malicious attempts to bypass security controls.
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
entryPoints: entryPoints:
@ -95,13 +100,13 @@ entryPoints:
address: ":443" address: ":443"
http: http:
encodedCharacters: encodedCharacters:
allowEncodedSlash: false # %2F - Default: false (RECOMMENDED) allowEncodedSlash: false # %2F - Default: true
allowEncodedBackSlash: false # %5C - Default: false (RECOMMENDED) allowEncodedBackSlash: false # %5C - Default: true
allowEncodedNullCharacter: false # %00 - Default: false (RECOMMENDED) allowEncodedNullCharacter: false # %00 - Default: true
allowEncodedSemicolon: false # %3B - Default: false (RECOMMENDED) allowEncodedSemicolon: false # %3B - Default: true
allowEncodedPercent: false # %25 - Default: false (RECOMMENDED) allowEncodedPercent: false # %25 - Default: true
allowEncodedQuestionMark: false # %3F - Default: false (RECOMMENDED) allowEncodedQuestionMark: false # %3F - Default: true
allowEncodedHash: false # %23 - Default: false (RECOMMENDED) allowEncodedHash: false # %23 - Default: true
``` ```
```toml tab="File (TOML)" ```toml tab="File (TOML)"

View file

@ -8,12 +8,18 @@
[entryPoints] [entryPoints]
[entryPoints.strict] [entryPoints.strict]
address = ":8000" address = ":8000"
# Default: no encoded characters allowed [entryPoints.strict.http.encodedCharacters]
allowEncodedSlash = false
[entryPoints.permissive] [entryPoints.permissive]
address = ":8001" address = ":8001"
# No config, default values should apply
[entryPoints.permissive2]
address = ":8002"
# No config for allowEncodedSlash, default value is effectively true
[entryPoints.permissive.http.encodedCharacters] [entryPoints.permissive.http.encodedCharacters]
allowEncodedSlash = true allowEncodedBackSlash = false
[api] [api]
insecure = true insecure = true

View file

@ -9,8 +9,6 @@
[entryPoints] [entryPoints]
[entryPoints.web] [entryPoints.web]
address = ":8000" address = ":8000"
[entryPoints.web.http.encodedCharacters]
allowEncodedSlash = true
[api] [api]
insecure = true insecure = true

View file

@ -2131,6 +2131,12 @@ func (s *SimpleSuite) TestEncodedCharactersDifferentEntryPoints() {
target: "127.0.0.1:8001", // permissive entry point target: "127.0.0.1:8001", // permissive entry point
expected: http.StatusOK, expected: http.StatusOK,
}, },
{
desc: "Encoded slash should be ALLOWED on permissive2 entry point",
request: "GET /path%2Fwith%2Fslash HTTP/1.1\r\nHost: test.localhost\r\n\r\n",
target: "127.0.0.1:8002", // permissive2 entry point
expected: http.StatusOK,
},
{ {
desc: "Regular path should work on strict entry point", desc: "Regular path should work on strict entry point",
request: "GET /regular/path HTTP/1.1\r\nHost: test.localhost\r\n\r\n", request: "GET /regular/path HTTP/1.1\r\nHost: test.localhost\r\n\r\n",
@ -2143,6 +2149,12 @@ func (s *SimpleSuite) TestEncodedCharactersDifferentEntryPoints() {
target: "127.0.0.1:8001", target: "127.0.0.1:8001",
expected: http.StatusOK, expected: http.StatusOK,
}, },
{
desc: "Regular path should work on permissive2 entry point",
request: "GET /regular/path HTTP/1.1\r\nHost: test.localhost\r\n\r\n",
target: "127.0.0.1:8002",
expected: http.StatusOK,
},
} }
for _, test := range testCases { for _, test := range testCases {

View file

@ -72,12 +72,12 @@ type Router struct {
Rule string `json:"rule,omitempty" toml:"rule,omitempty" yaml:"rule,omitempty"` Rule string `json:"rule,omitempty" toml:"rule,omitempty" yaml:"rule,omitempty"`
ParentRefs []string `json:"parentRefs,omitempty" toml:"parentRefs,omitempty" yaml:"parentRefs,omitempty" label:"-" export:"true"` ParentRefs []string `json:"parentRefs,omitempty" toml:"parentRefs,omitempty" yaml:"parentRefs,omitempty" label:"-" export:"true"`
// Deprecated: Please do not use this field and rewrite the router rules to use the v3 syntax. // Deprecated: Please do not use this field and rewrite the router rules to use the v3 syntax.
RuleSyntax string `json:"ruleSyntax,omitempty" toml:"ruleSyntax,omitempty" yaml:"ruleSyntax,omitempty" export:"true"` RuleSyntax string `json:"ruleSyntax,omitempty" toml:"ruleSyntax,omitempty" yaml:"ruleSyntax,omitempty" export:"true"`
Priority int `json:"priority,omitempty" toml:"priority,omitempty,omitzero" yaml:"priority,omitempty" export:"true"` Priority int `json:"priority,omitempty" toml:"priority,omitempty,omitzero" yaml:"priority,omitempty" export:"true"`
TLS *RouterTLSConfig `json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" label:"allowEmpty" file:"allowEmpty" kv:"allowEmpty" export:"true"` TLS *RouterTLSConfig `json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" label:"allowEmpty" file:"allowEmpty" kv:"allowEmpty" export:"true"`
Observability *RouterObservabilityConfig `json:"observability,omitempty" toml:"observability,omitempty" yaml:"observability,omitempty" export:"true"` Observability *RouterObservabilityConfig `json:"observability,omitempty" toml:"observability,omitempty" yaml:"observability,omitempty" export:"true"`
DefaultRule bool `json:"-" toml:"-" yaml:"-" label:"-" file:"-"` DefaultRule bool `json:"-" toml:"-" yaml:"-" label:"-" file:"-"`
DeniedEncodedPathCharacters RouterDeniedEncodedPathCharacters `json:"-" toml:"-" yaml:"-" label:"-" file:"-"` DeniedEncodedPathCharacters *RouterDeniedEncodedPathCharacters `json:"-" toml:"-" yaml:"-" label:"-" file:"-" kv:"-"`
} }
// +k8s:deepcopy-gen=true // +k8s:deepcopy-gen=true

View file

@ -1389,7 +1389,11 @@ func (in *Router) DeepCopyInto(out *Router) {
*out = new(RouterObservabilityConfig) *out = new(RouterObservabilityConfig)
(*in).DeepCopyInto(*out) (*in).DeepCopyInto(*out)
} }
out.DeniedEncodedPathCharacters = in.DeniedEncodedPathCharacters if in.DeniedEncodedPathCharacters != nil {
in, out := &in.DeniedEncodedPathCharacters, &out.DeniedEncodedPathCharacters
*out = new(RouterDeniedEncodedPathCharacters)
**out = **in
}
return return
} }

View file

@ -92,6 +92,16 @@ type EncodedCharacters struct {
AllowEncodedHash bool `description:"Defines whether requests with encoded hash characters in the path are allowed." json:"allowEncodedHash,omitempty" toml:"allowEncodedHash,omitempty" yaml:"allowEncodedHash,omitempty" export:"true"` AllowEncodedHash bool `description:"Defines whether requests with encoded hash characters in the path are allowed." json:"allowEncodedHash,omitempty" toml:"allowEncodedHash,omitempty" yaml:"allowEncodedHash,omitempty" export:"true"`
} }
func (ec *EncodedCharacters) SetDefaults() {
ec.AllowEncodedSlash = true
ec.AllowEncodedBackSlash = true
ec.AllowEncodedNullCharacter = true
ec.AllowEncodedSemicolon = true
ec.AllowEncodedPercent = true
ec.AllowEncodedQuestionMark = true
ec.AllowEncodedHash = true
}
// HTTP2Config is the HTTP2 configuration of an entry point. // HTTP2Config is the HTTP2 configuration of an entry point.
type HTTP2Config struct { type HTTP2Config struct {
MaxConcurrentStreams int32 `description:"Specifies the number of concurrent streams per connection that each client is allowed to initiate." json:"maxConcurrentStreams,omitempty" toml:"maxConcurrentStreams,omitempty" yaml:"maxConcurrentStreams,omitempty" export:"true"` MaxConcurrentStreams int32 `description:"Specifies the number of concurrent streams per connection that each client is allowed to initiate." json:"maxConcurrentStreams,omitempty" toml:"maxConcurrentStreams,omitempty" yaml:"maxConcurrentStreams,omitempty" export:"true"`

View file

@ -215,7 +215,7 @@ func applyModel(cfg dynamic.Configuration) dynamic.Configuration {
if m.DeniedEncodedPathCharacters != nil { if m.DeniedEncodedPathCharacters != nil {
// As the denied encoded path characters option is not configurable at the router level, // As the denied encoded path characters option is not configurable at the router level,
// we can simply copy the whole structure to override the router's default config. // we can simply copy the whole structure to override the router's default config.
cp.DeniedEncodedPathCharacters = *m.DeniedEncodedPathCharacters cp.DeniedEncodedPathCharacters = m.DeniedEncodedPathCharacters
} }
if cp.Observability == nil { if cp.Observability == nil {

View file

@ -2,29 +2,10 @@ package router
import ( import (
"net/http" "net/http"
"strings"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
// denyFragment rejects the request if the URL path contains a fragment (hash character).
// When go receives an HTTP request, it assumes the absence of fragment URL.
// However, it is still possible to send a fragment in the request.
// In this case, Traefik will encode the '#' character, altering the request's intended meaning.
// To avoid this behavior, the following function rejects requests that include a fragment in the URL.
func denyFragment(h http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
if strings.Contains(req.URL.RawPath, "#") {
log.Debug().Msgf("Rejecting request because it contains a fragment in the URL path: %s", req.URL.RawPath)
rw.WriteHeader(http.StatusBadRequest)
return
}
h.ServeHTTP(rw, req)
})
}
// denyEncodedPathCharacters reject the request if the escaped path contains encoded characters in the given list. // denyEncodedPathCharacters reject the request if the escaped path contains encoded characters in the given list.
func denyEncodedPathCharacters(encodedCharacters map[string]struct{}, h http.Handler) http.Handler { func denyEncodedPathCharacters(encodedCharacters map[string]struct{}, h http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {

View file

@ -8,42 +8,6 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func Test_denyFragment(t *testing.T) {
tests := []struct {
name string
url string
wantStatus int
}{
{
name: "Rejects fragment character",
url: "http://example.com/#",
wantStatus: http.StatusBadRequest,
},
{
name: "Allows without fragment",
url: "http://example.com/",
wantStatus: http.StatusOK,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
t.Parallel()
handler := denyFragment(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}))
req := httptest.NewRequest(http.MethodGet, test.url, nil)
res := httptest.NewRecorder()
handler.ServeHTTP(res, req)
assert.Equal(t, test.wantStatus, res.Code)
})
}
}
func Test_denyEncodedPathCharacters(t *testing.T) { func Test_denyEncodedPathCharacters(t *testing.T) {
tests := []struct { tests := []struct {
name string name string

View file

@ -274,10 +274,7 @@ func (m *Manager) buildHTTPHandler(ctx context.Context, router *runtime.RouterIn
// Here we are adding deny handlers for encoded path characters and fragment. // Here we are adding deny handlers for encoded path characters and fragment.
// Deny handler are only added for root routers, child routers are protected by their parent router deny handlers. // Deny handler are only added for root routers, child routers are protected by their parent router deny handlers.
if len(router.ParentRefs) == 0 { if len(router.ParentRefs) == 0 && router.DeniedEncodedPathCharacters != nil {
chain = chain.Append(func(next http.Handler) (http.Handler, error) {
return denyFragment(next), nil
})
chain = chain.Append(func(next http.Handler) (http.Handler, error) { chain = chain.Append(func(next http.Handler) (http.Handler, error) {
return denyEncodedPathCharacters(router.DeniedEncodedPathCharacters.Map(), next), nil return denyEncodedPathCharacters(router.DeniedEncodedPathCharacters.Map(), next), nil
}) })

View file

@ -1837,7 +1837,7 @@ func TestManager_BuildHandlers_Deny(t *testing.T) {
}, },
}, },
}, },
expectedStatusCode: http.StatusBadRequest, expectedStatusCode: http.StatusOK,
}, },
{ {
desc: "parent router with child routers, request with encoded slash", desc: "parent router with child routers, request with encoded slash",
@ -1860,18 +1860,18 @@ func TestManager_BuildHandlers_Deny(t *testing.T) {
}, },
}, },
}, },
expectedStatusCode: http.StatusBadRequest, expectedStatusCode: http.StatusOK,
}, },
{ {
desc: "parent router allowing encoded slash without child router", desc: "parent router disallowing encoded slash without child router",
requestPath: "/foo%2F", requestPath: "/foo%2F",
routers: map[string]*dynamic.Router{ routers: map[string]*dynamic.Router{
"parent": { "parent": {
EntryPoints: []string{"web"}, EntryPoints: []string{"web"},
Rule: "PathPrefix(`/`)", Rule: "PathPrefix(`/`)",
Service: "service", Service: "service",
DeniedEncodedPathCharacters: dynamic.RouterDeniedEncodedPathCharacters{ DeniedEncodedPathCharacters: &dynamic.RouterDeniedEncodedPathCharacters{
AllowEncodedSlash: true, AllowEncodedSlash: false,
}, },
}, },
}, },
@ -1882,17 +1882,17 @@ func TestManager_BuildHandlers_Deny(t *testing.T) {
}, },
}, },
}, },
expectedStatusCode: http.StatusOK, expectedStatusCode: http.StatusBadRequest,
}, },
{ {
desc: "parent router allowing encoded slash with child routers", desc: "parent router disallowing encoded slash with child routers",
requestPath: "/foo%2F", requestPath: "/foo%2F",
routers: map[string]*dynamic.Router{ routers: map[string]*dynamic.Router{
"parent": { "parent": {
EntryPoints: []string{"web"}, EntryPoints: []string{"web"},
Rule: "PathPrefix(`/`)", Rule: "PathPrefix(`/`)",
DeniedEncodedPathCharacters: dynamic.RouterDeniedEncodedPathCharacters{ DeniedEncodedPathCharacters: &dynamic.RouterDeniedEncodedPathCharacters{
AllowEncodedSlash: true, AllowEncodedSlash: false,
}, },
}, },
"child1": { "child1": {
@ -1908,48 +1908,6 @@ func TestManager_BuildHandlers_Deny(t *testing.T) {
}, },
}, },
}, },
expectedStatusCode: http.StatusOK,
},
{
desc: "parent router without child routers, request with fragment",
requestPath: "/foo#",
routers: map[string]*dynamic.Router{
"parent": {
EntryPoints: []string{"web"},
Rule: "PathPrefix(`/`)",
Service: "service",
},
},
services: map[string]*dynamic.Service{
"service": {
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{{URL: "http://localhost:8080"}},
},
},
},
expectedStatusCode: http.StatusBadRequest,
},
{
desc: "parent router with child routers, request with fragment",
requestPath: "/foo#",
routers: map[string]*dynamic.Router{
"parent": {
EntryPoints: []string{"web"},
Rule: "PathPrefix(`/`)",
},
"child1": {
Rule: "Path(`/v1`)",
Service: "child1-service",
ParentRefs: []string{"parent"},
},
},
services: map[string]*dynamic.Service{
"child1-service": {
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{{URL: "http://localhost:8080"}},
},
},
},
expectedStatusCode: http.StatusBadRequest, expectedStatusCode: http.StatusBadRequest,
}, },
} }

View file

@ -683,6 +683,8 @@ func newHTTPServer(ctx context.Context, ln net.Listener, configuration *static.E
handler = normalizePath(handler) handler = normalizePath(handler)
handler = denyFragment(handler)
serverHTTP := &http.Server{ serverHTTP := &http.Server{
Protocols: &protocols, Protocols: &protocols,
Handler: handler, Handler: handler,
@ -765,6 +767,24 @@ func (t *trackedConnection) Close() error {
return t.WriteCloser.Close() return t.WriteCloser.Close()
} }
// denyFragment rejects the request if the URL path contains a fragment (hash character).
// When go receives an HTTP request, it assumes the absence of fragment URL.
// However, it is still possible to send a fragment in the request.
// In this case, Traefik will encode the '#' character, altering the request's intended meaning.
// To avoid this behavior, the following function rejects requests that include a fragment in the URL.
func denyFragment(h http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
if strings.Contains(req.URL.RawPath, "#") {
log.Debug().Msgf("Rejecting request because it contains a fragment in the URL path: %s", req.URL.RawPath)
rw.WriteHeader(http.StatusBadRequest)
return
}
h.ServeHTTP(rw, req)
})
}
// This function is inspired by http.AllowQuerySemicolons. // This function is inspired by http.AllowQuerySemicolons.
func encodeQuerySemicolons(h http.Handler) http.Handler { func encodeQuerySemicolons(h http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {

View file

@ -387,6 +387,42 @@ func TestKeepAliveH2c(t *testing.T) {
require.Contains(t, err.Error(), "use of closed network connection") require.Contains(t, err.Error(), "use of closed network connection")
} }
func Test_denyFragment(t *testing.T) {
tests := []struct {
name string
url string
wantStatus int
}{
{
name: "Rejects fragment character",
url: "http://example.com/#",
wantStatus: http.StatusBadRequest,
},
{
name: "Allows without fragment",
url: "http://example.com/",
wantStatus: http.StatusOK,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
t.Parallel()
handler := denyFragment(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}))
req := httptest.NewRequest(http.MethodGet, test.url, nil)
res := httptest.NewRecorder()
handler.ServeHTTP(res, req)
assert.Equal(t, test.wantStatus, res.Code)
})
}
}
func TestSanitizePath(t *testing.T) { func TestSanitizePath(t *testing.T) {
tests := []struct { tests := []struct {
path string path string