🛡️ CVE-2026-45623 — postcss

🟠 CVSS 8.0 — High ⚠️ Exploit Public CWE-200 OSV
8.0
CVSS Score
0 Low4 Medium7 High9 Critical10

Description

PostCSS: Arbitrary file read and information disclosure via attacker-controlled sourceMappingURL in CSS comments

Summary

PostCSS's PreviousMap parses the /*# sourceMappingURL=PATH */ comment from any CSS string passed to process() and dereferences PATH against the local filesystem with no scheme, allowlist, or traversal check. An attacker who controls the CSS input can cause the host process to read any file readable by Node and leak the first ~10 bytes of its content through the resulting JSON.parse SyntaxError message. The bug also yields a precise file-existence oracle and a controllable-read primitive that may be combined with large-file targets for DoS. The behaviour is triggered with PostCSS's default options — no from, no map, no plugins required — and is therefore reachable from any pipeline that runs untrusted CSS through PostCSS (CMS themes, user-uploaded styles, browser-extension/userstyle processors, build pipelines for third-party packages, blog comment renderers, etc.).

Details

The dangerous chain lives in lib/previous-map.js and is wired into every Input construction at lib/input.js:70-77.

Input constructor (lib/input.js:70-77):

```js

if (pathAvailable && sourceMapAvailable) {

let map = new PreviousMap(this.css, opts)

if (map.text) {

this.map = map

let file = map.consumer().file

if (!this.file && file) this.file = this.mapResolve(file)

}

}

```

PreviousMap constructor (lib/previous-map.js:17-29):

```js

constructor(css, opts) {

if (opts.map === false) return

this.loadAnnotation(css)

this.inline = this.startWith(this.annotation, 'data:')

let prev = opts.map ? opts.map.prev : undefined

let text = this.loadMap(opts.from, prev)

...

}

```

Note opts.map === false is the only short-circuit. With default options (opts.map === undefined), the rest of the constructor — including the filesystem read — executes.

loadAnnotation (lib/previous-map.js:72-84) extracts the URL without sanitisation:

```js

loadAnnotation(css) {

let comments = css.match(/\/\*\s*# sourceMappingURL=/g)

if (!comments) return

let start = css.lastIndexOf(comments.pop())

let end = css.indexOf('*/', start)

if (start > -1 && end > -1) {

this.annotation = this.getAnnotationURL(css.substring(start, end))

}

}

```

getAnnotationURL (lib/previous-map.js:59-61) only strips the /*# sourceMappingURL= prefix and trims whitespace — no scheme check, no path normalisation, no allowlist.

loadMap (lib/previous-map.js:124-128) — when prev is absent and the annotation is not an inline data: URI:

```js

} else if (this.annotation) {

let map = this.annotation

if (file) map = join(dirname(file), map)

return this.loadFile(map)

}

```

  • If opts.from is unset, file is undefined and the raw attacker-supplied path (e.g. /etc/passwd) is used directly.
  • If opts.from is set, path.join(dirname(file), attackerPath) is used. path.join does not block .. segments, so ../../../../../etc/passwd resolves outside the intended directory.

loadFile (lib/previous-map.js:86-92) is the sink:

```js

loadFile(path) {

this.root = dirname(path)

if (existsSync(path)) {

this.mapFile = path

return readFileSync(path, 'utf-8').toString().trim()

}

}

```

The bytes are stored in this.text. Input immediately invokes map.consumer() (lib/input.js:74), which constructs a SourceMapConsumer (lib/previous-map.js:33). When the file is not valid source-map JSON (the common case), source-map-js calls JSON.parse, and V8's SyntaxError message embeds the first ~10 bytes of the file content:

```

Unexpected token 'r', "root:x:0:0"... is not valid JSON

```

This error is propagated back to the caller. Any application that surfaces PostCSS errors (logs, HTTP 500 responses, build-tool output, debug pages) discloses those bytes to the attacker.

Trust-boundary analysis:

  • Attacker controls: CSS input passed to postcss().process(css, opts?).
  • Server resources: any file readable by the Node process — typically including app config, environment files, SSH keys, /etc/passwd, /proc/self/environ, etc.
  • No mitigations: there is no path validation, scheme allowlist, traversal check, or symlink check. The only relevant check (startWith(annotation, 'data:')) routes inline URIs to decodeInline; everything else hits loadFile.

Primitives obtained:

  • (a) Arbitrary file read — bytes loaded into Node memory.
  • (b) Information disclosure — first ~10 bytes leaked via JSON.parse SyntaxError message.
  • (c) File-existence oracle — non-existent paths return silently from loadFile (existsSync is false → returns undefined → no map text → no consumer call → no error). Existent non-JSON paths throw. Existent JSON paths succeed silently. Three distinguishable states.
  • (d) DoS primitive — directing the read at /dev/zero, very large files, or device files can stall or crash the process.

PoC

All commands execut

How this vulnerability can be exploited

This issue can be reached over the network, attack complexity is low, an attacker needs no privileges on the target. No user interaction is required. The scope is unchanged, so the impact stays within the vulnerable component. Rated impact: confidentiality high, integrity none, availability none.

Weakness class

CVE-2026-45623 is classified as CWE-200: Exposure of Sensitive Information. Information that should stay internal is disclosed to someone who is not authorised to see it.

Affected software

CVE-2026-45623 is recorded against 1 package.

  • postcss

Timeline and source

Published on 23 July 2026 and last revised on 7 August 2026. A public exploit is known to exist, which raises the urgency of patching considerably. Record sourced from OSV.

References

github.com (Web)
github.com (Web)
github.com (Web)
github.com (Package)
github.com (Web)

Details

Severity HIGH
CVSS Score 8.0
CVSS Vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
CWE CWE-200
Public Exploit ⚠️ Yes
Source OSV
Published 2026-07-23
Updated 2026-08-12
Modified 2026-08-07
Fix URL N/A

Affected Packages

Software From version Fixed in
postcss

Exploit Protection

Are you running postcss?

CVE-2026-45623 carries CVSS 8.0 High rating and a public exploit already exists. BotEraser checks your installation against this and other known CVE records, and blocks IPs associated with exploit activity.

Check My Site For CVE-2026-45623 →

No credit card required  ·  Results in minutes

ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.