Visitar URL original
Resolve symlinks before the previous-source-map containment check (#2… · postcss/postcss@29e9e00 · GitHub
Skip to content

Commit 29e9e00

Browse files
authored
Resolve symlinks before the previous-source-map containment check (#2125)
relative() is textual and never resolves symlinks, so a symlink at or below the CSS file’s directory passes the guard and readFileSync() follows it out of the tree. Resolve both sides with realpathSync first so the check rejects by outcome rather than syntax.
1 parent 3ba8f84 commit 29e9e00

1 file changed

Lines changed: 14 additions & 2 deletions

File tree

‎lib/previous-map.js‎

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
11
'use strict'
22

3-
let { existsSync, readFileSync } = require('fs')
3+
let { existsSync, readFileSync, realpathSync } = require('fs')
44
let { dirname, isAbsolute, join, relative, sep } = require('path')
55
let { SourceMapConsumer, SourceMapGenerator } = require('source-map-js')
66

7+
function realPath(path) {
8+
try {
9+
return realpathSync(path)
10+
} catch {
11+
// Missing or dangling: keep the literal path. The existsSync() check below
12+
// still gates the read, and a path that does not exist cannot escape.
13+
return path
14+
}
15+
}
16+
717
function fromBase64(str) {
818
if (Buffer) {
919
return Buffer.from(str, 'base64').toString()
@@ -89,7 +99,9 @@ class PreviousMap {
8999
if (!/\.map$/i.test(path)) return undefined
90100
if (!cssFile) return undefined
91101

92-
let rel = relative(dirname(cssFile), path)
102+
// Compare *resolved* paths: relative() is textual, so without this a
103+
// symlink at or below the CSS file's directory points the map outside it.
104+
let rel = relative(realPath(dirname(cssFile)), realPath(path))
93105
if (rel === '..' || rel.startsWith('..' + sep) || isAbsolute(rel)) {
94106
return undefined
95107
}

0 commit comments

Comments
 (0)