@pnpm/fetching.binary-fetcher 1005.0.1 → 1005.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,7 +1,7 @@
1
1
  The MIT License (MIT)
2
2
 
3
3
  Copyright (c) 2015-2016 Rico Sta. Cruz and other contributors
4
- Copyright (c) 2016-2025 Zoltan Kochan and other contributors
4
+ Copyright (c) 2016-2026 Zoltan Kochan and other contributors
5
5
 
6
6
  Permission is hereby granted, free of charge, to any person obtaining a copy
7
7
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -8,6 +8,28 @@
8
8
  pnpm add @pnpm/fetching.binary-fetcher
9
9
  ```
10
10
 
11
+ ## Testing
12
+
13
+ ### Test Fixtures
14
+
15
+ The `test/fixtures/` directory contains malicious ZIP files for testing path traversal protection:
16
+
17
+ | File | Entry Path | Purpose |
18
+ |------|------------|---------|
19
+ | `path-traversal.zip` | `../../../.npmrc` | Tests `../` escape sequences |
20
+ | `absolute-path.zip` | `/etc/passwd` | Tests absolute path entries |
21
+ | `backslash-traversal.zip` | `..\..\..\evil.txt` | Tests Windows backslash traversal (Windows-only) |
22
+
23
+ These fixtures are manually crafted because AdmZip's `addFile()` sanitizes paths automatically.
24
+
25
+ > **Note:** The backslash test only runs on Windows because `\` is a valid filename character on Unix.
26
+
27
+ ### Regenerating Fixtures
28
+
29
+ ```bash
30
+ node --experimental-strip-types scripts/create-fixtures.ts
31
+ ```
32
+
11
33
  ## License
12
34
 
13
35
  MIT
package/lib/index.js CHANGED
@@ -10,6 +10,7 @@ const promises_1 = __importDefault(require("fs/promises"));
10
10
  const error_1 = require("@pnpm/error");
11
11
  const worker_1 = require("@pnpm/worker");
12
12
  const adm_zip_1 = __importDefault(require("adm-zip"));
13
+ const is_subdir_1 = __importDefault(require("is-subdir"));
13
14
  const rename_overwrite_1 = __importDefault(require("rename-overwrite"));
14
15
  const tempy_1 = __importDefault(require("tempy"));
15
16
  const ssri_1 = __importDefault(require("ssri"));
@@ -118,13 +119,39 @@ async function downloadWithIntegrityCheck(fetchFromRegistry, { url, integrity },
118
119
  * @param zipPath - Path to the zip file
119
120
  * @param basename - Base name of the file (without extension)
120
121
  * @param targetDir - Directory where contents should be extracted
121
- * @throws {PnpmError} When extraction fails
122
+ * @throws {PnpmError} When extraction fails or path traversal is detected
122
123
  */
123
124
  async function extractZipToTarget(zipPath, basename, targetDir) {
124
125
  const zip = new adm_zip_1.default(zipPath);
125
126
  const nodeDir = basename === '' ? targetDir : path_1.default.dirname(targetDir);
127
+ // Validate basename/prefix doesn't escape the target directory
128
+ if (basename !== '') {
129
+ validatePathSecurity(nodeDir, basename);
130
+ }
131
+ // Extract each entry with path validation to prevent path traversal attacks
132
+ for (const entry of zip.getEntries()) {
133
+ const entryPath = entry.entryName;
134
+ validatePathSecurity(nodeDir, entryPath);
135
+ zip.extractEntryTo(entry, nodeDir, true, true);
136
+ }
126
137
  const extractedDir = path_1.default.join(nodeDir, basename);
127
- zip.extractAllTo(nodeDir, true);
128
138
  await (0, rename_overwrite_1.default)(extractedDir, targetDir);
129
139
  }
140
+ /**
141
+ * Validates that a path does not escape the base directory via path traversal.
142
+ *
143
+ * @param basePath - The base directory that should contain the target
144
+ * @param targetPath - The relative path to validate
145
+ * @throws {PnpmError} When path traversal is detected
146
+ */
147
+ function validatePathSecurity(basePath, targetPath) {
148
+ // Explicitly reject absolute paths - they should never be allowed as prefixes or entry names
149
+ if (path_1.default.isAbsolute(targetPath)) {
150
+ throw new error_1.PnpmError('PATH_TRAVERSAL', `Refusing to extract path "${targetPath}" - absolute paths are not allowed`);
151
+ }
152
+ const normalizedTarget = path_1.default.resolve(basePath, targetPath);
153
+ if (!(0, is_subdir_1.default)(basePath, normalizedTarget) && normalizedTarget !== basePath) {
154
+ throw new error_1.PnpmError('PATH_TRAVERSAL', `Refusing to extract path "${targetPath}" outside of target directory`);
155
+ }
156
+ }
130
157
  //# sourceMappingURL=index.js.map
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pnpm/fetching.binary-fetcher",
3
- "version": "1005.0.1",
3
+ "version": "1005.0.2",
4
4
  "description": "A fetcher for binary archives",
5
5
  "keywords": [
6
6
  "pnpm",
@@ -25,20 +25,23 @@
25
25
  ],
26
26
  "dependencies": {
27
27
  "adm-zip": "^0.5.16",
28
+ "is-subdir": "^1.2.0",
28
29
  "rename-overwrite": "^6.0.2",
29
30
  "ssri": "10.0.5",
30
31
  "tempy": "^1.0.1",
31
- "@pnpm/fetching-types": "1000.2.0",
32
32
  "@pnpm/error": "1000.0.5",
33
- "@pnpm/fetcher-base": "1001.2.1"
33
+ "@pnpm/fetcher-base": "1001.2.2",
34
+ "@pnpm/fetching-types": "1000.2.0"
34
35
  },
35
36
  "peerDependencies": {
36
- "@pnpm/worker": "^1000.6.1"
37
+ "@pnpm/worker": "^1000.6.2"
37
38
  },
38
39
  "devDependencies": {
40
+ "@jest/globals": "29.7.0",
39
41
  "@types/adm-zip": "^0.5.7",
40
42
  "@types/ssri": "^7.1.5",
41
- "@pnpm/fetching.binary-fetcher": "1005.0.1"
43
+ "tempy": "^1.0.1",
44
+ "@pnpm/fetching.binary-fetcher": "1005.0.2"
42
45
  },
43
46
  "engines": {
44
47
  "node": ">=18.12"
@@ -47,8 +50,9 @@
47
50
  "preset": "@pnpm/jest-config"
48
51
  },
49
52
  "scripts": {
50
- "lint": "eslint \"src/**/*.ts\"",
51
- "test": "pnpm run compile",
53
+ "_test": "jest",
54
+ "test": "pnpm run compile && pnpm run _test",
55
+ "lint": "eslint \"src/**/*.ts\" \"test/**/*.ts\"",
52
56
  "compile": "tsc --build && pnpm run lint --fix"
53
57
  }
54
58
  }