An unlocked filing cabinet in the basement of a CMS nobody upgraded since 2017
CVE-2026-13533 is a direct-request / forced-browsing flaw in agentejo Cockpit CMS versions 0.12.0 through 0.12.2. The htaccess handler fails to deny access to /config/config.yaml, so an unauthenticated remote attacker can simply GET the URL and walk away with whatever the operator put in Spyc::YAMLLoad config — typically database DSN, SMTP creds, API tokens, and the application secret. There is no memory corruption, no code execution primitive in the bug itself; it is a config-disclosure issue with CWE-425 / CWE-552 as the underlying weaknesses.
The vendor-assigned MEDIUM (5.3, AV:N/AC:L/PR:N/UI:N/C:L/I:N/A:N) is honest. Confidentiality is *Low* because what leaks is bounded to the YAML file, but in practice that file is the keys to the kingdom for a small Cockpit install. The score is held down by two real factors: Cockpit's installed base is tiny, and the 0.12.x line was superseded years ago by the 2.x rewrite — anyone still running 0.12.2 in 2026 has bigger hygiene problems than this CVE.
4 steps from start to impact.
Discover an exposed Cockpit 0.12.x instance
/cockpit/ path, or the X-Powered-By style banners. Shodan/FOFA queries for http.favicon.hash and html:"Cockpit" return the candidate set. Version is confirmed by reading static asset paths.- Cockpit 0.12.0–0.12.2 reachable on TCP/80 or 443
- no upstream WAF blocking
/config/path
- Cockpit installed base is small (low thousands worldwide per Shodan)
- 0.12.x is an EOL branch; most live deployments are on 2.x
- many self-hosters put it behind nginx auth or a VPN
cockpit-cms-detect, and basic version-banner fingerprinting all flag the installForced-browse the config file
GET /config/config.yaml (or the equivalent under the Cockpit install root). Because the shipped .htaccess does not deny the path, the web server returns the YAML body. No auth, no token, no header tricks required. The public PoC is a single curl one-liner from nov_ on GitHub gist.- Apache with
AllowOverridehonoring the broken.htaccess, or nginx without an explicit deny rule for/config/
- nginx deployments commonly add a global
location ~ /\. { deny all; }or a/config/deny block - hardened images strip the file or relocate it outside the docroot
- any reverse proxy stripping non-app paths blocks it
config.yaml in URI path; access-log SIEM rule for 200-response on *.ya?mlHarvest secrets from the YAML body
database, sec-key, mailer, and any custom plugin keys. The sec-key value is used by Cockpit for signing — disclosure typically enables session forgery against the admin UI. Database DSN may be a local socket (useless externally) or a remote MySQL/MongoDB with public binding.- YAML actually contains credentials and not just
env(...)references
- modern Cockpit installs use
.envindirection so config.yaml holds only key names - DB is often bound to localhost
Pivot from disclosure to admin or RCE
sec-key and DB DSN, attacker either forges an admin session cookie or connects directly to the database to drop a privileged user. From an authenticated admin context, well-known Cockpit RCE chains (Metasploit multi/http/cockpit_cms_rce, the older NoSQLi-to-RCE) finish the job to webshell.- sec-key usable for the running version's signing scheme
- DB reachable from attacker network, or admin login internet-exposed
- DB rarely public
- admin endpoint frequently IP-restricted or behind SSO
- this step requires a *second* CVE class (auth bypass / RCE) — out of scope of 13533
/auth/loginThe supporting signals.
| In-the-wild exploitation | None observed. No KEV listing, no honeypot hits attributable to this CVE as of 2026-06-29 |
|---|---|
| Public PoC | Yes — single curl one-liner gist by nov_ referenced in the VulDB advisory; trivially reproducible |
| EPSS | Not yet scored (disclosed today); expect <0.5% / <50th percentile based on prior Cockpit CVE behavior |
| KEV status | Not listed |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N — network-reachable, unauthenticated, low confidentiality only |
| Affected versions | Cockpit CMS 0.12.0, 0.12.1, 0.12.2 (the abandoned 0.x branch) |
| Fixed version | No vendor patch. Vendor unresponsive per VulDB. Migrate to current Cockpit 2.x line (separate codebase) or remove |
| Exposure data | Shodan returns ~1.5–3k Cockpit instances globally across all versions; 0.12.x subset is hundreds, not thousands |
| Disclosure | 2026-06-29 by nov_ via VulDB CNA (entry 374541); GHSA-q4hh-wg87-823q |
| CWE | CWE-425 Direct Request (Forced Browsing) / CWE-552 Files or Directories Accessible |
noisgate verdict.
Verdict held at MEDIUM because the bug is a pure confidentiality disclosure on an end-of-life 0.x branch of a low-deployment headless CMS — the single most decisive factor is the *narrow affected version range on an abandoned product line*. There is no canonical high-value-role deployment of Cockpit 0.12.x (no enterprise runs IdP / PKI / hypervisor / backup on it), so the role-multiplier floor does not lift this above HIGH.
Why this verdict
- Friction — abandoned branch: Cockpit 0.12.x predates the 2.x rewrite by years; anyone still on it is statistically rare and often air-gapped behind reverse proxies.
- Friction — no second-order primitive in the CVE itself: the bug leaks a config file, not code execution. Escalation to RCE requires chaining a *separate* unpatched bug or a misconfigured DB.
- Friction — modern deployments dereference secrets via env: even when config.yaml is read, well-run installs store only
env(KEY)references, neutering the confidentiality impact. - Role multiplier: Cockpit is a small headless CMS for content management — the realistic deployment-role spectrum is (a) marketing microsite, (b) small-org blog, (c) developer sandbox. None of these are identity, PKI, hypervisor, or supply-chain roles. The role-multiplier floor stays at MEDIUM.
- No exploit-population pressure: no KEV, no observed campaigns, no EPSS signal — a baseline MEDIUM is appropriate against an abandoned product.
Why not higher?
Not HIGH because the vendor CVSS is honest about scope: only confidentiality is touched, and only of a single config file. There is no integrity or availability impact in the bug itself, and the affected-population evidence (small Cockpit footprint, abandoned 0.12.x branch) does not support an upgrade.
Why not lower?
Not LOW because the exploit is unauthenticated, network-reachable, and a one-line curl — that is genuinely dangerous when the config.yaml does contain secrets, which it usually did in the 0.12.x era before env-indirection became common.
What to do — in priority order.
- Block
/config/and*.ya?mlat the reverse proxy — Add an explicitlocation ~* /config/ { deny all; }(nginx) or<LocationMatch>Require all denied (Apache) in front of every Cockpit instance. This neutralizes the exploit entirely with no code change. Deploy as soon as possible — there is no noisgate mitigation SLA for MEDIUM, but this is a 30-minute change, do it this sprint. - Rotate every secret currently in config.yaml — Assume disclosure has already happened on any internet-facing 0.12.x instance: rotate
sec-key, DB password, SMTP creds, and any API tokens listed. Move them to.envand reference viaenv(...)in the YAML. - Migrate off the 0.12.x branch — Cockpit 2.x is a separate codebase; plan a content export/import within the noisgate remediation SLA of 365 days for MEDIUM. If migration is infeasible, decommission the install.
- Gate the admin panel behind SSO or IP allowlist — Reduces the post-disclosure pivot path (step 4 in the chain). Even if secrets leak, the attacker cannot reach
/auth/loginto forge a session.
- WAF generic rule sets — most OWASP CRS profiles do not block
GET /config/config.yamlbecause the URI is structurally benign; you need an explicit path deny. - Patching to the latest 0.12.x point release — there isn't one. The vendor never responded to disclosure; only migration or proxy-block fixes it.
- Disabling directory listing — irrelevant; this is a direct file request, not an index traversal.
- File permissions on config.yaml — the web server *needs* to read it; chmod does not help.
Crowdsourced verification payload.
Run from an auditor workstation (not the target) against each suspected Cockpit host. Requires curl only, no privileges. Invoke as: ./check_cve_2026_13533.sh https://cms.example.com
#!/usr/bin/env bash
# noisgate verification — CVE-2026-13533
# Detects exposed /config/config.yaml on agentejo Cockpit CMS 0.12.x
set -u
TARGET="${1:-}"
if [[ -z "$TARGET" ]]; then
echo "usage: $0 <https://host[:port][/path-to-cockpit]>" >&2
exit 2
fi
# Strip trailing slash
TARGET="${TARGET%/}"
UA='noisgate-verifier/1.0'
PATHS=("/config/config.yaml" "/cockpit/config/config.yaml")
found_vuln=0
found_cockpit=0
# 1. Fingerprint Cockpit presence
ROOT=$(curl -sk -A "$UA" --max-time 10 "$TARGET/" || true)
if grep -qiE 'cockpit|agentejo' <<<"$ROOT"; then
found_cockpit=1
fi
# 2. Probe each candidate config path
for p in "${PATHS[@]}"; do
URL="$TARGET$p"
CODE=$(curl -sk -A "$UA" --max-time 10 -o /tmp/ng_cfg.$$ -w '%{http_code}' "$URL" || echo '000')
if [[ "$CODE" == "200" ]] && grep -qE '^(database|sec-key|mailer|app):' /tmp/ng_cfg.$$; then
echo "VULNERABLE: $URL returned 200 with YAML config keys"
found_vuln=1
fi
rm -f /tmp/ng_cfg.$$
done
if [[ $found_vuln -eq 1 ]]; then
echo "RESULT: VULNERABLE"
exit 1
elif [[ $found_cockpit -eq 1 ]]; then
echo "RESULT: PATCHED (Cockpit detected, config not exposed)"
exit 0
else
echo "RESULT: UNKNOWN (no Cockpit fingerprint observed)"
exit 3
fi
If you remember one thing.
deny /config/ rule and rotate the secrets in that file today; the noisgate mitigation SLA for MEDIUM has no hard deadline, but this fix is a 30-minute config change with no downtime, so just do it. Plan migration to the Cockpit 2.x line (or decommission) inside the noisgate remediation SLA of 365 days. Do not let this CVE jump the queue past any KEV-listed or HIGH-verdict work — it is real, but it is not what compromises your network this quarter.Sources
- Vulnerability-Lookup CVE-2026-13533
- GitHub Security Advisory GHSA-q4hh-wg87-823q
- OpenCVE — agentejo Cockpit CVE listing
- CVEDetails — Agentejo Cockpit
- Metasploit — Cockpit CMS NoSQLi to RCE (chained context)
- CWE-425 — Direct Request (Forced Browsing)
- CWE-552 — Files or Directories Accessible to External Parties
- Cockpit project on GitHub (agentejo)
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.