mirror of
https://github.com/pnpm/pnpm.git
synced 2025-12-24 23:58:07 -05:00
fix(error): hide auth token in FetchError (#8069)
This commit is contained in:
5
.changeset/funny-cups-yell.md
Normal file
5
.changeset/funny-cups-yell.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/error": patch
|
||||
---
|
||||
|
||||
Hide auth token in FetchError object [#8069](https://github.com/pnpm/pnpm/pull/8069).
|
||||
3
packages/error/jest.config.js
Normal file
3
packages/error/jest.config.js
Normal file
@@ -0,0 +1,3 @@
|
||||
const config = require('../../jest.config.js');
|
||||
|
||||
module.exports = Object.assign({}, config, {});
|
||||
@@ -12,8 +12,9 @@
|
||||
"node": ">=18.12"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint \"src/**/*.ts\"",
|
||||
"test": "pnpm run compile",
|
||||
"lint": "eslint \"src/**/*.ts\" \"test/**/*.ts\"",
|
||||
"_test": "jest",
|
||||
"test": "pnpm run compile && pnpm run _test",
|
||||
"prepublishOnly": "pnpm run compile",
|
||||
"compile": "tsc --build && pnpm run lint --fix"
|
||||
},
|
||||
|
||||
@@ -34,28 +34,35 @@ export class FetchError extends PnpmError {
|
||||
response: FetchErrorResponse,
|
||||
hint?: string
|
||||
) {
|
||||
const _request: FetchErrorRequest = {
|
||||
url: request.url,
|
||||
}
|
||||
if (request.authHeaderValue) {
|
||||
_request.authHeaderValue = hideAuthInformation(request.authHeaderValue)
|
||||
}
|
||||
const message = `GET ${request.url}: ${response.statusText} - ${response.status}`
|
||||
const authHeaderValue = request.authHeaderValue
|
||||
? hideAuthInformation(request.authHeaderValue)
|
||||
: undefined
|
||||
// NOTE: For security reasons, some registries respond with 404 on authentication errors as well.
|
||||
// So we print authorization info on 404 errors as well.
|
||||
if (response.status === 401 || response.status === 403 || response.status === 404) {
|
||||
hint = hint ? `${hint}\n\n` : ''
|
||||
if (authHeaderValue) {
|
||||
hint += `An authorization header was used: ${authHeaderValue}`
|
||||
if (_request.authHeaderValue) {
|
||||
hint += `An authorization header was used: ${_request.authHeaderValue}`
|
||||
} else {
|
||||
hint += 'No authorization header was set for the request.'
|
||||
}
|
||||
}
|
||||
super(`FETCH_${response.status}`, message, { hint })
|
||||
this.request = request
|
||||
this.request = _request
|
||||
this.response = response
|
||||
}
|
||||
}
|
||||
|
||||
function hideAuthInformation (authHeaderValue: string): string {
|
||||
const [authType, token] = authHeaderValue.split(' ')
|
||||
if (token == null) return '[hidden]'
|
||||
if (token.length < 20) {
|
||||
return `${authType} [hidden]`
|
||||
}
|
||||
return `${authType} ${token.substring(0, 4)}[hidden]`
|
||||
}
|
||||
|
||||
|
||||
31
packages/error/test/index.ts
Normal file
31
packages/error/test/index.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { FetchError } from '@pnpm/error'
|
||||
|
||||
test('FetchError escapes auth tokens', () => {
|
||||
const error = new FetchError(
|
||||
{ url: 'https://foo.com', authHeaderValue: 'Bearer 00000000000000000000' },
|
||||
{ status: 401, statusText: 'Unauthorized' }
|
||||
)
|
||||
expect(error.message).toBe('GET https://foo.com: Unauthorized - 401')
|
||||
expect(error.hint).toBe('An authorization header was used: Bearer 0000[hidden]')
|
||||
expect(error.request.authHeaderValue).toBe('Bearer 0000[hidden]')
|
||||
})
|
||||
|
||||
test('FetchError escapes short auth tokens', () => {
|
||||
const error = new FetchError(
|
||||
{ url: 'https://foo.com', authHeaderValue: 'Bearer 0000000000' },
|
||||
{ status: 401, statusText: 'Unauthorized' }
|
||||
)
|
||||
expect(error.message).toBe('GET https://foo.com: Unauthorized - 401')
|
||||
expect(error.hint).toBe('An authorization header was used: Bearer [hidden]')
|
||||
expect(error.request.authHeaderValue).toBe('Bearer [hidden]')
|
||||
})
|
||||
|
||||
test('FetchError escapes non-standard auth header', () => {
|
||||
const error = new FetchError(
|
||||
{ url: 'https://foo.com', authHeaderValue: '0000000000' },
|
||||
{ status: 401, statusText: 'Unauthorized' }
|
||||
)
|
||||
expect(error.message).toBe('GET https://foo.com: Unauthorized - 401')
|
||||
expect(error.hint).toBe('An authorization header was used: [hidden]')
|
||||
expect(error.request.authHeaderValue).toBe('[hidden]')
|
||||
})
|
||||
Reference in New Issue
Block a user