Merge branch v2.11 into v3.6
This commit is contained in:
commit
8479d66d18
23 changed files with 266 additions and 224 deletions
|
|
@ -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)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v3.6.5...v3.6.6)
|
||||
|
||||
|
|
|
|||
|
|
@ -97,10 +97,10 @@ func runCmd(staticConfiguration *static.Configuration) error {
|
|||
return fmt.Errorf("setting up logger: %w", err)
|
||||
}
|
||||
|
||||
// Display warning to advertise for new behavior of rejecting encoded characters in the request path.
|
||||
// Deprecated: this has to be removed in the next minor/major version.
|
||||
log.Warn().Msg("Starting with v3.6.4, Traefik now rejects some encoded characters in the request path by default. " +
|
||||
"Refer to the documentation for more details: https://doc.traefik.io/traefik/migrate/v3/#encoded-characters-in-request-path")
|
||||
log.Warn().Msg("Traefik can reject some encoded characters in the request path." +
|
||||
"When your backend is not fully compliant with [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986)," +
|
||||
"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/v3.6/migrate/v3/#encoded-characters-configuration-default-values")
|
||||
|
||||
http.DefaultTransport.(*http.Transport).Proxy = http.ProxyFromEnvironment
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,14 @@
|
|||
/* Highlight */
|
||||
(function(hljs) {
|
||||
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);
|
||||
})();
|
||||
|
|
@ -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` |
|
||||
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -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-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-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-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-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-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-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-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-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-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. | 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. | 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. | 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. | 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. | 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. | 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-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. | |
|
||||
|
|
|
|||
|
|
@ -84,8 +84,8 @@ additionalArguments:
|
|||
|
||||
## 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-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 |
|
||||
|
|
@ -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-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-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-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-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-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-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-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-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-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. | 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. | 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. | 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. | 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. | 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. | 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-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-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 |
|
||||
|
|
@ -220,16 +220,22 @@ it can lead to unsafe routing when the `sanitizePath` option is set to `false`.
|
|||
### Encoded Characters
|
||||
|
||||
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
|
||||
|
||||
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).
|
||||
|
||||
Allowing certain encoded characters may expose your application to security vulnerabilities.
|
||||
!!! 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:
|
||||
|
||||
| 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-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) |
|
||||
|
|
|
|||
|
|
@ -238,25 +238,25 @@ Trust only forwarded headers from selected IPs.
|
|||
HTTP configuration.
|
||||
|
||||
`--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`:
|
||||
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`:
|
||||
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`:
|
||||
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`:
|
||||
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`:
|
||||
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`:
|
||||
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`:
|
||||
Defines whether request query semicolons should be URLEncoded. (Default: ```false```)
|
||||
|
|
|
|||
|
|
@ -247,25 +247,25 @@ HTTP/3 configuration. (Default: ```false```)
|
|||
UDP port to advertise, on which HTTP/3 is available. (Default: ```0```)
|
||||
|
||||
`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`:
|
||||
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`:
|
||||
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`:
|
||||
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`:
|
||||
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`:
|
||||
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`:
|
||||
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`:
|
||||
Defines whether request query semicolons should be URLEncoded. (Default: ```false```)
|
||||
|
|
|
|||
|
|
@ -131,13 +131,13 @@ They can be defined by using a file (YAML or TOML) or CLI arguments.
|
|||
- "192.168.0.1"
|
||||
http:
|
||||
encodedCharacters:
|
||||
allowEncodedSlash: true
|
||||
allowEncodedBackSlash: true
|
||||
allowEncodedNullCharacter: true
|
||||
allowEncodedSemicolon: true
|
||||
allowEncodedPercent: true
|
||||
allowEncodedQuestionMark: true
|
||||
allowEncodedHash: true
|
||||
allowEncodedSlash: false
|
||||
allowEncodedBackSlash: false
|
||||
allowEncodedNullCharacter: false
|
||||
allowEncodedSemicolon: false
|
||||
allowEncodedPercent: false
|
||||
allowEncodedQuestionMark: false
|
||||
allowEncodedHash: false
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
|
|
@ -166,13 +166,13 @@ They can be defined by using a file (YAML or TOML) or CLI arguments.
|
|||
insecure = true
|
||||
trustedIPs = ["127.0.0.1", "192.168.0.1"]
|
||||
[entryPoints.name.http.encodedCharacters]
|
||||
allowEncodedSlash = true
|
||||
allowEncodedBackSlash = true
|
||||
allowEncodedNullCharacter = true
|
||||
allowEncodedSemicolon = true
|
||||
allowEncodedPercent = true
|
||||
allowEncodedQuestionMark = true
|
||||
allowEncodedHash = true
|
||||
allowEncodedSlash = false
|
||||
allowEncodedBackSlash = false
|
||||
allowEncodedNullCharacter = false
|
||||
allowEncodedSemicolon = false
|
||||
allowEncodedPercent = false
|
||||
allowEncodedQuestionMark = false
|
||||
allowEncodedHash = false
|
||||
```
|
||||
|
||||
```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.forwardedHeaders.insecure=true
|
||||
--entryPoints.name.forwardedHeaders.trustedIPs=127.0.0.1,192.168.0.1
|
||||
--entryPoints.name.http.encodedCharacters.allowEncodedSlash=true
|
||||
--entryPoints.name.http.encodedCharacters.allowEncodedBackSlash=true
|
||||
--entryPoints.name.http.encodedCharacters.allowEncodedNullCharacter=true
|
||||
--entryPoints.name.http.encodedCharacters.allowEncodedSemicolon=true
|
||||
--entryPoints.name.http.encodedCharacters.allowEncodedPercent=true
|
||||
--entryPoints.name.http.encodedCharacters.allowEncodedQuestionMark=true
|
||||
--entryPoints.name.http.encodedCharacters.allowEncodedHash=true
|
||||
--entryPoints.name.http.encodedCharacters.allowEncodedSlash=false
|
||||
--entryPoints.name.http.encodedCharacters.allowEncodedBackSlash=false
|
||||
--entryPoints.name.http.encodedCharacters.allowEncodedNullCharacter=false
|
||||
--entryPoints.name.http.encodedCharacters.allowEncodedSemicolon=false
|
||||
--entryPoints.name.http.encodedCharacters.allowEncodedPercent=false
|
||||
--entryPoints.name.http.encodedCharacters.allowEncodedQuestionMark=false
|
||||
--entryPoints.name.http.encodedCharacters.allowEncodedHash=false
|
||||
```
|
||||
|
||||
### Address
|
||||
|
|
@ -1180,20 +1180,21 @@ entryPoints:
|
|||
### Encoded Characters
|
||||
|
||||
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
|
||||
|
||||
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).
|
||||
|
||||
!!! 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`"
|
||||
|
||||
_Optional, Default=false_
|
||||
_Optional, Default=true_
|
||||
|
||||
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"
|
||||
http:
|
||||
encodedCharacters:
|
||||
allowEncodedSlash: true
|
||||
allowEncodedSlash: false
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
|
|
@ -1214,18 +1215,18 @@ By default, Traefik rejects requests with path containing certain encoded charac
|
|||
address = ":80"
|
||||
|
||||
[entryPoints.web.http.encodedCharacters]
|
||||
allowEncodedSlash = true
|
||||
allowEncodedSlash = false
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
## Static configuration
|
||||
--entryPoints.web.address=:80
|
||||
--entryPoints.web.http.encodedCharacters.allowEncodedSlash=true
|
||||
--entryPoints.web.http.encodedCharacters.allowEncodedSlash=false
|
||||
```
|
||||
|
||||
??? 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.
|
||||
|
||||
|
|
@ -1236,7 +1237,7 @@ By default, Traefik rejects requests with path containing certain encoded charac
|
|||
address: ":80"
|
||||
http:
|
||||
encodedCharacters:
|
||||
allowEncodedBackSlash: true
|
||||
allowEncodedBackSlash: false
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
|
|
@ -1246,18 +1247,18 @@ By default, Traefik rejects requests with path containing certain encoded charac
|
|||
address = ":80"
|
||||
|
||||
[entryPoints.web.http.encodedCharacters]
|
||||
allowEncodedBackSlash = true
|
||||
allowEncodedBackSlash = false
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
## Static configuration
|
||||
--entryPoints.web.address=:80
|
||||
--entryPoints.web.http.encodedCharacters.allowEncodedBackSlash=true
|
||||
--entryPoints.web.http.encodedCharacters.allowEncodedBackSlash=false
|
||||
```
|
||||
|
||||
??? info "`encodedCharacters.allowEncodedNullCharacter`"
|
||||
|
||||
_Optional, Default=false_
|
||||
_Optional, Default=true_
|
||||
|
||||
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"
|
||||
http:
|
||||
encodedCharacters:
|
||||
allowEncodedNullCharacter: true
|
||||
allowEncodedNullCharacter: false
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
|
|
@ -1278,18 +1279,18 @@ By default, Traefik rejects requests with path containing certain encoded charac
|
|||
address = ":80"
|
||||
|
||||
[entryPoints.web.http.encodedCharacters]
|
||||
allowEncodedNullCharacter = true
|
||||
allowEncodedNullCharacter = false
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
## Static configuration
|
||||
--entryPoints.web.address=:80
|
||||
--entryPoints.web.http.encodedCharacters.allowEncodedNullCharacter=true
|
||||
--entryPoints.web.http.encodedCharacters.allowEncodedNullCharacter=false
|
||||
```
|
||||
|
||||
??? info "`encodedCharacters.allowEncodedSemicolon`"
|
||||
|
||||
_Optional, Default=false_
|
||||
_Optional, Default=true_
|
||||
|
||||
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"
|
||||
http:
|
||||
encodedCharacters:
|
||||
allowEncodedSemicolon: true
|
||||
allowEncodedSemicolon: false
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
|
|
@ -1310,18 +1311,18 @@ By default, Traefik rejects requests with path containing certain encoded charac
|
|||
address = ":80"
|
||||
|
||||
[entryPoints.web.http.encodedCharacters]
|
||||
allowEncodedSemicolon = true
|
||||
allowEncodedSemicolon = false
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
## Static configuration
|
||||
--entryPoints.web.address=:80
|
||||
--entryPoints.web.http.encodedCharacters.allowEncodedSemicolon=true
|
||||
--entryPoints.web.http.encodedCharacters.allowEncodedSemicolon=false
|
||||
```
|
||||
|
||||
??? info "`encodedCharacters.allowEncodedPercent`"
|
||||
|
||||
_Optional, Default=false_
|
||||
_Optional, Default=true_
|
||||
|
||||
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"
|
||||
http:
|
||||
encodedCharacters:
|
||||
allowEncodedPercent: true
|
||||
allowEncodedPercent: false
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
|
|
@ -1342,18 +1343,18 @@ By default, Traefik rejects requests with path containing certain encoded charac
|
|||
address = ":80"
|
||||
|
||||
[entryPoints.web.http.encodedCharacters]
|
||||
allowEncodedPercent = true
|
||||
allowEncodedPercent = false
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
## Static configuration
|
||||
--entryPoints.web.address=:80
|
||||
--entryPoints.web.http.encodedCharacters.allowEncodedPercent=true
|
||||
--entryPoints.web.http.encodedCharacters.allowEncodedPercent=false
|
||||
```
|
||||
|
||||
??? 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.
|
||||
|
||||
|
|
@ -1364,7 +1365,7 @@ By default, Traefik rejects requests with path containing certain encoded charac
|
|||
address: ":80"
|
||||
http:
|
||||
encodedCharacters:
|
||||
allowEncodedQuestionMark: true
|
||||
allowEncodedQuestionMark: false
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
|
|
@ -1374,18 +1375,18 @@ By default, Traefik rejects requests with path containing certain encoded charac
|
|||
address = ":80"
|
||||
|
||||
[entryPoints.web.http.encodedCharacters]
|
||||
allowEncodedQuestionMark = true
|
||||
allowEncodedQuestionMark = false
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
## Static configuration
|
||||
--entryPoints.web.address=:80
|
||||
--entryPoints.web.http.encodedCharacters.allowEncodedQuestionMark=true
|
||||
--entryPoints.web.http.encodedCharacters.allowEncodedQuestionMark=false
|
||||
```
|
||||
|
||||
??? info "`encodedCharacters.allowEncodedHash`"
|
||||
|
||||
_Optional, Default=false_
|
||||
_Optional, Default=true_
|
||||
|
||||
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"
|
||||
http:
|
||||
encodedCharacters:
|
||||
allowEncodedHash: true
|
||||
allowEncodedHash: false
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
|
|
@ -1406,13 +1407,13 @@ By default, Traefik rejects requests with path containing certain encoded charac
|
|||
address = ":80"
|
||||
|
||||
[entryPoints.web.http.encodedCharacters]
|
||||
allowEncodedHash = true
|
||||
allowEncodedHash = false
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
## Static configuration
|
||||
--entryPoints.web.address=:80
|
||||
--entryPoints.web.http.encodedCharacters.allowEncodedHash=true
|
||||
--entryPoints.web.http.encodedCharacters.allowEncodedHash=false
|
||||
```
|
||||
|
||||
### SanitizePath
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
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 |
|
||||
|-------------------|-------------------------|
|
||||
|
|
@ -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.
|
||||
|
||||
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)"
|
||||
entryPoints:
|
||||
|
|
@ -95,13 +100,13 @@ entryPoints:
|
|||
address: ":443"
|
||||
http:
|
||||
encodedCharacters:
|
||||
allowEncodedSlash: false # %2F - Default: false (RECOMMENDED)
|
||||
allowEncodedBackSlash: false # %5C - Default: false (RECOMMENDED)
|
||||
allowEncodedNullCharacter: false # %00 - Default: false (RECOMMENDED)
|
||||
allowEncodedSemicolon: false # %3B - Default: false (RECOMMENDED)
|
||||
allowEncodedPercent: false # %25 - Default: false (RECOMMENDED)
|
||||
allowEncodedQuestionMark: false # %3F - Default: false (RECOMMENDED)
|
||||
allowEncodedHash: false # %23 - Default: false (RECOMMENDED)
|
||||
allowEncodedSlash: false # %2F - Default: true
|
||||
allowEncodedBackSlash: false # %5C - Default: true
|
||||
allowEncodedNullCharacter: false # %00 - Default: true
|
||||
allowEncodedSemicolon: false # %3B - Default: true
|
||||
allowEncodedPercent: false # %25 - Default: true
|
||||
allowEncodedQuestionMark: false # %3F - Default: true
|
||||
allowEncodedHash: false # %23 - Default: true
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
|
|
|
|||
|
|
@ -8,12 +8,18 @@
|
|||
[entryPoints]
|
||||
[entryPoints.strict]
|
||||
address = ":8000"
|
||||
# Default: no encoded characters allowed
|
||||
[entryPoints.strict.http.encodedCharacters]
|
||||
allowEncodedSlash = false
|
||||
|
||||
[entryPoints.permissive]
|
||||
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]
|
||||
allowEncodedSlash = true
|
||||
allowEncodedBackSlash = false
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
|
|
|||
|
|
@ -9,8 +9,6 @@
|
|||
[entryPoints]
|
||||
[entryPoints.web]
|
||||
address = ":8000"
|
||||
[entryPoints.web.http.encodedCharacters]
|
||||
allowEncodedSlash = true
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
|
|
|||
|
|
@ -2131,6 +2131,12 @@ func (s *SimpleSuite) TestEncodedCharactersDifferentEntryPoints() {
|
|||
target: "127.0.0.1:8001", // permissive entry point
|
||||
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",
|
||||
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",
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -72,12 +72,12 @@ type Router struct {
|
|||
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"`
|
||||
// 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"`
|
||||
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"`
|
||||
Observability *RouterObservabilityConfig `json:"observability,omitempty" toml:"observability,omitempty" yaml:"observability,omitempty" export:"true"`
|
||||
DefaultRule bool `json:"-" toml:"-" yaml:"-" label:"-" file:"-"`
|
||||
DeniedEncodedPathCharacters RouterDeniedEncodedPathCharacters `json:"-" toml:"-" yaml:"-" label:"-" file:"-"`
|
||||
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"`
|
||||
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"`
|
||||
DefaultRule bool `json:"-" toml:"-" yaml:"-" label:"-" file:"-"`
|
||||
DeniedEncodedPathCharacters *RouterDeniedEncodedPathCharacters `json:"-" toml:"-" yaml:"-" label:"-" file:"-" kv:"-"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
|
|
|||
|
|
@ -1389,7 +1389,11 @@ func (in *Router) DeepCopyInto(out *Router) {
|
|||
*out = new(RouterObservabilityConfig)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
out.DeniedEncodedPathCharacters = in.DeniedEncodedPathCharacters
|
||||
if in.DeniedEncodedPathCharacters != nil {
|
||||
in, out := &in.DeniedEncodedPathCharacters, &out.DeniedEncodedPathCharacters
|
||||
*out = new(RouterDeniedEncodedPathCharacters)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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"`
|
||||
}
|
||||
|
||||
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.
|
||||
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"`
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ func applyModel(cfg dynamic.Configuration) dynamic.Configuration {
|
|||
if m.DeniedEncodedPathCharacters != nil {
|
||||
// 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.
|
||||
cp.DeniedEncodedPathCharacters = *m.DeniedEncodedPathCharacters
|
||||
cp.DeniedEncodedPathCharacters = m.DeniedEncodedPathCharacters
|
||||
}
|
||||
|
||||
if cp.Observability == nil {
|
||||
|
|
|
|||
|
|
@ -2,29 +2,10 @@ package router
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"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.
|
||||
func denyEncodedPathCharacters(encodedCharacters map[string]struct{}, h http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||
|
|
|
|||
|
|
@ -8,42 +8,6 @@ import (
|
|||
"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) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
// Deny handler are only added for root routers, child routers are protected by their parent router deny handlers.
|
||||
if len(router.ParentRefs) == 0 {
|
||||
chain = chain.Append(func(next http.Handler) (http.Handler, error) {
|
||||
return denyFragment(next), nil
|
||||
})
|
||||
if len(router.ParentRefs) == 0 && router.DeniedEncodedPathCharacters != nil {
|
||||
chain = chain.Append(func(next http.Handler) (http.Handler, error) {
|
||||
return denyEncodedPathCharacters(router.DeniedEncodedPathCharacters.Map(), next), nil
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
@ -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",
|
||||
routers: map[string]*dynamic.Router{
|
||||
"parent": {
|
||||
EntryPoints: []string{"web"},
|
||||
Rule: "PathPrefix(`/`)",
|
||||
Service: "service",
|
||||
DeniedEncodedPathCharacters: dynamic.RouterDeniedEncodedPathCharacters{
|
||||
AllowEncodedSlash: true,
|
||||
DeniedEncodedPathCharacters: &dynamic.RouterDeniedEncodedPathCharacters{
|
||||
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",
|
||||
routers: map[string]*dynamic.Router{
|
||||
"parent": {
|
||||
EntryPoints: []string{"web"},
|
||||
Rule: "PathPrefix(`/`)",
|
||||
DeniedEncodedPathCharacters: dynamic.RouterDeniedEncodedPathCharacters{
|
||||
AllowEncodedSlash: true,
|
||||
DeniedEncodedPathCharacters: &dynamic.RouterDeniedEncodedPathCharacters{
|
||||
AllowEncodedSlash: false,
|
||||
},
|
||||
},
|
||||
"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,
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -683,6 +683,8 @@ func newHTTPServer(ctx context.Context, ln net.Listener, configuration *static.E
|
|||
|
||||
handler = normalizePath(handler)
|
||||
|
||||
handler = denyFragment(handler)
|
||||
|
||||
serverHTTP := &http.Server{
|
||||
Protocols: &protocols,
|
||||
Handler: handler,
|
||||
|
|
@ -765,6 +767,24 @@ func (t *trackedConnection) Close() error {
|
|||
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.
|
||||
func encodeQuerySemicolons(h http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||
|
|
|
|||
|
|
@ -387,6 +387,42 @@ func TestKeepAliveH2c(t *testing.T) {
|
|||
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) {
|
||||
tests := []struct {
|
||||
path string
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue