CVE-2026-113652Medium· 5.6▾ SunlitApostropheCMS uploadfs Azure backend leaks account-level SAS token into every public attachment URL (sas: true)
▾ Sunlit zone — Low / medium · no exploitation signal
impact 30.8 · likelihood 0 · exploitation 0
Need a working PoC? Pro members can cast a request and our team develops one — it lands right here.
When uploadfs is configured with the Azure backend and sas: true (a supported configuration introduced in uploadfs 1.25.0), createContainer() builds the BlobServiceClient from a URL that embeds the full SAS query string, and Azure SDK v12 derived clients inherit that query string. As a result, getUrl() returns a base URL carrying the complete account/container SAS signature (?sv=...&sig=...), and Apostrophe's attachment.url() prepends it to every public attachment link — broadcasting a container-level SAS credential (commonly sp=rwdlac, full read/write/delete/list) to every site visitor, including anonymous ones. Anyone who can see an attachment URL can read, overwrite, delete, and list every blob in the container for the SAS lifetime. A companion functional bug (blob path appended after the query string, producing broken URLs) shows this code path was never exercised end to end. Shared-key mode (default) and non-Azure backends are not affected.
Verified at commit 5a3746aaed49761e171c2cbfe793267c959829fd (uploadfs 1.27.0 in the apostrophe monorepo).
Root cause: a credential-bearing client URL is reused as the public base URL. The chain:
new BlobServiceClient("https://<account>.blob.core.windows.net?<SAS query string>") where cluster.key is the full SAS string including siggetUrl() takes getContainerClient(...).getBlobClient('').url as baseUrl; SDK v12 derived clients inherit the SAS query string, so baseUrl already contains ?sv=...&sig=...attachment.url() = uploadfs.getUrl() + path for every rendered attachment link; attachment/index.js#L1503 — getBrowserData() also ships uploadsUrl to every logged-in editor session/container/?sv=...&sig=XXX/attachments/id-name), so these URLs are also broken — evidence the 1.25.0 code path was never testedAttack surface: every public page rendering attachment URLs (images, download links), plus the uploadsUrl delivered to editor sessions. The leak is passive and unconditional — no action required from the victim beyond serving a page. The credential further propagates through HTML source, logs, Referer headers, and CDN/proxy access logs.
Suggested remediation:
const u = new URL(blob.svc.getContainerClient(...).getBlobClient('').url); u.search = ''; (or compose accountUrl + '/' + container manually), and append the blob path to the pathname, not after the query.sr=b per-blob), and prefer generating short-lived per-blob read-only signed URLs via generateBlobSASQueryParameters instead of embedding a service-level SAS in permanent public URLs.Full PoC posted as the first comment below (poc.js + README; offline, no Azure account needed). It replicates the library's exact two steps with the declared dependency @azure/storage-blob@12:
npm install @azure/storage-blob@12 && node poc.jsnew BlobServiceClient("https://myaccount.blob.core.windows.net?sv=...&sig=FAKESIGNATURE") exactly like createContainer(), then evaluates the getUrl() logic (getContainerClient('uploads-container').getBlobClient('').url) and asserts the resulting base URL still contains the sig parameter.baseUrl: https://myaccount.blob.core.windows.net/uploads-container/?sv=2021-06-08&ss=b&srt=co&sp=rwdlac&se=2099-01-01&sig=FAKESIGNATURE
attachment URL as served to visitors: https://myaccount.blob.core.windows.net/uploads-container/?sv=2021-06-08&ss=b&srt=co&sp=rwdlac&se=2099-01-01&sig=FAKESIGNATURE/attachments/abc123-photo.jpg
The produced URL both leaks the token (sv…sig) and demonstrates the broken path placement. Cross-checking attachment/index.js confirms this URL reaches public pages unmodified.
sp=rwdlac (read/write/delete/list/ACL) — is disclosed to every site visitor including anonymous users, valid for the SAS lifetime (often years). Holders can read, overwrite, delete, and enumerate every attachment in the container; the library applies no narrowing.sas: true (introduced in 1.25.0; present through 1.27.0). Default shared-key mode and other backends are unaffected. When the SAS is provisioned read-only, the impact reduces to unauthenticated read/download of all attachments.Reported by Kimi Security Team ([email protected]).
uploadfs >= 1.25.0, < 1.28.0Upgrade to a patched release:
uploadfs 1.28.0Connected by shared product, vendor, weakness, or advisory.
CVE-2026-113651Low· 3.3ApostropheCMS: Path traversal in uploadfs
CVE-2022-31746Medium· 6.5Internal URLs are protected by a secret UUID key, which could have been leaked to web page through the Referrer header
CVE-2025-31976Medium· 4.8HCL BigFix Service Management (SM) is vulnerable to insufficiently protected credentials for a short duration while communicating with a backend, internal application which could allow an attacker to potentially misuse them, if exfiltrat…
CVE-2018-12224Low· 3.3Buffer leakage in igdkm64.sys in Intel(R) Graphics Driver for Windows* before versions 10.18.x.5059 (aka 15.33.x.5059), 10.18.x.5057 (aka 15.36.x.5057), 20.19.x.5063 (aka 15.40.x.5063) 21.20.x.5064 (aka 15.45.x.5064) and 24.20.100.6373 m…
CVE-2016-0012Medium· 4.3Microsoft Office 2007 SP3, Excel 2007 SP3, PowerPoint 2007 SP3, Visio 2007 SP3, Word 2007 SP3, Office 2010 SP2, Excel 2010 SP2, PowerPoint 2010 SP2, Visio 2010 SP2, Word 2010 SP2, Office 2013 SP1, Excel 2013 SP1, PowerPoint 2013 SP1, Vis…
CVE-2016-0141Medium· 6.5The Visual Basic macros in Microsoft Office 2007 SP3, 2010 SP2, 2013 SP1, and 2016 export a certificate-store private key during a document-save operation, which allows attackers to obtain sensitive information via unspecified vectors, a…