wyvrnpm 2.4.1 → 2.8.1

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.
@@ -7,6 +7,7 @@ const path = require('path');
7
7
  const { getProvider } = require('./providers');
8
8
  const { defaultCompatBlock } = require('./compat');
9
9
  const { getBuildPaths } = require('./build/cache');
10
+ const { resolveSourceAuth } = require('./auth');
10
11
  const log = require('./logger');
11
12
 
12
13
  const WYVRNPM_VERSION = require('../package.json').version;
@@ -193,6 +194,7 @@ function resolveUploadDestination(argv, config) {
193
194
  let src = argv.uploadSource;
194
195
  let awsProfile = argv.awsProfile;
195
196
  let token = argv.token;
197
+ let sourceEntry = null;
196
198
 
197
199
  const publishSources = config.publishSources ?? [];
198
200
 
@@ -202,17 +204,24 @@ function resolveUploadDestination(argv, config) {
202
204
  if (named) {
203
205
  src = named.url;
204
206
  awsProfile = awsProfile ?? named.profile;
205
- token = token ?? named.token;
207
+ sourceEntry = named;
206
208
  log.info(`upload-built: using publish source "${named.name}" from config`);
207
209
  }
208
210
  } else if (publishSources.length > 0) {
209
211
  const first = publishSources[0];
210
212
  src = first.url;
211
213
  awsProfile = awsProfile ?? first.profile;
212
- token = token ?? first.token;
214
+ sourceEntry = first;
213
215
  log.info(`upload-built: using first configured publish source "${first.name}"`);
214
216
  }
215
217
 
218
+ // Fall back to the matched source entry's own token / tokenEnv only if
219
+ // the caller didn't pass one already (argv.token wins). resolveSourceAuth
220
+ // handles the literal-vs-env-backed precedence per side.
221
+ if (token === undefined || token === null) {
222
+ token = resolveSourceAuth({}, sourceEntry).token;
223
+ }
224
+
216
225
  if (!src) return null;
217
226
  return { uploadSource: src, uploadAuth: { awsProfile, token } };
218
227
  }
@@ -0,0 +1,52 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Defense-in-depth against Zip Slip (CVE-2018-1002200 family). Both
5
+ * node-stream-zip and adm-zip claim to handle this upstream, but we
6
+ * don't want to take the library's word for it on a supply-chain-
7
+ * critical code path. Pre-scan zip entry names before extraction and
8
+ * reject anything that could write outside the target directory.
9
+ *
10
+ * The ZIP spec uses forward slashes only, but Windows-produced archives
11
+ * sometimes leak backslashes — normalise both.
12
+ *
13
+ * @param {string} entryName zip-internal path as reported by the zip library
14
+ * @param {string} [context] optional archive identifier for the error message
15
+ * @throws {Error} if the entry name is absolute, contains a path-traversal
16
+ * segment, or starts with a Windows drive-letter prefix.
17
+ */
18
+ function assertSafeZipEntryName(entryName, context) {
19
+ const where = context ? ` in ${context}` : '';
20
+
21
+ if (/^[A-Za-z]:[\\/]/.test(entryName)) {
22
+ throw new Error(`unsafe zip entry${where}: drive-letter absolute path ${JSON.stringify(entryName)}`);
23
+ }
24
+ if (entryName.startsWith('/') || entryName.startsWith('\\')) {
25
+ throw new Error(`unsafe zip entry${where}: absolute path ${JSON.stringify(entryName)}`);
26
+ }
27
+
28
+ const segments = entryName.split(/[\\/]+/);
29
+ for (const seg of segments) {
30
+ if (seg === '..') {
31
+ throw new Error(`unsafe zip entry${where}: path-traversal segment in ${JSON.stringify(entryName)}`);
32
+ }
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Convenience: validate every name in an iterable. Throws on the first
38
+ * offender (fail-fast) rather than collecting all violations.
39
+ *
40
+ * @param {Iterable<string>} names
41
+ * @param {string} [context]
42
+ */
43
+ function assertAllSafeZipEntryNames(names, context) {
44
+ for (const name of names) {
45
+ assertSafeZipEntryName(name, context);
46
+ }
47
+ }
48
+
49
+ module.exports = {
50
+ assertSafeZipEntryName,
51
+ assertAllSafeZipEntryNames,
52
+ };