@pnpm/error 1100.2.1 → 1100.2.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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # @pnpm/error
2
2
 
3
+ ## 1100.2.2
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies:
8
+ - @pnpm/constants@1102.0.1
9
+
3
10
  ## 1100.2.1
4
11
 
5
12
  ### Patch Changes
package/lib/index.d.ts CHANGED
@@ -38,6 +38,19 @@ export declare class FetchTimeoutError extends PnpmError {
38
38
  cause: unknown;
39
39
  });
40
40
  }
41
+ /**
42
+ * Strip `user:pass@` (or `user@`) userinfo that follows a URL scheme in any
43
+ * text, e.g. `GET https://user:pass@host/pkg: ...` → `GET https://host/pkg: ...`.
44
+ * A registry configured as `https://user:pass@host/` would otherwise leak its
45
+ * embedded basic-auth credentials into every error message that interpolates
46
+ * the request URL (terminal output, CI logs). `FetchError` already hides the
47
+ * auth *header*; this covers credentials carried in the URL itself.
48
+ *
49
+ * Implemented as a single forward scan rather than a regex: `text` is
50
+ * uncontrolled (it interpolates the request URL), so a backtracking pattern is
51
+ * a ReDoS vector, and the scan strips up to the **last** `@` in the authority
52
+ * so a raw `@` inside the password (`user:p@ss@host`) doesn't leak its tail.
53
+ */
41
54
  export declare function redactUrlCredentials(text: string): string;
42
55
  /**
43
56
  * Make untrusted, URL-bearing text safe to print or log: redact inline
package/lib/index.js CHANGED
@@ -68,19 +68,6 @@ export class FetchTimeoutError extends PnpmError {
68
68
  });
69
69
  }
70
70
  }
71
- /**
72
- * Strip `user:pass@` (or `user@`) userinfo that follows a URL scheme in any
73
- * text, e.g. `GET https://user:pass@host/pkg: …` → `GET https://host/pkg: …`.
74
- * A registry configured as `https://user:pass@host/` would otherwise leak its
75
- * embedded basic-auth credentials into every error message that interpolates
76
- * the request URL (terminal output, CI logs). `FetchError` already hides the
77
- * auth *header*; this covers credentials carried in the URL itself.
78
- *
79
- * Implemented as a single forward scan rather than a regex: `text` is
80
- * uncontrolled (it interpolates the request URL), so a backtracking pattern is
81
- * a ReDoS vector, and the scan strips up to the **last** `@` in the authority
82
- * so a raw `@` inside the password (`user:p@ss@host`) doesn't leak its tail.
83
- */
84
71
  /**
85
72
  * A request URL made safe to print: its `user:pass@` userinfo and control
86
73
  * characters redacted ({@link redactAndSanitize}), then everything from the
@@ -107,6 +94,19 @@ function redactUrlSecrets(url) {
107
94
  return '[hidden]';
108
95
  return sanitized.split(/[?#]/)[0];
109
96
  }
97
+ /**
98
+ * Strip `user:pass@` (or `user@`) userinfo that follows a URL scheme in any
99
+ * text, e.g. `GET https://user:pass@host/pkg: ...` → `GET https://host/pkg: ...`.
100
+ * A registry configured as `https://user:pass@host/` would otherwise leak its
101
+ * embedded basic-auth credentials into every error message that interpolates
102
+ * the request URL (terminal output, CI logs). `FetchError` already hides the
103
+ * auth *header*; this covers credentials carried in the URL itself.
104
+ *
105
+ * Implemented as a single forward scan rather than a regex: `text` is
106
+ * uncontrolled (it interpolates the request URL), so a backtracking pattern is
107
+ * a ReDoS vector, and the scan strips up to the **last** `@` in the authority
108
+ * so a raw `@` inside the password (`user:p@ss@host`) doesn't leak its tail.
109
+ */
110
110
  export function redactUrlCredentials(text) {
111
111
  let result = '';
112
112
  let cursor = 0;
@@ -122,21 +122,23 @@ export function redactUrlCredentials(text) {
122
122
  // bare `://` in the text is left untouched.
123
123
  if (schemeSep === 0 || !isSchemeTailChar(text.charCodeAt(schemeSep - 1)))
124
124
  continue;
125
- // Userinfo runs to the last `@` within the authority, which itself ends at
126
- // the first `/`, `?`, `#`, or whitespace.
127
- let lastAt = -1;
128
- for (let i = authorityStart; i < text.length; i++) {
129
- const code = text.charCodeAt(i);
130
- if (code === 0x2f || code === 0x3f || code === 0x23 || isAsciiWhitespace(code))
131
- break;
132
- if (code === 0x40)
133
- lastAt = i;
134
- }
135
- if (lastAt !== -1)
136
- cursor = lastAt + 1;
125
+ const userinfoEnd = findAuthorityUserinfoEnd(text, authorityStart);
126
+ if (userinfoEnd !== -1)
127
+ cursor = userinfoEnd;
137
128
  }
138
129
  return result;
139
130
  }
131
+ function findAuthorityUserinfoEnd(text, authorityStart) {
132
+ let lastAt = -1;
133
+ for (let index = authorityStart; index < text.length; index++) {
134
+ const code = text.charCodeAt(index);
135
+ if (code === 0x2f || code === 0x3f || code === 0x23 || isAsciiWhitespace(code))
136
+ break;
137
+ if (code === 0x40)
138
+ lastAt = index;
139
+ }
140
+ return lastAt === -1 ? -1 : lastAt + 1;
141
+ }
140
142
  /**
141
143
  * Make untrusted, URL-bearing text safe to print or log: redact inline
142
144
  * `user:pass@` credentials ({@link redactUrlCredentials}) and strip every
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pnpm/error",
3
- "version": "1100.2.1",
3
+ "version": "1100.2.2",
4
4
  "description": "An error class for pnpm errors",
5
5
  "keywords": [
6
6
  "pnpm",
@@ -28,11 +28,11 @@
28
28
  "!*.map"
29
29
  ],
30
30
  "dependencies": {
31
- "@pnpm/constants": "1102.0.0"
31
+ "@pnpm/constants": "1102.0.1"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@jest/globals": "30.4.1",
35
- "@pnpm/error": "1100.2.1"
35
+ "@pnpm/error": "1100.2.2"
36
36
  },
37
37
  "engines": {
38
38
  "node": ">=22.13"