Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deps updates to get to latest @npmcli/redact #7453

Merged
merged 6 commits into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions node_modules/@npmcli/redact/lib/deep-map.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
const deepMap = (input, handler = v => v, path = ['$'], seen = new Set([input])) => {
if (Array.isArray(input)) {
const result = []
for (let i = 0; i < input.length; i++) {
const element = input[i]
const elementPath = [...path, i]
if (element instanceof Object) {
if (!seen.has(element)) { // avoid getting stuck in circular reference
seen.add(element)
result.push(deepMap(handler(element, elementPath), handler, elementPath, seen))
}
} else {
result.push(handler(element, elementPath))
}
}
return result
}

if (input === null) {
return null
} else if (typeof input === 'object' || typeof input === 'function') {
const result = {}

if (input instanceof Error) {
// `name` property is not included in `Object.getOwnPropertyNames(error)`
result.errorType = input.name
}

for (const propertyName of Object.getOwnPropertyNames(input)) {
// skip logging internal properties
if (propertyName.startsWith('_')) {
continue
}

try {
const property = input[propertyName]
const propertyPath = [...path, propertyName]
if (property instanceof Object) {
if (!seen.has(property)) { // avoid getting stuck in circular reference
seen.add(property)
result[propertyName] = deepMap(
handler(property, propertyPath), handler, propertyPath, seen
)
}
} else {
result[propertyName] = handler(property, propertyPath)
}
} catch (err) {
// a getter may throw an error
result[propertyName] = `[error getting value: ${err.message}]`
}
}
return result
}

return handler(input, path)
}

module.exports = { deepMap }
25 changes: 5 additions & 20 deletions node_modules/@npmcli/redact/lib/index.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,15 @@
const { URL } = require('url')
const matchers = require('./matchers')
const { redactUrlPassword } = require('./utils')

const REPLACE = '***'
const TOKEN_REGEX = /\bnpm_[a-zA-Z0-9]{36}\b/g
const GUID_REGEX = /\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/g

const redact = (value) => {
if (typeof value !== 'string' || !value) {
return value
}

let urlValue
try {
urlValue = new URL(value)
} catch {
// If it's not a URL then we can ignore all errors
}

if (urlValue?.password) {
urlValue.password = REPLACE
value = urlValue.toString()
}

return value
.replace(TOKEN_REGEX, `npm_${REPLACE}`)
.replace(GUID_REGEX, REPLACE)
return redactUrlPassword(value, REPLACE)
.replace(matchers.NPM_SECRET.pattern, `npm_${REPLACE}`)
.replace(matchers.UUID.pattern, REPLACE)
}

// split on \s|= similar to how nopt parses options
Expand All @@ -49,7 +35,6 @@ const redactLog = (arg) => {
} else if (Array.isArray(arg)) {
return arg.map((a) => typeof a === 'string' ? splitAndRedact(a) : a)
}

return arg
}

Expand Down
81 changes: 81 additions & 0 deletions node_modules/@npmcli/redact/lib/matchers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
const TYPE_REGEX = 'regex'
const TYPE_URL = 'url'
const TYPE_PATH = 'path'

const NPM_SECRET = {
type: TYPE_REGEX,
pattern: /\b(npms?_)[a-zA-Z0-9]{36,48}\b/gi,
replacement: `[REDACTED_NPM_SECRET]`,
}

const AUTH_HEADER = {
type: TYPE_REGEX,
pattern: /\b(Basic\s+|Bearer\s+)[\w+=\-.]+\b/gi,
replacement: `[REDACTED_AUTH_HEADER]`,
}

const JSON_WEB_TOKEN = {
type: TYPE_REGEX,
pattern: /\b[A-Za-z0-9-_]{10,}(?!\.\d+\.)\.[A-Za-z0-9-_]{3,}\.[A-Za-z0-9-_]{20,}\b/gi,
replacement: `[REDACTED_JSON_WEB_TOKEN]`,
}

const UUID = {
type: TYPE_REGEX,
pattern: /\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/gi,
replacement: `[REDACTED_UUID]`,
}

const URL_MATCHER = {
type: TYPE_REGEX,
pattern: /(?:https?|ftp):\/\/[^\s/"$.?#].[^\s"]*/gi,
replacement: '[REDACTED_URL]',
}

const DEEP_HEADER_AUTHORIZATION = {
type: TYPE_PATH,
predicate: ({ path }) => path.endsWith('.headers.authorization'),
replacement: '[REDACTED_HEADER_AUTHORIZATION]',
}

const DEEP_HEADER_SET_COOKIE = {
type: TYPE_PATH,
predicate: ({ path }) => path.endsWith('.headers.set-cookie'),
replacement: '[REDACTED_HEADER_SET_COOKIE]',
}

const REWRITE_REQUEST = {
type: TYPE_PATH,
predicate: ({ path }) => path.endsWith('.request'),
replacement: (input) => ({
method: input?.method,
path: input?.path,
headers: input?.headers,
url: input?.url,
}),
}

const REWRITE_RESPONSE = {
type: TYPE_PATH,
predicate: ({ path }) => path.endsWith('.response'),
replacement: (input) => ({
data: input?.data,
status: input?.status,
headers: input?.headers,
}),
}

module.exports = {
TYPE_REGEX,
TYPE_URL,
TYPE_PATH,
NPM_SECRET,
AUTH_HEADER,
JSON_WEB_TOKEN,
UUID,
URL_MATCHER,
DEEP_HEADER_AUTHORIZATION,
DEEP_HEADER_SET_COOKIE,
REWRITE_REQUEST,
REWRITE_RESPONSE,
}
34 changes: 34 additions & 0 deletions node_modules/@npmcli/redact/lib/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
const {
AUTH_HEADER,
JSON_WEB_TOKEN,
NPM_SECRET,
DEEP_HEADER_AUTHORIZATION,
DEEP_HEADER_SET_COOKIE,
REWRITE_REQUEST,
REWRITE_RESPONSE,
} = require('./matchers')

const {
redactUrlMatcher,
redactUrlPasswordMatcher,
redactMatchers,
} = require('./utils')

const { deepMap } = require('./deep-map')

const _redact = redactMatchers(
NPM_SECRET,
AUTH_HEADER,
JSON_WEB_TOKEN,
DEEP_HEADER_AUTHORIZATION,
DEEP_HEADER_SET_COOKIE,
REWRITE_REQUEST,
REWRITE_RESPONSE,
redactUrlMatcher(
redactUrlPasswordMatcher()
)
)

const redact = (input) => deepMap(input, (value, path) => _redact(value, { path }))

module.exports = { redact }
Loading
Loading