Like tricking a building manager into wheeling a sealed crate into the server room without opening it
CVE-2026-8140 affects Concrete CMS 9.5.0 and earlier. The /dashboard/extend/install/download/<remoteId> route performs a state-changing package download from the Concrete marketplace but, prior to 9.5.1, did not validate a CSRF token first. If an authenticated user with canInstallPackages() rights is lured to a crafted page, their browser can be used to trigger a package download into DIR_PACKAGES.
The vendor's MEDIUM 6.5 is still a little generous in enterprise reality. The missing token is real, but the exploit path is heavily narrowed by admin-session dependency, user interaction, marketplace connectivity, and the fact that this CVE by itself downloads code but does not install or execute it. That makes it more like *unauthorized staging* than direct takeover.
4 steps from start to impact.
Land a privileged browser session
canInstallPackages(). In practice that means an administrator or similarly privileged operator actively using the dashboard. Weaponized tool: a phishing link, ad, or embedded HTML element that forces a cross-site navigation.- Victim is logged into Concrete CMS
- Victim account has
canInstallPackages()permission - Victim visits attacker-controlled content
- This is not unauthenticated remote exploitation
- Many enterprises restrict CMS admin access to a small staff subset
- Security awareness, URL filtering, browser isolation, or SSO reauth can break the lure
Abuse the state-changing GET
/dashboard/extend/install/download/<remoteId> through a browser primitive such as an img, iframe, or top-level redirect. Because the route lacked CSRF enforcement before 9.5.1, the browser's authenticated cookies are enough to submit the request. Weaponized tool: trivial HTML/JS, no exploit framework required.- Target runs Concrete CMS 9.5.0 or earlier
- Session cookies are sent to the application
- The route is reachable from the victim browser
- Requires user interaction (
UI:R) - Browser SameSite behavior and custom hardening can reduce reliability
- Admin may not remain logged in long enough for the lure to succeed
/dashboard/extend/install/download/ coming from normal administrator workstations. Most EDR tools will not treat this as suspicious unless chained with follow-on behavior.Force a marketplace package download
<remoteId> and writes it into DIR_PACKAGES. That is a server-side state change and a code staging event, but not automatic execution. Weaponized tool: the application's own marketplace downloader.- Concrete marketplace connectivity is configured
- Chosen
remoteIdresolves to a downloadable package
- If the site is not connected to the marketplace, the path dies here
- Package availability and licensing constraints may limit what can be fetched
- Download alone does not run installer logic
DIR_PACKAGES is the best coverage. Marketplace download logs and outbound HTTP logs may also show the fetch.Attempt follow-on abuse
- Downloaded package is later installed or otherwise acted on
- Attacker has an additional path to code execution or persistence
- No auto-install or auto-execution in this CVE alone
- Modern change control and package review often stop the chain
- Any second-stage dependency compounds failure probability
packages/ followed by administrator package-management actions. If only the download occurs, many environments will never see a functional payload.The supporting signals.
| In-the-wild status | No evidence of active exploitation found in the sources reviewed, and CISA KEV does not list CVE-2026-8140. |
|---|---|
| Proof-of-concept availability | No authoritative public PoC repo surfaced in NVD, Concrete CMS release notes, or the reporter reference. This is a low-complexity browser CSRF, so reproducing it is straightforward even without a packaged exploit. |
| EPSS | User-supplied EPSS is 0.00018, which is extremely low. *Inference:* that places it near the bottom of the exploitation-likelihood distribution. |
| KEV status | Not KEV-listed as of the CISA catalog source reviewed. |
| CVSS vector reality check | CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N captures the browser-driven nature, but it overstates enterprise urgency because the chain really depends on authenticated admin context + marketplace connectivity + no auto-execution. |
| Affected versions | Concrete CMS 9.5.0 and earlier. |
| Fixed version | Fixed in Concrete CMS 9.5.1. I found no vendor-published distro backport guidance in the sources reviewed. |
| Exposure reality | This is not a classic internet-edge pre-auth bug. The exposed surface is an admin dashboard workflow for extension downloads, and the vulnerable action only matters when the site is connected to the Concrete marketplace. |
| Disclosure | Published 2026-05-21 via NVD record; vendor says the issue was fixed in 9.5.1 and credits maru1009 for reporting. |
noisgate verdict.
The decisive downward driver is that this bug requires an authenticated package-install-capable admin session and only stages a package download. That's post-click, narrow-population abuse with no direct code execution, so it does not deserve the urgency normally implied by a network-exploitable CMS flaw.
Why this verdict
- Admin-session required: the attacker position is not unauthenticated remote; it requires a live browser session for a user who can install packages, which sharply narrows reachable victims.
- Marketplace-connected only: the prerequisite implies a specific deployment posture. Environments not linked to the Concrete marketplace are simply not exploitable on this path.
- Download is not execution: the endpoint writes a package to
DIR_PACKAGES, but this CVE alone does not install or run it. That missing final step is the biggest reason to push the score down from the vendor baseline.
Why not higher?
If this route installed packages or executed package code automatically, the rating would jump fast. But on the facts available, it is a CSRF-triggered staging action with multiple prerequisites and a second-stage dependency for serious impact.
Why not lower?
This still causes a real server-side state change and places attacker-selected package content on disk. In shops with weak admin hygiene or adjacent package-management flaws, that staging action can become meaningful, so this is not pure noise.
What to do — in priority order.
- Constrain package-install privileges — Reduce the set of accounts that pass
canInstallPackages()to the smallest possible group. For a LOW verdict there is no mitigation SLA; treat this as backlog hygiene, but do it during the next role-review cycle because shrinking the privileged browser population directly kills the attack path. - Disable marketplace connectivity where unused — If the site does not need in-dashboard extension downloads, disconnect it from the Concrete marketplace or move extension handling to a controlled build process. For LOW, there is no mitigation SLA; fold this into routine hardening because it removes a core prerequisite of the bug.
- Monitor
DIR_PACKAGESfor drift — Add file integrity monitoring or SIEM alerts for unexpected new package directories and marketplace download events. For LOW, there is no mitigation SLA; treat as normal control improvement, especially on shared CMS estates with multiple administrators. - Harden admin browsing — Use separate admin browsers, reauthentication for privileged actions, and web filtering/browser isolation for CMS operators. For LOW, there is no mitigation SLA; implement through standard privileged-access hardening because it reduces CSRF success in general, not just for this CVE.
- A perimeter WAF is not a reliable fix here, because the malicious request is a legitimate-looking authenticated admin GET to a first-party dashboard route.
- Generic internet exposure reduction does not fully solve it if admins can still reach the dashboard and browse the web from the same session.
- Relying on endpoint AV alone misses the core issue, because the vulnerable action is performed by the CMS itself using valid session cookies.
Crowdsourced verification payload.
Run this on the target Concrete CMS host from a shell on the web server, pointing it at the Concrete webroot. Example: bash verify_cve_2026_8140.sh /var/www/html. It needs only read access to the webroot and the ability to invoke php; root is not required.
#!/usr/bin/env bash
# verify_cve_2026_8140.sh
# Checks whether a local Concrete CMS instance is vulnerable to CVE-2026-8140
# Usage: bash verify_cve_2026_8140.sh /path/to/concrete-webroot
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN, 3=USAGE
set -u
WEBROOT="${1:-}"
if [[ -z "$WEBROOT" ]]; then
echo "UNKNOWN - usage: $0 /path/to/concrete-webroot"
exit 3
fi
if [[ ! -d "$WEBROOT" ]]; then
echo "UNKNOWN - webroot not found: $WEBROOT"
exit 2
fi
version=""
# Preferred path: use Concrete CLI if present.
if [[ -x "$WEBROOT/concrete/bin/concrete" ]]; then
info_out="$((cd "$WEBROOT" && php concrete/bin/concrete c5:info) 2>/dev/null)"
version="$(printf '%s\n' "$info_out" | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+' | head -n1)"
fi
# Fallback: parse composer.lock for concrete package version.
if [[ -z "$version" && -f "$WEBROOT/composer.lock" ]]; then
version="$(grep -A4 -E '"name":\s*"(concrete5/core|concretecms/core)"' "$WEBROOT/composer.lock" 2>/dev/null | grep -Eo '"version":\s*"v?[0-9]+\.[0-9]+\.[0-9]+' | head -n1 | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+')"
fi
# Very loose fallback: search common PHP files for a semantic version string near 'concrete'.
if [[ -z "$version" ]]; then
version="$(grep -RIEo 'concrete[^\n]{0,80}[0-9]+\.[0-9]+\.[0-9]+' "$WEBROOT" 2>/dev/null | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+' | head -n1)"
fi
if [[ -z "$version" ]]; then
echo "UNKNOWN - unable to determine Concrete CMS version"
exit 2
fi
verlte() {
# returns success if $1 <= $2
[[ "$1" == "$2" ]] && return 0
local first
first="$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -n1)"
[[ "$first" == "$1" ]]
}
if verlte "$version" "9.5.0"; then
echo "VULNERABLE - Concrete CMS version $version is <= 9.5.0"
exit 1
else
echo "PATCHED - Concrete CMS version $version is > 9.5.0"
exit 0
fi
If you remember one thing.
Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.