mirror of
https://github.com/actions/toolkit.git
synced 2026-08-07 00:00:18 +02:00
Fix GNU tar path matching issue
This commit is contained in:
+4
-2
@@ -208,8 +208,10 @@ and bsdtar on macOS (and `tar.exe` on Windows):
|
|||||||
- `'error'` mode, clean archive → every approved member is extracted
|
- `'error'` mode, clean archive → every approved member is extracted
|
||||||
- `'error'` mode, PAX path newline archive → throws `CacheIntegrityError` and
|
- `'error'` mode, PAX path newline archive → throws `CacheIntegrityError` and
|
||||||
writes nothing to the workspace
|
writes nothing to the workspace
|
||||||
- `'error'` mode, leading `./` entry → still extracted (the `-T` allow-list
|
- `'error'` mode, leading `./` entry → still extracted; the `-T` allow-list
|
||||||
uses the canonical `cache/f` name, so the member is not silently skipped)
|
uses the member name verbatim (exactly as node-tar derived it from the
|
||||||
|
archive), which is what GNU tar matches anchored/exact — stripping the `./`
|
||||||
|
would make GNU tar report "Not found in archive"
|
||||||
- `'error'` mode, long path (> 100 bytes) delivered via PAX → extracted, not
|
- `'error'` mode, long path (> 100 bytes) delivered via PAX → extracted, not
|
||||||
dropped by the allow-list (exercises long-name matching in `-T`)
|
dropped by the allow-list (exercises long-name matching in `-T`)
|
||||||
|
|
||||||
|
|||||||
Vendored
+9
-17
@@ -431,11 +431,16 @@ function writeAllowList(approvedNames: string[]): string {
|
|||||||
.randomBytes(8)
|
.randomBytes(8)
|
||||||
.toString('hex')}.lst`
|
.toString('hex')}.lst`
|
||||||
)
|
)
|
||||||
|
// Write each approved name exactly as node-tar derived it from the archive
|
||||||
|
// bytes. That is the same name system tar reads from the archive header, so
|
||||||
|
// an anchored `-T` match succeeds for every member without us second-guessing
|
||||||
|
// tar's name handling. In particular we must NOT strip a leading `./`: GNU
|
||||||
|
// tar matches `-T` names anchored and exact and keeps the `./`, so a
|
||||||
|
// `cache/f` pattern does not match a `./cache/f` member (it fails with
|
||||||
|
// "Not found in archive", exit code 2) whereas the verbatim `./cache/f`
|
||||||
|
// matches and extracts to `cache/f`.
|
||||||
const payload = Buffer.concat(
|
const payload = Buffer.concat(
|
||||||
approvedNames.flatMap(name => [
|
approvedNames.flatMap(name => [Buffer.from(name, 'utf8'), Buffer.from([0])])
|
||||||
Buffer.from(canonicalMemberName(name), 'utf8'),
|
|
||||||
Buffer.from([0])
|
|
||||||
])
|
|
||||||
)
|
)
|
||||||
// `flag: 'wx'` (O_CREAT | O_EXCL | O_WRONLY) makes the open fail if the path
|
// `flag: 'wx'` (O_CREAT | O_EXCL | O_WRONLY) makes the open fail if the path
|
||||||
// already exists, so a file or symlink pre-planted at the (randomized) temp
|
// already exists, so a file or symlink pre-planted at the (randomized) temp
|
||||||
@@ -446,19 +451,6 @@ function writeAllowList(approvedNames: string[]): string {
|
|||||||
return allowListPath
|
return allowListPath
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Canonicalize an approved entry name to the form system `tar` matches against
|
|
||||||
* its archive members when reading the `-T` allow-list. node-tar already
|
|
||||||
* converts backslashes to forward slashes; here we additionally strip any
|
|
||||||
* leading `./` (both GNU tar and bsdtar normalize member names this way) so an
|
|
||||||
* entry node-tar surfaced as `./cache/f` still matches the member `cache/f`
|
|
||||||
* and is not silently skipped during extraction. A trailing slash on a
|
|
||||||
* directory entry is preserved because tar matches directories with it.
|
|
||||||
*/
|
|
||||||
function canonicalMemberName(name: string): string {
|
|
||||||
return name.replace(/^(?:\.\/)+/, '')
|
|
||||||
}
|
|
||||||
|
|
||||||
function reportViolations(
|
function reportViolations(
|
||||||
violations: PathValidationViolation[],
|
violations: PathValidationViolation[],
|
||||||
mode: PathValidationMode
|
mode: PathValidationMode
|
||||||
|
|||||||
Reference in New Issue
Block a user