Like printing a hotel room key on the outside of the envelope
In Optimizely Configured Commerce versions before 5.2.2408 on both the STS and LTS branches, some resource requests placed the authenticated session token in the URL query string instead of keeping it out of the address bar. That means the token can bleed into browser history, screenshots, proxy logs, referrer headers, shared-device traces, and any monitoring stack that records full URLs. If an attacker gets that token before it expires, they can replay the victim's authenticated session.
The raw AV:N/PR:N/UI:N scoring is too generous for what defenders actually face. Attackers do not get a session out of thin air; they need a second failure first: access to logs, a leaked URL, a shared workstation, a malicious browser extension, or some other path to the token. Optimizely's own advisory labeled the issue Medium 5.9, and that tracks reality better than the higher 7.5 enrichment score because the real-world chain has meaningful friction.
4 steps from start to impact.
Find a live storefront using URL-based session transport
curl, or Burp Suite, the attacker identifies a Configured Commerce site on a vulnerable build and confirms that authenticated requests place the session token in the query string. The bug is passive until a legitimate user logs in and generates one of those URLs.- The target is running Optimizely Configured Commerce before
5.2.2408 - The storefront is reachable to the attacker or the attacker already has internal visibility
- A legitimate user authenticates and triggers affected requests
- This is a niche enterprise B2B commerce platform, not a mass-market perimeter appliance
- Not every request path may expose the token
- Many deployments sit behind customer-specific domains and Cloudflare-managed front ends
Harvest the token from somewhere else
Burp Suite, proxy log access, SIEM queries, browser history inspection, or a copied URL from chat/email/tickets. The attacker needs the full query string containing a still-valid token generated by a real user session.- Access to web logs, reverse proxy logs, APM traces, browser history, screenshots, support tickets, or copied links
- The session token remains valid long enough to replay
- Requires a secondary leak path; no leak path means no exploit
- Short session lifetimes, logout, or server-side invalidation reduce the window
- Least-privilege log access and query-string redaction kill this step outright
Replay the victim session
curl/Postman, impersonating the victim without needing their password. Impact depends on the victim account: buyer, approver, customer service, or admin-level access if privileged sessions are exposed the same way.- A valid stolen token
- The token is accepted from the replaying client
- No additional re-authentication gates block sensitive actions
- Some environments bind sessions to additional context or invalidate them on logout
- Modern anomaly detection, geo-velocity, or session hygiene may catch reuse
- Blast radius is usually the victim account, not platform-wide code execution
Use the hijacked account for business impact
- The victim account has access to sensitive commercial data or elevated workflows
- Confidentiality impact varies heavily by role and tenant configuration
- No evidence in reviewed sources of widespread weaponization or automation
- The impact is meaningful but usually contained to the hijacked session's privileges
The supporting signals.
| In-the-wild status | No reviewed authoritative source showed active exploitation. Not KEV-listed in the CISA catalog page reviewed. |
|---|---|
| Proof-of-concept availability | I found no credible public PoC or GitHub exploit repo for this CVE in primary-source review. That does not make it harmless; it just means attackers still need their own token-harvest path. |
| EPSS | Provided intel lists EPSS at 0.00383 (0.383%), which is low. I did not find an authoritative percentile in reviewed sources, so treat this as low-likelihood threat telemetry rather than a percentile-ranked signal. |
| KEV status | No. Reviewed against the CISA Known Exploited Vulnerabilities Catalog URL; no indication this CVE is listed. |
| CVSS vector reality check | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N assumes a clean remote path to confidentiality loss. In practice, the missing piece is token capture; that prerequisite is where the real-world score should come down. |
| Affected versions | All Optimizely Configured Commerce versions before 5.2.2408 on both STS and LTS branches. |
| Fixed versions | Upgrade to 5.2.2408 STS or 5.2.2408 LTS. This is a proprietary platform; there are no distro backports to track. |
| Exposure and scanning | No public GreyNoise/Censys/Shodan telemetry was located in reviewed primary sources. Inference: exposure is customer-domain specific rather than a single vendor-owned service, and many deployments appear to sit behind Optimizely-managed DNS/Cloudflare patterns. |
| Date clarity | There is a date mismatch across sources: the vendor advisory says December 13, 2024 as published, NVD shows January 3, 2025 publication, and your prompt listed 2025-01-04. Treat this as a late-2024 disclosure that was cataloged in early January 2025. |
| Severity mismatch | There is also a severity mismatch: Optimizely's advisory states Medium 5.9, while NVD displays a CISA-ADP enriched 7.5 High vector. For prioritization, the vendor's Medium label is closer to reality because exploitation depends on a secondary token leak. |
noisgate verdict.
The decisive factor is that exploitation requires a separate token-exposure event before the attacker can do anything. This is not a true unauthenticated internet-to-compromise path; it is a session replay issue whose reachable population shrinks hard once you ask how the attacker actually gets the URL token.
Why this verdict
- Start from 7.5, then subtract for the missing first mile: the attacker still needs to steal a live session token from logs, history, referrers, or a shared device before replay is possible.
- This is often post-initial-access or adjacent visibility: needing internal log access, browser artifacts, support-ticket leakage, or shared-endpoint access implies another compromise stage or at least another control failure.
- Blast radius is usually account-scoped: the impact can be serious for a privileged buyer/admin, but it is still bounded by the victim session rather than giving server-side code execution or tenant-wide takeover by default.
Why not higher?
There is no evidence in reviewed sources of KEV listing, mass scanning, or public weaponization. More importantly, the CVSS view hides the real prerequisite: a valid token must first leak somewhere an attacker can reach, and that materially narrows both exploitability and exposed population.
Why not lower?
This is still a genuine authentication-material exposure bug, not cosmetic hygiene. On commerce platforms, a hijacked session can expose pricing, order data, customer account details, approvals, and potentially privileged business workflows if the stolen token belongs to the wrong user.
What to do — in priority order.
- Redact query strings everywhere — Strip or hash URL query parameters in reverse proxies, CDNs, WAF logs, APM traces, browser telemetry, and SIEM ingestion so the token cannot be harvested downstream. For a MEDIUM verdict there is no noisgate mitigation SLA; apply this in the next normal change window while you move toward remediation.
- Expire and rotate sessions aggressively — Shorten session lifetime, invalidate tokens on logout, and force re-authentication for high-risk workflows so any leaked token dies faster. Again, there is no mitigation SLA for MEDIUM; use standard change control rather than emergency weekend work.
- Tighten access to logs and support systems — Limit who can read raw request URLs in web logs, help-desk tickets, chat transcripts, and analytics tools because those systems become the easiest theft point. Do this during normal operational cleanup if those platforms currently retain full URLs.
- Monitor for session replay anomalies — Alert on same-session use across unusual ASN changes, user-agent drift, impossible travel, or privileged actions immediately after a session appears in logging systems. This is a detective backstop, not a fix, but it meaningfully reduces dwell time until the patch is deployed.
- A generic WAF signature does not solve this because the vulnerable behavior is the application's own legitimate use of a query-string token, not an obviously malicious payload.
- TLS alone does not help once the URL lands in logs, browser history, tickets, or screenshots after decryption at the edge.
- MFA protects login, but a replayed live session token can bypass the need to log in again.
Crowdsourced verification payload.
Run this on a developer workstation, CI runner, or server that has access to the Configured Commerce codebase or deployment artifact. Invoke it as python3 verify_cve_2025_22387.py /path/to/repo-or-VersionInfo.yaml; it needs read-only access only and checks the declared Configured Commerce version against the fixed 5.2.2408 floor.
#!/usr/bin/env python3
# verify_cve_2025_22387.py
# Checks whether an Optimizely Configured Commerce deployment is below 5.2.2408.
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN, 3=USAGE
import os
import re
import sys
FIX_MAJOR = 5
FIX_MINOR = 2
FIX_RELEASE = 2408
def norm_tuple(version_str):
m = re.search(r'(\d+)\.(\d+)\.(\d+)', version_str)
if not m:
return None
return tuple(int(x) for x in m.groups())
def compare_version(t):
fixed = (FIX_MAJOR, FIX_MINOR, FIX_RELEASE)
if t < fixed:
return 'VULNERABLE'
return 'PATCHED'
def find_versioninfo(start_path):
if os.path.isfile(start_path):
return start_path
candidates = []
for root, dirs, files in os.walk(start_path):
if 'VersionInfo.yaml' in files:
candidates.append(os.path.join(root, 'VersionInfo.yaml'))
# keep walk bounded for safety on giant repos
if root.count(os.sep) - start_path.count(os.sep) > 6:
dirs[:] = []
return candidates[0] if candidates else None
def extract_version(path):
with open(path, 'r', encoding='utf-8', errors='ignore') as f:
data = f.read()
# Try common patterns first.
patterns = [
r'(?im)^\s*version\s*:\s*["\']?([^"\'\n]+)',
r'(?im)^\s*baseVersion\s*:\s*["\']?([^"\'\n]+)',
r'(?im)^\s*releaseVersion\s*:\s*["\']?([^"\'\n]+)',
r'(?im)^\s*commerceVersion\s*:\s*["\']?([^"\'\n]+)',
]
for pat in patterns:
m = re.search(pat, data)
if m:
return m.group(1).strip()
# Fallback: first 5.2.x style version anywhere in file.
m = re.search(r'(\d+\.\d+\.\d+(?:\.\d+)?(?:\+(?:sts|lts))?)', data, re.IGNORECASE)
if m:
return m.group(1).strip()
return None
def main():
if len(sys.argv) != 2:
print('UNKNOWN - usage: python3 verify_cve_2025_22387.py /path/to/repo-or-VersionInfo.yaml')
sys.exit(3)
target = sys.argv[1]
if not os.path.exists(target):
print(f'UNKNOWN - path not found: {target}')
sys.exit(2)
vf = find_versioninfo(target)
if not vf:
print('UNKNOWN - could not locate VersionInfo.yaml under the supplied path')
sys.exit(2)
raw_version = extract_version(vf)
if not raw_version:
print(f'UNKNOWN - could not parse version from {vf}')
sys.exit(2)
parsed = norm_tuple(raw_version)
if not parsed:
print(f'UNKNOWN - unsupported version format: {raw_version}')
sys.exit(2)
result = compare_version(parsed)
print(f'{result} - detected version {raw_version} from {vf}; fixed threshold is 5.2.2408')
if result == 'VULNERABLE':
sys.exit(1)
sys.exit(0)
if __name__ == '__main__':
main()
If you remember one thing.
5.2.2408 or later within the noisgate remediation SLA of ≤365 days. If you know a storefront is internet-facing and your logs preserve full URLs, move it ahead of the generic medium backlog even though this does not justify emergency patching.Sources
- Optimizely Configured Commerce Security Advisory COM-2024-06
- NVD CVE-2025-22387
- Optimizely Configured Commerce Security Announcements index
- Optimizely Long-Term Support and Short-Term Support branches
- Optimizely Configured Commerce release schedule
- Optimizely Go-live with Configured Commerce
- FIRST EPSS overview
- CISA Known Exploited Vulnerabilities Catalog
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.