fix(security): add archive extraction containment validation

Validate tar and zip entries before extraction to prevent path traversal:
- Reject absolute paths in archives
- Reject .. traversal paths
- Reject symlinks pointing outside extraction dir
- New archive-entry-validator module with comprehensive tests

Addresses: security audit finding for unsafe archive extraction.
This commit is contained in:
YeonGyu-Kim
2026-04-02 15:01:15 +09:00
parent a637cca702
commit d861d51959
5 changed files with 454 additions and 0 deletions
+19
View File
@@ -1,6 +1,9 @@
import { spawn, spawnSync } from "bun"
import { release } from "os"
import { validateArchiveEntries } from "./archive-entry-validator"
import { listZipEntriesWithPowerShell, listZipEntriesWithTar } from "./zip-entry-listing"
const WINDOWS_BUILD_WITH_TAR = 17134
function getWindowsBuildNumber(): number | null {
@@ -41,6 +44,9 @@ function getWindowsZipExtractor(): WindowsZipExtractor {
}
export async function extractZip(archivePath: string, destDir: string): Promise<void> {
const entries = await listZipEntries(archivePath)
validateArchiveEntries(entries, destDir)
let proc
if (process.platform === "win32") {
@@ -81,3 +87,16 @@ export async function extractZip(archivePath: string, destDir: string): Promise<
throw new Error(`zip extraction failed (exit ${exitCode}): ${stderr}`)
}
}
async function listZipEntries(archivePath: string) {
if (process.platform === "win32") {
const extractor = getWindowsZipExtractor()
if (extractor === "tar") {
return listZipEntriesWithTar(archivePath)
}
return listZipEntriesWithPowerShell(archivePath, escapePowerShellPath, extractor)
}
return listZipEntriesWithTar(archivePath)
}