A shop's back office ledger left visible to anyone who guesses the room number
Drupal Commerce Core is the e-commerce engine for Drupal sites, handling products, carts, orders, and customer records. CVE-2026-118539 is a missing authorization flaw (CWE-862) that enables forced browsing: certain Commerce routes rely on URL obscurity or incomplete access checks, so an unauthenticated visitor can directly request protected order/administration pages and read data they should not see. The vulnerable range is Commerce Core 0.0.0 through 2.41 and 3.0.0 through 3.3.13; fixed versions are 2.42 and 3.3.14.
There is no vendor CVSS baseline for this record, so this assessment establishes severity from first principles. The impact is primarily confidentiality loss of customer PII and order metadata, not code execution or payment-token theft. A HIGH severity is appropriate because Drupal Commerce stores are public by design, the attack is network-reachable with no authentication, and sequential order IDs make bulk browsing practical.
4 steps from start to impact.
Identify a Drupal Commerce site
/admin/modules, /modules/contrib/commerce/commerce.info.yml, or a normal storefront response that reveals Drupal headers. Confirm Commerce Core is installed and, if version disclosure is present, map it to the vulnerable ranges. Tools: curl, wappalyzer, whatweb.- Site is internet-facing
- Commerce Core module is enabled or version is disclosed
- Version may be hidden by server config or Composer installs
- Not all Drupal sites run Commerce Core
Request an unauthorized Commerce route directly
curl.- Vulnerable version installed
- Affected route is reachable from attacker position
- Site may place admin routes behind an IP allowlist or reverse-proxy ACL
- Some routes may require at least a low-privilege Drupal session if the missing check is only enforced downstream
Enumerate order and customer identifiers
requests loop or ffuf with numeric wordlists. Because Commerce order IDs are often sequential, the forced-browsing gap returns customer-facing data instead of 403 for unauthorized IDs. Tools: Python requests, ffuf, Burp Intruder.- Predictable or sequential identifiers
- Response differentiates authorized from unauthorized records
- If order IDs are UUIDs or scoped by randomness, bulk enumeration slows down
- Rate limiting or bot detection can stall automated iteration
Exfiltrate customer PII and order history
curl + custom parser, or gau/httpx for crawling affected routes.- Commerce installation stores PII in page output
- No field-level redaction on affected route
- Payment card data is typically tokenized by payment gateways and not shown
- Some deployments store minimal customer data
/admin/commerce/* and known order paths from public access and allow only trusted admin IPs/VPN within the noisgate mitigation SLA (≤30 days for HIGH). This breaks anonymous network reach.- CAPTCHA or login throttling: does not stop direct URL access to missing-authorization routes.
- Generic WAF signature rules: forced browsing looks like legitimate HTTP GETs; a WAF won't detect missing access control unless route-specific ACLs are configured.
- Drupal Security Kit / headers: controls browser-side behavior, not server-side access checks.
The supporting signals.
| CVE ID | CVE-2026-118539 |
|---|---|
| Product | Drupal Commerce Core |
| CWE | CWE-862 Missing Authorization |
| Affected versions | 0.0.0–2.41, 3.0.0–3.3.13 |
| Fixed versions | 2.42, 3.3.14 |
| Disclosed | 2026-10-30 |
| KEV | No; not in CISA KEV as of 2026-10-31 |
| In-the-wild exploitation | None reported |
| PoC availability | None found on pocindex.io or GitHub |
| EPSS | Not yet scored / no data |
| CVSS v3.1 (assessed) | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N → 7.5 High |
| Reporting org | Not disclosed in record |
Sources.
Why this verdict
- No vendor CVSS: This is a first-assessed severity, not an upgrade or downgrade. The official record lacks a vendor score.
- Friction audit: Anonymous network access is sufficient; no prior compromise is required. Public e-commerce exposure is inherent, so the base attack path is broadly reachable.
- Role multiplier: Drupal Commerce stores are internet-facing and hold customer PII/order data. Successful forced browsing can mass-exfiltrate regulated PII and fuel fraud; this floors the verdict at HIGH.
- No KEV/exploit: No in-the-wild exploitation or public PoC lowers immediate urgency but does not reduce data exposure on vulnerable stores.
Why not higher?
No evidence of administrator write access, payment-token theft, remote code execution, or store defacement. The weakness is missing authorization on browsing routes, so availability and integrity are unaffected. No active exploitation or KEV listing further argues against CRITICAL.
Why not lower?
The vulnerable component is network-facing by design and stores personal data. A direct forced-browsing request with no authentication can reveal customer PII and order history at scale, making MEDIUM too low. Sequential order IDs make enumeration straightforward.
Crowdsourced verification payload.
Run on the Drupal web server or a host with the webroot mounted, as a user with read access to the codebase (e.g., root or www-data). Invoke: bash check_cve_2026_118539.sh /var/www/html where the argument is your Drupal docroot.
#!/usr/bin/env bash
# CVE-2026-118539 Drupal Commerce Core version checker
set -uo pipefail
docroot="${1:-/var/www/html}"
printf 'Checking %s\n' "$docroot"
ver_lte() {
local a="$1" b="$2"
local latest
latest="$(printf '%s\n%s\n' "$a" "$b" | sort -V | tail -n1)"
[[ "$latest" == "$b" ]]
}
ver_lt() {
if [[ "$1" == "$2" ]]; then return 1; fi
ver_lte "$1" "$2"
}
in_range() {
local v="$1"
v="${v#8.x-}"
v="${v#7.x-}"
v="${v#v}"
case "$v" in
*.*.*) ;;
*.*) v="$v.0" ;;
*) v="$v.0.0" ;;
esac
if ver_lte "$v" "2.41.0" && ! ver_lt "$v" "0.0.0"; then return 0; fi
if ver_lte "$v" "3.3.13" && ! ver_lt "$v" "3.0.0"; then return 0; fi
return 1
}
found=0
vuln=0
while IFS= read -r -d '' file; do
found=1
ver="$(grep -m1 -E '^version[[:space:]]*:' "$file" 2>/dev/null | sed -E 's/^[^:]*:[[:space:]]*//')"
if [[ -z "$ver" ]]; then
lock="${docroot}/composer.lock"
if [[ -f "$lock" ]]; then
ver="$(php -r '$data=json_decode(file_get_contents($argv[1]), true); foreach (($data["packages"]??[]) as $p) { if (($p["name"]??"")==="drupal/commerce") { echo $p["version"]??""; break; } }' "$lock" 2>/dev/null)"
fi
fi
echo "Found: ${file#$docroot/} version=${ver:-unknown}"
if [[ -n "$ver" ]]; then
if in_range "$ver"; then
vuln=1
fi
else
vuln=2
fi
done < <(find "$docroot" -type f -path '*/commerce/commerce.info.yml' -print0 2>/dev/null)
if [[ $found -eq 0 ]]; then
echo "UNKNOWN: Commerce Core info file not found under $docroot"
exit 2
fi
if [[ $vuln -eq 1 ]]; then
echo "VULNERABLE: Drupal Commerce Core version is in affected ranges 0.0.0-2.41 or 3.0.0-3.3.13"
exit 1
elif [[ $vuln -eq 2 ]]; then
echo "UNKNOWN: unable to determine Commerce Core version"
exit 2
else
echo "PATCHED: Drupal Commerce Core version is 2.42+, 3.3.14+, or otherwise outside affected ranges"
exit 0
fi