Vulnerability GHSA-grm4-wm43-9jh5

Low Risk
LOW RISK
CVSS Score: 3.1
Score Range: < 4.0
Low severity vulnerabilities (CVSS < 4.0). Hygiene issues that can accumulate but pose lower immediate risk.
1 month ago
August 06, 2026 at 07:49 PM UTC
Contao: Possible path traversal in job download URIs
5.7.0 - 5.7.6
5.7.0 - 5.7.6

Summary

Contao: Possible path traversal in job download URIs

Details

Summary

An authenticated backend user who can access one job can request an attachment identifier containing ../ segments and make the job attachment download endpoint read a file from another job directory inside var/job-attachments.

The controller authorizes only the jobUuid route parameter. The later attachment lookup joins that authorized job UUID with the attacker-controlled identifier, then passes the combined path to the virtual filesystem. VirtualFilesystem::resolve() canonicalizes the whole path and only rejects paths that escape the filesystem mount, so authorized-job/../victim-job/debug_log.csv becomes victim-job/debug_log.csv.

This is a cross-job authorization bypass for known job attachment paths. It is not a practical brute-force against unknown jobs because job directories are UUID v4 values.

Root Cause

JobsController::downloadJobAttachment() checks access to the route jobUuid before loading the attachment:

$job = $this->jobs->getByUuid($jobUuid);

if (!$job || !$this->jobs->hasAccess($job)) {
    throw $this->createNotFoundException();
}

$attachment = $this->jobs->getAttachment($jobUuid, $identifier);

Jobs::getAttachment() then resolves a path built from the authorized job UUID and the attacker-controlled identifier:

$fileItem = $this->jobAttachmentsStorage->get($this->getAttachmentIdentifier($job, $identifier));
return $job->getUuid().'/'.$identifier;

VirtualFilesystem::resolve() canonicalizes the combined path. It rejects absolute paths and paths that start with .., but it does not preserve the authorized job directory as a boundary:

$path = Path::canonicalize($location);

if (str_starts_with($path, '..')) {
    throw new \OutOfBoundsException(...);
}

return Path::join($this->prefix, $path);

Therefore:

<authorized-job>/../<victim-job>/debug_log.csv

canonicalizes to:

<victim-job>/debug_log.csv

which remains inside the job-attachments filesystem mount and is accepted.

Recommended Fix

Treat the attachment identifier as a filename, not a path:

  • Reject /, \, NUL, and dot-segment components in identifier.
  • Add a route requirement that prevents slashes in {identifier} if nested attachment paths are not intended.
  • After resolving, assert the canonical relative path starts with <authorized-job-uuid>/ before returning a FilesystemItem.
  • Apply the same identifier validation in Jobs::addAttachment() so future producers/extensions cannot write outside the owning job directory.

Impact

A low-privileged backend user can read another job's attachment if they know or obtain the target job UUID and attachment filename. Built-in crawler jobs attach CSV logs such as debug_log.csv, broken-link-checker_log.csv, and search-index_log.csv, which can contain crawled URLs, referring URLs, tags, and error messages.

Related Vulnerabilities

Other vulnerabilities affecting the same packages

Low Risk
3 days ago
Contao: Server-Side Request Forgery (SSRF) via Unvalidated RSS Feed URL in Feed Reader Module
5.3.35 - 5.3.47 and 5.4.0 - 5.4.14 and 5.5.0 - 5.5.16 and 5.6.0 - 5.6.11 and 5.7.0 - 5.7.8 GHSA-87mg-5grr-rhwh
5.3.35 - 5.3.47 and 5.4.0 - 5.4.14 and 5.5.0 - 5.5.16 and 5.6.0 - 5.6.11 and 5.7.0 - 5.7.8 GHSA-87mg-5grr-rhwh
Low Risk
3 days ago
Contao: Server-Side Request Forgery (SSRF) via Unvalidated RSS Feed URL in Feed Reader Module
5.3.35 - 5.3.47 and 5.4.0 - 5.4.14 and 5.5.0 - 5.5.16 and 5.6.0 - 5.6.11 and 5.7.0 - 5.7.8 GHSA-87mg-5grr-rhwh
5.3.35 - 5.3.47 and 5.4.0 - 5.4.14 and 5.5.0 - 5.5.16 and 5.6.0 - 5.6.11 and 5.7.0 - 5.7.8 GHSA-87mg-5grr-rhwh
Low Risk
1 month ago
Contao crawler leaks auth credentials to external hosts
4.13.0 - 4.13.58 and 5.0.0 - 5.0.10 and 5.1.0 - 5.1.11 and 5.2.0 - 5.2.10 and 5.3.0 - 5.3.46 and 5.4.0 - 5.4.14 and 5.5.0 - 5.5.16 and 5.6.0 - 5.6.11 and 5.7.0 - 5.7.6 GHSA-3mr9-p497-58f6
4.13.0 - 4.13.58 and 5.0.0 - 5.0.10 and 5.1.0 - 5.1.11 and 5.2.0 - 5.2.10 and 5.3.0 - 5.3.46 and 5.4.0 - 5.4.14 and 5.5.0 - 5.5.16 and 5.6.0 - 5.6.11 and 5.7.0 - 5.7.6 GHSA-3mr9-p497-58f6
Low Risk
1 month ago
Contao crawler leaks auth credentials to external hosts
4.13.0 - 4.13.58 and 5.0.0 - 5.0.10 and 5.1.0 - 5.1.11 and 5.2.0 - 5.2.10 and 5.3.0 - 5.3.46 and 5.4.0 - 5.4.14 and 5.5.0 - 5.5.16 and 5.6.0 - 5.6.11 and 5.7.0 - 5.7.6 GHSA-3mr9-p497-58f6
4.13.0 - 4.13.58 and 5.0.0 - 5.0.10 and 5.1.0 - 5.1.11 and 5.2.0 - 5.2.10 and 5.3.0 - 5.3.46 and 5.4.0 - 5.4.14 and 5.5.0 - 5.5.16 and 5.6.0 - 5.6.11 and 5.7.0 - 5.7.6 GHSA-3mr9-p497-58f6
Low Risk
10 months ago
Contao is vulnerable to cross-site scripting in templates
4.0.0 - 4.0.4 and 4.1.0 - 4.1.3 and 4.2.0 - 4.2.5 and 4.3.0 - 4.3.11 and 4.4.0 - 4.4.57 and 4.5.0 - 4.5.14 and 4.6.0 - 4.6.14 and 4.7.0 - 4.7.7 and 4.8.0 - 4.8.8 and 4.9.0 - 4.9.42 and 4.10.0 - 4.10.7 and 4.11.0 - 4.11.9 and 4.12.0 - 4.12.7 and 4.13.0 - 4.13.56 and 5.0.0 - 5.0.10 and 5.1.0 - 5.1.11 and 5.2.0 - 5.2.10 and 5.3.0 - 5.3.41 and 5.4.0 - 5.4.14 and 5.5.0 - 5.5.16 and 5.6.0 - 5.6.4 GHSA-68q5-78xp-cwwc
4.0.0 - 4.0.4 and 4.1.0 - 4.1.3 and 4.2.0 - 4.2.5 and 4.3.0 - 4.3.11 and 4.4.0 - 4.4.57 and 4.5.0 - 4.5.14 and 4.6.0 - 4.6.14 and 4.7.0 - 4.7.7 and 4.8.0 - 4.8.8 and 4.9.0 - 4.9.42 and 4.10.0 - 4.10.7 and 4.11.0 - 4.11.9 and 4.12.0 - 4.12.7 and 4.13.0 - 4.13.56 and 5.0.0 - 5.0.10 and 5.1.0 - 5.1.11 and 5.2.0 - 5.2.10 and 5.3.0 - 5.3.41 and 5.4.0 - 5.4.14 and 5.5.0 - 5.5.16 and 5.6.0 - 5.6.4 GHSA-68q5-78xp-cwwc
View all vulnerabilities for these packages

Timeline

Published
1 month ago
August 06, 2026 at 07:49 PM UTC
Fixed (5.7.7)
3 months ago
June 15, 2026 at 10:46 AM UTC
Fixed (5.7.7)
3 months ago
June 15, 2026 at 03:39 PM UTC
Last Modified
1 month ago
August 06, 2026 at 08:00 PM UTC