CVE-2026-48013 — core
MEDIUMCVE-2026-48013 is a medium-severity (CVSS 4.1) Server-Side Request Forgery (SSRF) vulnerability in shopware/core. A fix is available for shopware/core — see the affected versions and patch details below.
Shopware: SSRF in Media External-Link Endpoint Bypasses IP Validation
Exploitation Status
No confirmed exploitation observed yet
- CISA’s own triage has not observed active exploitation or public proof-of-concept code for this CVE as of its last assessment.
Exploitation and automatability from CISA’s SSVC triage for CVE-2026-48013.
EPSS Exploitation Probability
Probability of exploitation in the next 30 days, from FIRST.org EPSS.
How urgent is this, really
CVE-2026-48013 by exploitation likelihood (EPSS) against impact (CVSS). Outside the shaded patch-first corner.
Where this sits among everything scored
Of 390,400 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Counts from FIRST.org, log-scaled.
Real-World Exposure
shopware/core🐘shopware/platformReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects Packagist packages — download data is not available via public APIs for these ecosystems.
Description
Summary
The /api/_action/media/external-link endpoint allows authenticated admin users to make server-side HTTP HEAD requests to arbitrary internal IP addresses. While the parallel uploadFromURL flow validates target IPs against private/reserved ranges via FileUrlValidator, the linkURL flow only performs a URL format check (regex for http:// or https:// prefix), allowing SSRF to internal network services and cloud metadata endpoints.
Details
The vulnerability is an inconsistency between two URL-handling flows in MediaUploadService.
Vulnerable path (external-link):
MediaUploadV2Controller::externalLink() at src/Core/Content/Media/Api/MediaUploadV2Controller.php:66 takes a user-supplied url parameter and passes it to MediaUploadService::linkURL() at src/Core/Content/Media/Upload/MediaUploadService.php:134.
linkURL() calls getContentSizeFromValidExternalUrl($url) at line 159, which only validates via validateExternalUrl():
// src/Core/Content/Media/Upload/MediaUploadService.php:207-212
public static function validateExternalUrl(string $url): void
{
if (!preg_match('/^https?:\/\/.+/', $url)) {
throw MediaException::invalidUrl($url);
}
}
Then makes a server-side HEAD request with no IP filtering:
// src/Core/Content/Media/Upload/MediaUploadService.php:292-300
private function getContentSizeFromValidExternalUrl(string $url): int
{
$this->validateExternalUrl($url);
$headers = $this->httpClient->request('HEAD', $url)->getHeaders();
if (!\array_key_exists('content-length', $headers)) {
throw MediaException::fileNotFound($url);
}
return (int) $headers['content-length'][0];
}
Protected path (upload_by_url):
In contrast, uploadFromURL uses FileFetcher::fetchFromURL() which calls FileUrlValidator::isValid():
// src/Core/Content/Media/File/FileFetcher.php:64
if ($this->enableUrlValidation && !$this->fileUrlValidator->isValid($url)) {
throw MediaException::illegalUrl($url);
}
FileUrlValidator::isValid() resolves the hostname via gethostbyname() and validates the IP against private and reserved ranges using filter_var() with FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE. This protection is entirely absent from the linkURL flow.
Impact
An authenticated admin user can:
- Probe cloud metadata services — HEAD requests to
169.254.169.254reveal whether cloud metadata endpoints exist and leak content-length values - Scan internal networks — Differentiate open/closed/filtered ports on internal hosts (10.x, 172.16.x, 192.168.x) based on response timing and error types
- Leak internal service information — The
fileSizefield stored in the database reflects thecontent-lengthheader from internal services - Redirect-based escalation — Symfony HttpClient follows redirects by default (max_redirects=20), allowing an attacker-controlled external server to redirect the HEAD request to arbitrary internal destinations
Impact is limited to information disclosure via HEAD requests. The admin authentication requirement (PR:H) reduces exploitability, but in multi-tenant or compromised-credential scenarios this allows network reconnaissance from the server's perspective.
Recommended Fix
Apply FileUrlValidator to the linkURL flow, consistent with the uploadFromURL flow. In MediaUploadService:
// src/Core/Content/Media/Upload/MediaUploadService.php
// Add constructor dependency:
private readonly FileUrlValidatorInterface $fileUrlValidator;
// In getContentSizeFromValidExternalUrl(), add IP validation:
private function getContentSizeFromValidExternalUrl(string $url): int
{
$this->validateExternalUrl($url);
if (!$this->fileUrlValidator->isValid($url)) {
throw MediaException::illegalUrl($url);
}
$headers = $this->httpClient->request('HEAD', $url)->getHeaders();
if (!\array_key_exists('content-length', $headers)) {
throw MediaException::fileNotFound($url);
}
return (int) $headers['content-length'][0];
}
Additionally, consider setting max_redirects: 0 on the HttpClient request to prevent redirect-based SSRF bypasses.
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 🐘Packagist | shopware/core | ≥ 6.7.0.0&&< 6.7.10.1 | 6.7.10.1composer require shopware/core:^6.7.10.1 |
| 🐘Packagist | shopware/platform | ≥ 6.7.0.0&&< 6.7.10.1 | 6.7.10.1composer require shopware/platform:^6.7.10.1 |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for shopware/core, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update shopware/core to 6.7.10.1 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-48013 is resolved across your whole dependency graph.
Workarounds
Restrict outbound requests from the affected component to an allowlist of hosts, block access to link-local and internal address ranges at the network layer, and require authentication on internal services so a forged request cannot reach them unauthenticated.
Frequently Asked Questions
Is CVE-2026-48013 in your dependencies?
Find it across Packagist, including transitive dependencies.