@vltpkg/types 1.0.1 → 1.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/dist/index.d.ts CHANGED
@@ -428,7 +428,7 @@ export declare const asManifest: (m: unknown, from?: (...a: unknown[]) => any) =
428
428
  * contains normalized author, bugs, funding, contributors, keywords and
429
429
  * version fields.
430
430
  */
431
- export declare const normalizeManifest: <T extends Manifest | ManifestRegistry>(manifest: T) => SomeNormalizedManifest<T>;
431
+ export declare const normalizeManifest: <T extends Manifest | ManifestRegistry>(manifest: T, from?: string) => SomeNormalizedManifest<T>;
432
432
  /**
433
433
  * Type guard to check if a value is a {@link NormalizedManifest}.
434
434
  */
package/dist/index.js CHANGED
@@ -1,5 +1,9 @@
1
1
  import { error } from '@vltpkg/error-cause';
2
2
  import { Version } from '@vltpkg/semver';
3
+ import { assertPathSafeName } from '@vltpkg/spec/browser';
4
+ import { posix } from 'node:path';
5
+ import { debuglog } from 'node:util';
6
+ const debug = debuglog('vlt');
3
7
  /**
4
8
  * Normalize a single funding entry to a consistent format.
5
9
  */
@@ -469,6 +473,37 @@ export const isNormalizedLibc = (o) => {
469
473
  !item.startsWith(' ') &&
470
474
  !item.endsWith(' ')));
471
475
  };
476
+ const unixify = (ref) => ref.replace(/[\\:]/g, '/');
477
+ /**
478
+ * Clamp a manifest-supplied relative path into the package dir. The result
479
+ * is always a `..`-free, non-absolute path, so resolving it under the
480
+ * package dir cannot escape. Returns `''` for `.`, `..` and `''`.
481
+ */
482
+ const secure = (ref) => {
483
+ const s = unixify(posix.join('.', posix.join('/', unixify(ref))));
484
+ return s === './' ? '' : s;
485
+ };
486
+ /**
487
+ * Clamp bin keys (which become path segments under `.bin/`) and bin values
488
+ * (resolved under the package dir) into safe relative paths.
489
+ */
490
+ const secureBinPaths = (bin) => {
491
+ const res = {};
492
+ for (const [key, val] of Object.entries(bin)) {
493
+ // types say string, but manifests are untrusted
494
+ const v = typeof val === 'string' ? secure(val) : '';
495
+ const k = posix.basename(secure(key));
496
+ if (!k || !v) {
497
+ debug('dropped unusable bin entry', key, val);
498
+ continue;
499
+ }
500
+ if (k !== key || v !== val) {
501
+ debug('rewrote unsafe bin entry', key, val, '->', k, v);
502
+ }
503
+ res[k] = v;
504
+ }
505
+ return res;
506
+ };
472
507
  /**
473
508
  * Normalizes the bin paths.
474
509
  */
@@ -477,10 +512,10 @@ export const normalizeBinPaths = (manifest) => {
477
512
  if (bin) {
478
513
  if (name && typeof bin === 'string') {
479
514
  const [_scope, pkg] = parseScope(name);
480
- return { [pkg]: bin };
515
+ return secureBinPaths({ [pkg]: bin });
481
516
  }
482
517
  else if (typeof bin === 'object') {
483
- return bin;
518
+ return secureBinPaths(bin);
484
519
  }
485
520
  }
486
521
  };
@@ -593,12 +628,16 @@ const normalizeManifestCache = new WeakMap();
593
628
  * contains normalized author, bugs, funding, contributors, keywords and
594
629
  * version fields.
595
630
  */
596
- export const normalizeManifest = (manifest) => {
631
+ export const normalizeManifest = (manifest, from) => {
597
632
  // Check cache first using manifest object reference
598
633
  const cached = normalizeManifestCache.get(manifest);
599
634
  if (cached) {
600
635
  return cached;
601
636
  }
637
+ // the single choke point every manifest passes through, from any source
638
+ if (manifest.name !== undefined) {
639
+ assertPathSafeName(manifest.name, from);
640
+ }
602
641
  manifest = fixManifestVersion(manifest);
603
642
  const normalizedAuthor = parsePerson(manifest.author);
604
643
  const normalizedFunding = normalizeFunding(manifest.funding);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vltpkg/types",
3
3
  "description": "definitions for some of vlt's core types",
4
- "version": "1.0.1",
4
+ "version": "1.0.2",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/vltpkg/vltpkg.git",
@@ -13,10 +13,10 @@
13
13
  "url": "http://vlt.sh"
14
14
  },
15
15
  "dependencies": {
16
- "@vltpkg/dep-id": "1.0.1",
17
- "@vltpkg/error-cause": "1.0.1",
18
- "@vltpkg/semver": "1.0.1",
19
- "@vltpkg/spec": "1.0.1"
16
+ "@vltpkg/dep-id": "1.0.2",
17
+ "@vltpkg/error-cause": "1.0.2",
18
+ "@vltpkg/semver": "1.0.2",
19
+ "@vltpkg/spec": "1.0.2"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@eslint/js": "^9.39.1",