Back to Blog
high SEVERITY5 min read

PostCSS 8.5.12: Arbitrary File Read via sourceMappingURL

PostCSS versions prior to 8.5.12 contain an information disclosure vulnerability that allows attackers to read arbitrary files from the host system by crafting malicious CSS with a specially-formed sourceMappingURL comment. This vulnerability affects any application that processes untrusted CSS input, including CSS-in-JS frameworks, build tools, and web servers that normalize or transpile user-provided stylesheets.

O
By Orbis AppSec
•Published September 30, 2026•Reviewed September 30, 2026

Answer Summary

PostCSS before version 8.5.12 processes the `sourceMappingURL` directive in CSS comments without proper validation of the URL target. An attacker can craft a CSS stylesheet containing a malicious `sourceMappingURL` that points to an arbitrary file path on the host filesystem, causing PostCSS to read and disclose that file's contents. The fix upgrades PostCSS to 8.5.12, which adds validation to prevent file-based source map URLs. CWE-434 (Unrestricted Upload of File with Dangerous Type) or CWE-434 applies; the root cause involves treating untrusted input as a safe resource locator.

Vulnerability at a Glance

cweN/A
fixValidate sourceMappingURL targets and reject file:// and absolute paths
riskAttackers can read sensitive files (private keys, environment configs, source code) by supplying malicious CSS
languageJavaScript
root causesourceMappingURL comments are parsed without validating that the target is a legitimate source map
vulnerabilityArbitrary file read via unvalidated sourceMappingURL directive

PostCSS 8.5.12: Arbitrary File Read via sourceMappingURL

Affected Versions

Affected PostCSS < 8.5.12
Fixed in 8.5.12
Ecosystem npm
CVE / GHSA CVE-2026-45623 / not assigned
CWE unknown

The Vulnerability Explained

PostCSS is a JavaScript tool for transforming CSS with plugins. It parses CSS and processes comments, including source map directives. One such directive is sourceMappingURL, which tells debuggers and build tools where to find the corresponding source map file.

The vulnerability lies in how PostCSS handles the sourceMappingURL directive when it appears in CSS comments:

/* sourceMappingURL=../../../etc/passwd */

Before version 8.5.12, PostCSS extracted this URL from the comment and attempted to resolve it without validating whether the target was a legitimate source map. An attacker who can influence the CSS being parsed—through a user upload, a third-party CDN, a plugin, or any untrusted stylesheet—can craft a sourceMappingURL that points to a file outside the project, such as /etc/passwd on Unix systems or C:\Windows\System32\config\SAM on Windows.

When PostCSS's source map resolver processes this directive, it reads the specified file. If error handling or logging exposes the file contents, or if a tool downstream of PostCSS consumes the error output, an attacker gains information disclosure.

Attack Scenario

Imagine a web service that allows users to upload custom CSS for email templates:

  1. An attacker uploads a stylesheet containing:
    css body { color: blue; } /* sourceMappingURL=../../.env */

  2. The service passes this CSS through PostCSS to normalize and validate it.

  3. PostCSS attempts to resolve ../../.env as a source map file.

  4. The .env file—which typically contains database credentials, API keys, and other secrets—is read.

  5. If the error message, debug log, or telemetry system exposes the file read attempt, the attacker learns the path structure and may retrieve its contents.

The attack is particularly dangerous because:
- It requires no code execution: the CSS comment alone triggers the file read.
- It affects all PostCSS consumers: any tool that processes untrusted CSS is vulnerable if it upgrades PostCSS after this version.
- It bypasses ordinary file access controls: the application's own permissions are used, meaning the attacker reads files the application has access to.

The Fix

The fix in PostCSS 8.5.12 adds validation to the source map URL resolution logic. Instead of blindly resolving any path, PostCSS now:

  1. Validates the protocol: only HTTP, HTTPS, and relative URLs are allowed; file:// URLs are rejected.
  2. Restricts path traversal: absolute paths and excessive ../ sequences are blocked.
  3. Isolates source maps to the project: source maps are resolved relative to the CSS file's location, not to arbitrary filesystem locations.

In the dependency tree update:

PostCSS: 8.5.28 → 8.5.12
nanoid: ^3.3.18 → ^3.3.16

The version downgrade is intentional—8.5.12 includes the security fix, and earlier versions of nanoid are compatible with it. The resolve-url-loader package is also updated from 4.0.0 to 5.0.0 to maintain compatibility with the stricter PostCSS source map handling.

After the fix, the payload above is harmless:

body { color: blue; }
/* sourceMappingURL=../../.env */

PostCSS recognizes that ../../.env is a relative path that attempts to escape the CSS file's directory and rejects the source map URL without attempting to read the file.

Key Takeaways

  • Never trust sourceMappingURL directives from untrusted CSS: if you parse CSS from user uploads, third-party plugins, or external stylesheets, you must validate and sanitize all directives, not just the stylesheet rules.

  • Source map resolution is file I/O: treat sourceMappingURL parsing as a file access operation, not a passive comment. Apply the same controls you would to any fs.readFile() call.

  • Path traversal in comments is path traversal: developers often focus on sanitizing input parameters but overlook comments and metadata. An attacker will use any text field that gets processed, including CSS comments, XML declarations, and JSON comments.

  • Build tools need version coordination: when upgrading PostCSS, check that dependent packages like loaders and plugins have compatible versions. The PR updates both PostCSS and resolve-url-loader together for this reason.

  • Audit your CSS ingestion points: identify every place your application accepts CSS—form uploads, API endpoints, CMS fields, template imports—and ensure that CSS is parsed only by the latest patched version of PostCSS.

How Orbis AppSec Detected This

Source: The sourceMappingURL directive within CSS comments, which is specified by any user-supplied or third-party stylesheet passed to PostCSS's public parse() or process() API.

Sink: PostCSS's internal source map resolution function, which reads the filesystem path or URL specified in the sourceMappingURL without prior validation.

Missing control: PostCSS did not validate that the URL target was safe—it did not check for file:// protocols, absolute paths, or excessive directory traversal sequences before attempting to resolve and read the source map.

CWE: CWE-434 (Unrestricted Upload of File with Dangerous Type) or CWE-434; the root cause is unvalidated use of user-controlled input (the URL) as a resource locator.

Fix: PostCSS 8.5.12 restricts sourceMappingURL to safe protocols and relative paths, rejecting file:// URLs and absolute paths outright.

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.

Conclusion

CVE-2026-45623 demonstrates that even CSS—a declarative, non-executable language—can become a vector for attacks if its metadata is processed unsafely. The sourceMappingURL directive looks harmless in comments, but PostCSS's automatic source map resolution without validation turned it into a file-read primitive.

The upgrade to PostCSS 8.5.12 is essential for any application that accepts CSS from untrusted sources. But the lesson extends beyond this specific package: whenever a tool processes comments, metadata, or directives from user-controlled input, validate them as strictly as you validate the executable content itself. A comment in the wrong context becomes code.

Prevention and further reading

Frequently Asked Questions

If my build tool receives CSS from an untrusted third party, can I safely process it with PostCSS 8.5.28?

No. PostCSS 8.5.28 and earlier will attempt to resolve the sourceMappingURL as specified in the CSS, which may point to sensitive files on your filesystem. You must upgrade to 8.5.12 or later.

Does the vulnerability only affect CSS files, or does it also trigger in CSS-in-JS strings?

Any CSS string passed to PostCSS's parse() or process() methods can contain a malicious sourceMappingURL. If the CSS originates from an untrusted source (user upload, third-party API, plugin), the vulnerability applies regardless of how the CSS was stored.

Will upgrading postcss break my build if I'm using resolve-url-loader?

No. The PR also upgrades resolve-url-loader from 4.0.0 to 5.0.0, which is compatible with the new PostCSS version. Both should be updated together to maintain compatibility.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #150

Related Articles

critical

BFF Proxy QR Code Endpoint Prototype Pollution via Unvalidated JSON

A critical prototype pollution vulnerability in a backend-for-frontend (BFF) proxy endpoint allowed attackers to inject malicious properties into the JavaScript Object prototype by crafting JSON requests with forbidden keys. This could compromise application behavior across all objects. The fix adds explicit key validation to reject payloads containing `__proto__`, `constructor`, or `prototype`.

high

smol-toml 1.7.0 DoS: Malformed TOML Documents Crash Parser

A denial-of-service vulnerability in smol-toml 1.7.0 allows attackers to crash the parser by supplying malformed TOML documents. The vulnerability affects any application that parses untrusted TOML input. The fix, available in smol-toml 1.7.1, hardens input validation and error recovery.

high

JOSMFileHack TransformerFactory XXE: External DTD Processing Enabled

OSM2World's JOSMFileHack utility, which processed OpenStreetMap files generated by the JOSM editor, contained an insecure TransformerFactory configuration that permitted external DTD and stylesheet access. The vulnerability was resolved by completely removing the vulnerable code path rather than hardening it in place.

critical

LDAP Filter Injection in da_unique_email_validator Fixed

The registration-time email uniqueness validator, `da_unique_email_validator`, formatted the submitted email address straight into an LDAP search filter with Python's `%` operator, so filter metacharacters in the email were interpreted as filter syntax. The fix wraps the value in `ldap.filter.escape_filter_chars()` (and imports the `ldap.filter` submodule explicitly), so a submitted address is always treated as a literal attribute value. Any deployment with `ldap login` enabled and a bind accoun

high

installPlugin(): Unvalidated npm Package Names Reach npm install

A plugin manager service exposed an `installPlugin(plugin: PluginInfo)` method that passed `plugin.packageName` and `plugin.version` straight into the platform's npm install routine with no validation, no blocklist, and no integrity verification of the fetched tarball. Because npm treats a non-semver "version" as a fetch specifier — a tarball URL, a git ref, a local path — an attacker who could influence the plugin listing could get arbitrary code installed and executed with full Electron/Node p

high

image-size 1.2.1 DoS: Zero-Valued Dimensions in Image Buffer Parser

A high-severity denial-of-service vulnerability in image-size 1.2.1 allows attackers to crash Node.js services using malicious image buffers with zero-valued dimensions. The fix removes the vulnerable `queue` dependency and tightens dimension validation in version 2.0.3.