CVE-2026-55824
Contao crawler leaks auth credentials to external hosts
Contao is an Open Source CMS. In versions 4.13.40 through 5.3.46 and 5.7.0-RC1 through 5.7.6, the crawler leaks auth credentials to external hosts. Contao's crawler tries to prevent confidential HTTP client options from being sent to external domains by creating a scoped client: full options for root page origins, cleaned options for everything else. The cleaner removes Cookie and Authorization headers, but it removes the non-Symfony option names basic_auth and bearer_auth instead of Symfony HttpClient's real auth_basic and auth_bearer options. When contao.crawl.default_http_client_options contains Basic or Bearer authentication for a protected staging/production site, those credentials remain in the "clean" client used for external links or configured additional URIs. An attacker who can get an external URL crawled, for example through a link on a crawled page while the broken-link checker is enabled, can receive the crawler credentials. This issue has been fixed in versions 5.3.47 and 5.7.7.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- High
- Privileges needed
- Low
- User interaction
- Required
What an attacker can affect
- Confidentiality
- Low
- Integrity
- None
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
2.6
Contao crawler leaks auth credentials to external hosts
Contao is an Open Source CMS. In versions 4.13.40 through 5.3.46 and 5.7.0-RC1 through 5.7.6, the crawler leaks auth credentials to external hosts. Contao's crawler tries to prevent confidential HTTP client options from being sent to external domains by creating a scoped client: full options for root page origins, cleaned options for everything else. The cleaner removes Cookie and Authorization headers, but it removes the non-Symfony option names basic_auth and bearer_auth instead of Symfony HttpClient's real auth_basic and auth_bearer options. When contao.crawl.default_http_client_options contains Basic or Bearer authentication for a protected staging/production site, those credentials remain in the "clean" client used for external links or configured additional URIs. An attacker who can get an external URL crawled, for example through a link on a crawled page while the broken-link checker is enabled, can receive the crawler credentials. This issue has been fixed in versions 5.3.47 and 5.7.7.
- Record
CVE-2026-55824- CVSS 3.1
- 2.6 Low
CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:L/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
EUVDEUVD-2026-51613
2.6
Contao is an Open Source CMS. In versions 4.13.40 through 5.3.46 and 5.7.0-RC1 through 5.7.6, the crawler leaks auth credentials to external hosts. Contao's crawler tries to prevent confidential HTTP client options from being sent to external domains by creating a scoped client: full options for root page origins, cleaned options for everything else. The cleaner removes Cookie and Authorization headers, but it removes the non-Symfony option names basic_auth and bearer_auth instead of Symfony HttpClient's real auth_basic and auth_bearer options. When contao.crawl.default_http_client_options contains Basic or Bearer authentication for a protected staging/production site, those credentials remain in the "clean" client used for external links or configured additional URIs. An attacker who can get an external URL crawled, for example through a link on a crawled page while the broken-link checker is enabled, can receive the crawler credentials. This issue has been fixed in versions 5.3.47 and 5.7.7.
- Record
EUVD-2026-51613- CVSS 3.1
- 2.6 Low
CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:L/I:N/A:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-3mr9-p497-58f6
2.6
Contao crawler leaks auth credentials to external hosts
Summary
Contao's crawler tries to prevent confidential HTTP client options from being sent to external domains by creating a scoped client: full options for root page origins, cleaned options for everything else. The cleaner removes Cookie and Authorization headers, but it removes the non-Symfony option names basic_auth and bearer_auth instead of Symfony HttpClient's real auth_basic and auth_bearer options.
When contao.crawl.default_http_client_options contains Basic or Bearer authentication for a protected staging/production site, those credentials remain in the "clean" client used for external links or configured additional URIs. An attacker who can get an external URL crawled, for example through a link on a crawled page while the broken-link checker is enabled, can receive the crawler credentials.
Technical Detail
Root Cause
// core-bundle/src/Crawl/Escargot/Factory.php:175-209 @ e550b92a01ef625bd546e6c3956dd200af05ebf0
private function createHttpClient(array $options = []): HttpClientInterface
{
$options = array_merge_recursive(
[
'headers' => [
'accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'user-agent' => self::USER_AGENT,
],
'max_duration' => 10,
],
array_merge_recursive($this->getDefaultHttpClientOptions(), $options),
);
$cleanOptions = $this->cleanOptionsFromConfidentialData($options);
if ($options === $cleanOptions) {
return ($this->httpClientFactory)($options);
}
$scopedOptionsByRegex = [];
foreach ($this->getRootPageUriCollection()->all() as $rootPageUri) {
$scopedOptionsByRegex[preg_quote($this->getOriginFromUri($rootPageUri))] = $options;
}
return new ScopingHttpClient(($this->httpClientFactory)($cleanOptions), $scopedOptionsByRegex);
}
// core-bundle/src/Crawl/Escargot/Factory.php:226-247 @ e550b92a01ef625bd546e6c3956dd200af05ebf0
foreach ($options as $k => $v) {
if ('headers' === $k) {
foreach ($v as $header => $value) {
if (\in_array(strtolower($header), ['authorization', 'cookie'], true)) {
continue;
}
$cleanOptions['headers'][$header] = $value;
}
continue;
}
if ('basic_auth' === $k || 'bearer_auth' === $k) {
continue;
}
$cleanOptions[$k] = $v;
}
Symfony HttpClient authentication options are auth_basic and auth_bearer; Contao's own manual documents auth_basic for crawler Basic Authentication. Because the cleaner only strips basic_auth and bearer_auth, the "clean" default client for non-root-page hosts still carries the real auth options. The existing factory test intends to assert that Authorization is not sent to www.foreign-domain.com, but its mock client factory ignores the $defaultOptions argument, so it does not catch auth options that survive into HttpClient::create($cleanOptions).
Suggested Mitigation
Strip the actual Symfony HttpClient authentication option keys from the clean client. Include NTLM as a defensive extension because Symfony documents it as another auth option.
- if ('basic_auth' === $k || 'bearer_auth' === $k) {
+ if (\in_array($k, ['auth_basic', 'auth_bearer', 'auth_ntlm', 'basic_auth', 'bearer_auth'], true)) {
continue;
}
Also update the factory test so the mock factory records or preserves $defaultOptions; otherwise the test does not verify what HttpClient::create($cleanOptions) receives in production.
Impact
- Direct primitive: disclosure of crawler Basic/Bearer credentials to an external host reached by the crawler.
- Chain potential: if those credentials protect a staging or pre-publication environment, an attacker can use them to access that environment. The impact depends on what the leaked credential unlocks.
- **Realistic…
- Record
GHSA-3mr9-p497-58f6- CVSS 3.1
- 2.6 Low
CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:L/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
NVD
2.6
Contao is an Open Source CMS. In versions 4.13.40 through 5.3.46 and 5.7.0-RC1 through 5.7.6, the crawler leaks auth credentials to external hosts. Contao's crawler tries to prevent confidential HTTP client options from being sent to external domains by creating a scoped client: full options for root page origins, cleaned options for everything else. The cleaner removes Cookie and Authorization headers, but it removes the non-Symfony option names basic_auth and bearer_auth instead of Symfony HttpClient's real auth_basic and auth_bearer options. When contao.crawl.default_http_client_options contains Basic or Bearer authentication for a protected staging/production site, those credentials remain in the "clean" client used for external links or configured additional URIs. An attacker who can get an external URL crawled, for example through a link on a crawled page while the broken-link checker is enabled, can receive the crawler credentials. This issue has been fixed in versions 5.3.47 and 5.7.7.
- Record
CVE-2026-55824- CVSS 3.1
- 2.6 Low
CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:L/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
OSV
2.6
Contao crawler leaks auth credentials to external hosts
Contao is an Open Source CMS. In versions 4.13.40 through 5.3.46 and 5.7.0-RC1 through 5.7.6, the crawler leaks auth credentials to external hosts. Contao's crawler tries to prevent confidential HTTP client options from being sent to external domains by creating a scoped client: full options for root page origins, cleaned options for everything else. The cleaner removes Cookie and Authorization headers, but it removes the non-Symfony option names basic_auth and bearer_auth instead of Symfony HttpClient's real auth_basic and auth_bearer options. When contao.crawl.default_http_client_options contains Basic or Bearer authentication for a protected staging/production site, those credentials remain in the "clean" client used for external links or configured additional URIs. An attacker who can get an external URL crawled, for example through a link on a crawled page while the broken-link checker is enabled, can receive the crawler credentials. This issue has been fixed in versions 5.3.47 and 5.7.7.
- Record
CVE-2026-55824- CVSS 3.1
- 2.6 Low
CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:L/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
OSVGHSA-3mr9-p497-58f6
2.6
Contao crawler leaks auth credentials to external hosts
Summary
Contao's crawler tries to prevent confidential HTTP client options from being sent to external domains by creating a scoped client: full options for root page origins, cleaned options for everything else. The cleaner removes Cookie and Authorization headers, but it removes the non-Symfony option names basic_auth and bearer_auth instead of Symfony HttpClient's real auth_basic and auth_bearer options.
When contao.crawl.default_http_client_options contains Basic or Bearer authentication for a protected staging/production site, those credentials remain in the "clean" client used for external links or configured additional URIs. An attacker who can get an external URL crawled, for example through a link on a crawled page while the broken-link checker is enabled, can receive the crawler credentials.
Technical Detail
Root Cause
// core-bundle/src/Crawl/Escargot/Factory.php:175-209 @ e550b92a01ef625bd546e6c3956dd200af05ebf0
private function createHttpClient(array $options = []): HttpClientInterface
{
$options = array_merge_recursive(
[
'headers' => [
'accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'user-agent' => self::USER_AGENT,
],
'max_duration' => 10,
],
array_merge_recursive($this->getDefaultHttpClientOptions(), $options),
);
$cleanOptions = $this->cleanOptionsFromConfidentialData($options);
if ($options === $cleanOptions) {
return ($this->httpClientFactory)($options);
}
$scopedOptionsByRegex = [];
foreach ($this->getRootPageUriCollection()->all() as $rootPageUri) {
$scopedOptionsByRegex[preg_quote($this->getOriginFromUri($rootPageUri))] = $options;
}
return new ScopingHttpClient(($this->httpClientFactory)($cleanOptions), $scopedOptionsByRegex);
}
// core-bundle/src/Crawl/Escargot/Factory.php:226-247 @ e550b92a01ef625bd546e6c3956dd200af05ebf0
foreach ($options as $k => $v) {
if ('headers' === $k) {
foreach ($v as $header => $value) {
if (\in_array(strtolower($header), ['authorization', 'cookie'], true)) {
continue;
}
$cleanOptions['headers'][$header] = $value;
}
continue;
}
if ('basic_auth' === $k || 'bearer_auth' === $k) {
continue;
}
$cleanOptions[$k] = $v;
}
Symfony HttpClient authentication options are auth_basic and auth_bearer; Contao's own manual documents auth_basic for crawler Basic Authentication. Because the cleaner only strips basic_auth and bearer_auth, the "clean" default client for non-root-page hosts still carries the real auth options. The existing factory test intends to assert that Authorization is not sent to www.foreign-domain.com, but its mock client factory ignores the $defaultOptions argument, so it does not catch auth options that survive into HttpClient::create($cleanOptions).
Suggested Mitigation
Strip the actual Symfony HttpClient authentication option keys from the clean client. Include NTLM as a defensive extension because Symfony documents it as another auth option.
- if ('basic_auth' === $k || 'bearer_auth' === $k) {
+ if (\in_array($k, ['auth_basic', 'auth_bearer', 'auth_ntlm', 'basic_auth', 'bearer_auth'], true)) {
continue;
}
Also update the factory test so the mock factory records or preserves $defaultOptions; otherwise the test does not verify what HttpClient::create($cleanOptions) receives in production.
Impact
- Direct primitive: disclosure of crawler Basic/Bearer credentials to an external host reached by the crawler.
- Chain potential: if those credentials protect a staging or pre-publication environment, an attacker can use them to access that environment. The impact depends on what the leaked credential unlocks.
- **Realistic…
- Record
GHSA-3mr9-p497-58f6- CVSS 3.1
- 2.6 Low
CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:L/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
contao/contaoPackagist |
4.13.0 up to 5.3.47 | 5.3.47 |
contao/contaoPackagist |
5.4.0 up to 5.7.7 | 5.7.7 |
contao/core-bundlePackagist |
4.13.0 up to 5.3.47 | 5.3.47 |
contao/core-bundlePackagist |
5.4.0 up to 5.7.7 | 5.7.7 |
contao/contaoPackagist |
4.13.0 up to 5.3.47, plus listed versions 4.13.14.13.104.13.114.13.124.13.13 Show 45 moreShow less4.13.144.13.154.13.164.13.174.13.184.13.194.13.24.13.204.13.214.13.224.13.234.13.244.13.254.13.264.13.274.13.284.13.294.13.34.13.304.13.314.13.324.13.334.13.344.13.354.13.364.13.374.13.384.13.394.13.44.13.404.13.414.13.424.13.434.13.444.13.454.13.464.13.474.13.484.13.494.13.54.13.504.13.514.13.524.13.534.13.54 |
5.3.47 |
contao/contaoPackagist |
5.4.0 up to 5.7.7, plus listed versions 5.4.15.4.105.4.115.4.125.4.13 Show 45 moreShow less5.4.145.4.25.4.35.4.45.4.55.4.65.4.75.4.85.4.95.5.05.5.0-RC15.5.0-RC25.5.0-RC35.5.0-RC45.5.15.5.105.5.115.5.125.5.135.5.145.5.155.5.165.5.25.5.35.5.45.5.55.5.65.5.75.5.85.5.95.6.05.6.0-RC15.6.0-RC25.6.0-RC35.6.15.6.105.6.115.6.25.6.35.6.45.6.55.6.65.6.75.6.85.6.9 |
5.7.7 |
contao/core-bundlePackagist |
4.13.0 up to 5.3.47, plus listed versions 4.13.14.13.104.13.114.13.124.13.13 Show 45 moreShow less4.13.144.13.154.13.164.13.174.13.184.13.194.13.24.13.204.13.214.13.224.13.234.13.244.13.254.13.264.13.274.13.284.13.294.13.34.13.304.13.314.13.324.13.334.13.344.13.354.13.364.13.374.13.384.13.394.13.44.13.404.13.414.13.424.13.434.13.444.13.454.13.464.13.474.13.484.13.494.13.54.13.504.13.514.13.524.13.534.13.54 |
5.3.47 |
contao/core-bundlePackagist |
5.4.0 up to 5.7.7, plus listed versions 5.4.15.4.105.4.115.4.125.4.13 Show 45 moreShow less5.4.145.4.25.4.35.4.45.4.55.4.65.4.75.4.85.4.95.5.05.5.0-RC15.5.0-RC25.5.0-RC35.5.0-RC45.5.15.5.105.5.115.5.125.5.135.5.145.5.155.5.165.5.25.5.35.5.45.5.55.5.65.5.75.5.85.5.95.6.05.6.0-RC15.6.0-RC25.6.0-RC35.6.15.6.105.6.115.6.25.6.35.6.45.6.55.6.65.6.75.6.85.6.9 |
5.7.7 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-55824 is a low vulnerability (CVSS 2.6) in Contao, published July 31, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.24%, the 15th percentile. Fixed in contao/contao 5.3.47.
References
github.com/contao/contao/security/advisories/GHSA-3mr9-p497-58f6
nvd.nist.gov/vuln/detail/CVE-2026-55824
github.com/contao/contao/commit/5bc6e3f900c439313df57aa561d0865792aafa05
github.com/contao/contao/commit/80425d28cdf66280a209bd3f5bc31b1a76901a04
contao.org/en/security-advisories/credentials-disclosure-in-the-crawler
github.com/FriendsOfPHP/security-advisories/blob/master/contao/contao/CVE-2026-55824.yaml
Left out here: 234 versions and the rest of 2 source descriptions. The JSON record has them.