Skip to content

fix(deps): Update dependency postcss to v8.5.18 [SECURITY] - #91

Open
williaby wants to merge 1 commit into
mainfrom
renovate/npm-postcss-vulnerability
Open

fix(deps): Update dependency postcss to v8.5.18 [SECURITY]#91
williaby wants to merge 1 commit into
mainfrom
renovate/npm-postcss-vulnerability

Conversation

@williaby

@williaby williaby commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Why

Scheduled patch update, bug fixes and security patches with no API changes.

Changes

This PR contains the following updates:

Package Change Age Confidence
postcss (source) 8.5.158.5.18 age confidence

Warning

Some dependencies could not be looked up. Check the Dependency Dashboard for more information.

Impact

  • ✅ Patch update: bug fixes and security patches only
  • ✅ No breaking changes

Acceptance Criteria

  • All CI checks pass

Testing

  • CI gates pass (tests, lint, type checking, security scan)

Notes


PostCSS: Path Traversal in Previous Source Map Auto-Loading (sourceMappingURL) leads to Arbitrary .map File Disclosure

GHSA-r28c-9q8g-f849

More information

Details

Vulnerability Details

File: lib/previous-map.js
Line: 87-98 (loadFile), 129-144 (loadMap)

Root Cause

PostCSS auto-detects a /*# sourceMappingURL=... */ comment inside the CSS text it is asked to parse and, unless the caller explicitly passes map: false, attempts to load that path from disk as a "previous source map." This happens on every postcss.parse() / postcss().process() call by default (opt-out, not opt-in).

loadMap() builds the candidate path via join(dirname(opts.from), annotation), where annotation is the raw, attacker-controlled string from the CSS comment. path.join() normalizes but does not sandbox .. segments, so a ../../../ prefix walks the resolved path outside the intended directory. If opts.from is not set at all, the annotation is used completely unmodified — an absolute path in the CSS comment is read verbatim.

8.5.12 already fixed a strictly worse variant of this (any file, any extension, could be read) by requiring the resolved path to end in .map (loadFile()). That fix did not address the traversal itself, only the target extension. Since the join(dirname(file), map) logic has existed unchanged since PostCSS 8.0.0 (Feb 2020), any file ending in .map remains readable through this path in the current release (8.5.16).

Once loaded, MapGenerator.isMap() treats the mere presence of a loaded "previous map" as an implicit request to generate result.map, even when the caller never set the map option. If the loaded map has a sourcesContent field (common for maps emitted by bundlers/transpilers), that content is merged into result.map and returned to the caller — disclosing the traversed-to file's content to whoever supplied the CSS.

Attack Scenario
  1. A service accepts user-submitted CSS and runs it through PostCSS to lint/format/transform it, e.g. postcss().process(userCss, { from: '/app/uploads/user123/input.css', to: '/app/uploads/user123/output.css' }) — idiomatic usage; map option untouched.
  2. Attacker submits CSS containing /*# sourceMappingURL=../../../../some/other/app/dist/bundle.js.map */ (or an absolute path if from is unset).
  3. PostCSS reads that .map file and folds its sourcesContent into result.map.
  4. The service does what most build pipelines do with a truthy result.map — writes it next to the CSS output or returns it via API (source maps are meant to be consumed by browser devtools, so this is commonly public/served).
  5. Attacker retrieves the emitted map and reads out the traversed file's content.
Impact

Disclosure of the contents of arbitrary .map files reachable via path traversal (or absolute path when from is unset) from the process's filesystem. Affects any application processing CSS it does not fully trust without explicitly passing map: false. No authentication or user interaction beyond submitting CSS text is required.

Vulnerable Code
loadFile(path, cssFile, trusted) {
  if (!trusted && !this.unsafeMap) {
    if (!/\.map$/i.test(path)) {
      return undefined
    }
  }
  this.root = dirname(path)
  if (existsSync(path)) {
    this.mapFile = path
    return readFileSync(path, 'utf-8').toString().trim()
  }
}

loadMap(file, prev) {
  ...
  } else if (this.annotation) {
    let map = this.annotation
    if (file) map = join(dirname(file), map)
    let unknown = this.loadFile(map, file, false)
    ...
  }
}
Recommended Fix

Constrain the resolved path to remain inside the CSS file's own directory instead of relying solely on a filename-extension check:

loadFile(path, cssFile, trusted) {
  if (!trusted && !this.unsafeMap) {
    if (!/\.map$/i.test(path)) {
      return undefined
    }
    if (!cssFile) return undefined
    let root = resolve(dirname(cssFile))
    let resolvedPath = resolve(root, path)
    if (resolvedPath !== root && !resolvedPath.startsWith(root + sep)) {
      return undefined
    }
  }
  this.root = dirname(path)
  if (existsSync(path)) {
    this.mapFile = path
    return readFileSync(path, 'utf-8').toString().trim()
  }
}

I've implemented, tested (full existing test suite — 660/660 passing, plus new PoC-based regression checks for both the traversal and legitimate same-directory cases), and can share this fix on request or via a private fork if invited.

Verification

Dynamically confirmed on v8.5.16 (current npm release / repo HEAD) via a standalone Node.js harness against lib/postcss.js: a "secret" .map file placed two directories outside a simulated project directory was read via a crafted sourceMappingURL comment in otherwise-innocuous CSS, with its sourcesContent appearing verbatim in result.map.toString() — with no map option set by the caller. A second harness confirmed the simpler no-from case reads an absolute path directly. A third harness confirmed map: false is the only current workaround. The attached fix branch closes both vectors while keeping all 660 existing unit tests green.

Severity

  • CVSS Score: 7.5 / 10 (High)
  • Vector String: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Release Notes

postcss/postcss (postcss)

v8.5.18

Compare Source

  • Restricted loading previous source maps file to the opts.from folder for security reasons (use unsafeMap: true to disable the check).

v8.5.17

Compare Source

  • Fixed Maximum call stack size exceeded error.
  • Fixed Prototype hijacking for postcss.fromJSON().
  • Fixed Input#origin() for unmapped end position (by @​chatman-media).

v8.5.16

Compare Source


Configuration

📅 Schedule: (in timezone America/New_York)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR has been generated by Mend Renovate.

Copilot AI review requested due to automatic review settings August 1, 2026 20:33
@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

Next included review available in 34 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Team

Run ID: 8fd68922-e428-4369-9727-374318795d93

📥 Commits

Reviewing files that changed from the base of the PR and between 9f80a0c and 952082b.

⛔ Files ignored due to path filters (1)
  • frontend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (1)
  • frontend/package.json

Walkthrough

The frontend postcss development dependency range changes from ^8.5.6 to ^8.5.18.

Changes

Frontend dependency update

Layer / File(s) Summary
Update PostCSS version range
frontend/package.json
The postcss development dependency changes from ^8.5.6 to ^8.5.18.

Estimated code review effort: 1 (Trivial) | ~2 minutes

Suggested reviewers: copilot, byronwilliamscpa

Poem

A rabbit checks the package line,
PostCSS hops to version fine.
From eight-five-six to eight-five-eighteen,
A tidy change in the frontend scene.
“All set!” the bunny says with cheer.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the PostCSS dependency update and its security purpose.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch renovate/npm-postcss-vulnerability

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@socket-security

socket-security Bot commented Aug 1, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatednpm/​postcss@​8.5.15 ⏵ 8.5.18100 +199 +168194 +1100

View full report

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown

⚠️ Deprecation Warning: The deny-licenses option is deprecated for possible removal in the next major release. For more information, see issue 997.

Dependency Review

The following issues were found:
  • ❌ 1 vulnerable package(s)
  • ✅ 0 package(s) with incompatible licenses
  • ✅ 0 package(s) with invalid SPDX license definitions
  • ✅ 0 package(s) with unknown licenses.
See the Details below.

Vulnerabilities

frontend/package-lock.json

NameVersionVulnerabilitySeverity
postcss8.5.18PostCSS: incomplete fix of GHSA-6g55-p6wh-862q — attacker-controlled sourceMappingURL reads arbitrary .map files when `from` is unsetmoderate
Only included vulnerabilities with severity moderate or higher.

OpenSSF Scorecard

PackageVersionScoreDetails
npm/postcss 8.5.18 🟢 7.5
Details
CheckScoreReason
Code-Review🟢 4Found 12/30 approved changesets -- score normalized to 4
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Packaging⚠️ -1packaging workflow not detected
Maintained🟢 1030 commit(s) and 16 issue activity found in the last 90 days -- score normalized to 10
Security-Policy🟢 10security policy file detected
Binary-Artifacts🟢 10no binaries found in the repo
Token-Permissions🟢 9detected GitHub workflow tokens with excessive permissions
Pinned-Dependencies🟢 10all dependencies are pinned
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Fuzzing🟢 10project is fuzzed
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Branch-Protection🟢 3branch protection is not maximal on development and all release branches
SAST⚠️ 0SAST tool is not run on all commits -- score normalized to 0

Scanned Files

  • frontend/package-lock.json

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/package.json`:
- Line 47: Update the PostCSS dependency from 8.5.18 to the approved 8.5.23
version in package metadata, then regenerate the lockfile so its resolved
PostCSS entry and integrity data match 8.5.23.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ee714266-7508-4e67-bcf8-9060cdbd320b

📥 Commits

Reviewing files that changed from the base of the PR and between a06abe3 and 9f80a0c.

⛔ Files ignored due to path filters (1)
  • frontend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (1)
  • frontend/package.json

Comment thread frontend/package.json
"globals": "^17.0.0",
"jsdom": "^29.0.0",
"postcss": "^8.5.6",
"postcss": "^8.5.18",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== package files =="
fd -a '^(package|package-lock)\.json$' . 2>/dev/null | sed "s#^$(pwd)/##" | head -50

echo
echo "== frontend/package.json postcss section =="
if [ -f frontend/package.json ]; then
  nl -ba frontend/package.json | sed -n '1,80p'
fi

echo
echo "== lockfile postcss entries =="
if [ -f frontend/package-lock.json ]; then
  rg -n '"postcss"|source-map' frontend/package-lock.json -C 2 || true
  python3 - <<'PY'
import json
p='frontend/package-lock.json'
data=json.load(open(p))
packages=data.get('packages', {})
for pkg in [p for p in packages if p.endswith('node_modules/postcss') or p=='node_modules/postcss']:
    print(pkg, '=>', packages[pkg])
PY
fi

echo
echo "== npmjs/release metadata =="
npm view postcss version dist-tags --json 2>/dev/null | sed -n '1,120p' || true

Repository: ByronWilliamsCPA/rag-processor

Length of output: 323


🌐 Web query:

PostCSS 8.5.23 source-map security hardening release notes

💡 Result:

PostCSS version 8.5.23, released on July 24, 2026, includes security hardening related to source map handling [1][2]. Specifically, this release introduces a change to prevent the loading of source map files when the 'from' option is not provided [3][2]. This change is part of ongoing efforts to address security vulnerabilities involving arbitrary file read and information disclosure via attacker-controlled 'sourceMappingURL' comments in CSS [4][5][6]. Previous versions of PostCSS would attempt to dereference and load these paths from the local filesystem by default, even when no source map was intended or explicitly configured, potentially allowing attackers to read files on the host system [4][5][6]. By requiring the 'from' option to be present for source map loading, PostCSS adds a layer of defense to limit the scenarios in which files are automatically accessed [3][2].

Citations:


🌐 Web query:

PostCSS 8.5.25 GitHub release

💡 Result:

PostCSS version 8.5.25 was released on July 29, 2026 [1][2][3][4]. This release included two specific fixes: a correction for an 8.5.17 visitor regression and a fix for list.split when handling non-string values [1].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== npm metadata =="
npm view postcss version dist-tags --json 2>/dev/null || true

echo
echo "== frontend/package.json =="
python3 - <<'PY'
from pathlib import Path
p = Path("frontend/package.json")
text = p.read_text()
for i, line in enumerate(text.splitlines(), 1):
    if "postcss" in line.lower() or i <= 80:
        print(f"{i}: {line}")
PY

echo
echo "== frontend/package-lock.json postcss entries =="
python3 - <<'PY'
import json
from pathlib import Path
p = Path("frontend/package-lock.json")
data = json.loads(p.read_text())
for name, entry in data.get("packages", {}).items():
    if name == "node_modules/postcss" or name.endswith("/node_modules/postcss"):
        print(f"{name}:")
        for k, v in entry.items():
            if k in ("version", "resolved", "integrity", "dependencies", "dev"):
                print(f"  {k}: {v}")
PY

echo
echo "== semantic comparison =="
python3 - <<'PY'
import re
locked = Path("frontend/package-lock.json").read_text()
m = re.search(r'"node_modules/postcss":\s*\{[^"]*"version"\s*:\s*"([^"]+)"', locked)
manifest = Path("frontend/package.json").read_text()
match = re.search(r'"postcss"\s*:\s*"([^"]+)"', manifest)
print(f"locked_version={m.group(1) if m else None}")
print(f"manifest_range={match.group(1) if match else None}")
PY

Repository: ByronWilliamsCPA/rag-processor

Length of output: 2703


Update the locked PostCSS version.

frontend/package-lock.json pins PostCSS to 8.5.18, so installs from the lockfile do not get PostCSS 8.5.23 source-map hardening. Regenerate the lockfile to resolve PostCSS to the latest approved patch version.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/package.json` at line 47, Update the PostCSS dependency from 8.5.18
to the approved 8.5.23 version in package metadata, then regenerate the lockfile
so its resolved PostCSS entry and integrity data match 8.5.23.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the frontend build tooling dependency postcss to a patched version that includes security fixes, aligning with the Renovate-driven dependency maintenance workflow.

Changes:

  • Bumped postcss in frontend/package.json to ^8.5.18.
  • Updated the node_modules/postcss entry in frontend/package-lock.json to 8.5.18 with corresponding resolved URL and integrity hash.

Reviewed changes

Copilot reviewed 1 out of 2 changed files in this pull request and generated 1 comment.

File Description
frontend/package.json Updates the declared devDependency range for postcss to ^8.5.18.
frontend/package-lock.json Updates the locked postcss package version metadata to 8.5.18.
Files not reviewed (1)
  • frontend/package-lock.json: Generated file

Comment thread frontend/package.json
"globals": "^17.0.0",
"jsdom": "^29.0.0",
"postcss": "^8.5.6",
"postcss": "^8.5.18",
@sonarqubecloud

sonarqubecloud Bot commented Aug 1, 2026

Copy link
Copy Markdown

@williaby
williaby enabled auto-merge September 3, 2026 12:33
@williaby
williaby force-pushed the renovate/npm-postcss-vulnerability branch from 9f80a0c to d129cdf Compare September 3, 2026 16:41
@williaby
williaby force-pushed the renovate/npm-postcss-vulnerability branch from d129cdf to 952082b Compare September 3, 2026 17:06
@sonarqubecloud

sonarqubecloud Bot commented Sep 3, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants