Deployed the page to Github Pages.
This commit is contained in:
parent
1d79754e93
commit
2c89899458
62797 changed files with 6551425 additions and 15279 deletions
21
node_modules/@npmcli/redact/LICENSE
generated
vendored
Normal file
21
node_modules/@npmcli/redact/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2024 npm
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
42
node_modules/@npmcli/redact/README.md
generated
vendored
Normal file
42
node_modules/@npmcli/redact/README.md
generated
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
# @npmcli/redact
|
||||
|
||||
Redact sensitive npm information from output.
|
||||
|
||||
## API
|
||||
|
||||
This will redact `npm_` prefixed tokens and UUIDs from values.
|
||||
|
||||
It will also replace passwords in stringified URLs.
|
||||
|
||||
### `redact(string)`
|
||||
|
||||
Redact values from a single value
|
||||
|
||||
```js
|
||||
const { redact } = require('@npmcli/redact')
|
||||
|
||||
redact('https://user:pass@registry.npmjs.org/')
|
||||
// https://user:***@registry.npmjs.org/
|
||||
|
||||
redact(`https://registry.npmjs.org/path/npm_${'a'.repeat('36')}`)
|
||||
// https://registry.npmjs.org/path/npm_***
|
||||
```
|
||||
|
||||
### `redactLog(string | string[])`
|
||||
|
||||
Redact values from a string or array of strings.
|
||||
|
||||
This method will also split all strings on `\s` and `=` and iterate over them.
|
||||
|
||||
```js
|
||||
const { redactLog } = require('@npmcli/redact')
|
||||
|
||||
redactLog([
|
||||
'Something --x=https://user:pass@registry.npmjs.org/ foo bar',
|
||||
'--url=http://foo:bar@registry.npmjs.org',
|
||||
])
|
||||
// [
|
||||
// 'Something --x=https://user:***@registry.npmjs.org/ foo bar',
|
||||
// '--url=http://foo:***@registry.npmjs.org/',
|
||||
// ]
|
||||
```
|
78
node_modules/@npmcli/redact/lib/deep-map.js
generated
vendored
Normal file
78
node_modules/@npmcli/redact/lib/deep-map.js
generated
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
function filterError (input) {
|
||||
return {
|
||||
errorType: input.name,
|
||||
message: input.message,
|
||||
stack: input.stack,
|
||||
...(input.code ? { code: input.code } : {}),
|
||||
...(input.statusCode ? { statusCode: input.statusCode } : {}),
|
||||
}
|
||||
}
|
||||
|
||||
const deepMap = (input, handler = v => v, path = ['$'], seen = new Set([input])) => {
|
||||
// this is in an effort to maintain bole's error logging behavior
|
||||
if (path.join('.') === '$' && input instanceof Error) {
|
||||
return deepMap({ err: filterError(input) }, handler, path, seen)
|
||||
}
|
||||
if (input instanceof Error) {
|
||||
return deepMap(filterError(input), handler, path, seen)
|
||||
}
|
||||
if (input instanceof Buffer) {
|
||||
return `[unable to log instanceof buffer]`
|
||||
}
|
||||
if (input instanceof Uint8Array) {
|
||||
return `[unable to log instanceof Uint8Array]`
|
||||
}
|
||||
|
||||
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 = {}
|
||||
|
||||
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 }
|
44
node_modules/@npmcli/redact/lib/index.js
generated
vendored
Normal file
44
node_modules/@npmcli/redact/lib/index.js
generated
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
const matchers = require('./matchers')
|
||||
const { redactUrlPassword } = require('./utils')
|
||||
|
||||
const REPLACE = '***'
|
||||
|
||||
const redact = (value) => {
|
||||
if (typeof value !== 'string' || !value) {
|
||||
return value
|
||||
}
|
||||
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
|
||||
const splitAndRedact = (str) => {
|
||||
// stateful regex, don't move out of this scope
|
||||
const splitChars = /[\s=]/g
|
||||
|
||||
let match = null
|
||||
let result = ''
|
||||
let index = 0
|
||||
while (match = splitChars.exec(str)) {
|
||||
result += redact(str.slice(index, match.index)) + match[0]
|
||||
index = splitChars.lastIndex
|
||||
}
|
||||
|
||||
return result + redact(str.slice(index))
|
||||
}
|
||||
|
||||
// replaces auth info in an array of arguments or in a strings
|
||||
const redactLog = (arg) => {
|
||||
if (typeof arg === 'string') {
|
||||
return splitAndRedact(arg)
|
||||
} else if (Array.isArray(arg)) {
|
||||
return arg.map((a) => typeof a === 'string' ? splitAndRedact(a) : a)
|
||||
}
|
||||
return arg
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
redact,
|
||||
redactLog,
|
||||
}
|
81
node_modules/@npmcli/redact/lib/matchers.js
generated
vendored
Normal file
81
node_modules/@npmcli/redact/lib/matchers.js
generated
vendored
Normal file
|
@ -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
node_modules/@npmcli/redact/lib/server.js
generated
vendored
Normal file
34
node_modules/@npmcli/redact/lib/server.js
generated
vendored
Normal file
|
@ -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 }
|
202
node_modules/@npmcli/redact/lib/utils.js
generated
vendored
Normal file
202
node_modules/@npmcli/redact/lib/utils.js
generated
vendored
Normal file
|
@ -0,0 +1,202 @@
|
|||
const {
|
||||
URL_MATCHER,
|
||||
TYPE_URL,
|
||||
TYPE_REGEX,
|
||||
TYPE_PATH,
|
||||
} = require('./matchers')
|
||||
|
||||
/**
|
||||
* creates a string of asterisks,
|
||||
* this forces a minimum asterisk for security purposes
|
||||
*/
|
||||
const asterisk = (length = 0) => {
|
||||
length = typeof length === 'string' ? length.length : length
|
||||
if (length < 8) {
|
||||
return '*'.repeat(8)
|
||||
}
|
||||
return '*'.repeat(length)
|
||||
}
|
||||
|
||||
/**
|
||||
* escapes all special regex chars
|
||||
* @see https://stackoverflow.com/a/9310752
|
||||
* @see https://github.com/tc39/proposal-regex-escaping
|
||||
*/
|
||||
const escapeRegExp = (text) => {
|
||||
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, `\\$&`)
|
||||
}
|
||||
|
||||
/**
|
||||
* provieds a regex "or" of the url versions of a string
|
||||
*/
|
||||
const urlEncodeRegexGroup = (value) => {
|
||||
const decoded = decodeURIComponent(value)
|
||||
const encoded = encodeURIComponent(value)
|
||||
const union = [...new Set([encoded, decoded, value])].map(escapeRegExp).join('|')
|
||||
return union
|
||||
}
|
||||
|
||||
/**
|
||||
* a tagged template literal that returns a regex ensures all variables are excaped
|
||||
*/
|
||||
const urlEncodeRegexTag = (strings, ...values) => {
|
||||
let pattern = ''
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
pattern += strings[i] + `(${urlEncodeRegexGroup(values[i])})`
|
||||
}
|
||||
pattern += strings[strings.length - 1]
|
||||
return new RegExp(pattern)
|
||||
}
|
||||
|
||||
/**
|
||||
* creates a matcher for redacting url hostname
|
||||
*/
|
||||
const redactUrlHostnameMatcher = ({ hostname, replacement } = {}) => ({
|
||||
type: TYPE_URL,
|
||||
predicate: ({ url }) => url.hostname === hostname,
|
||||
pattern: ({ url }) => {
|
||||
return urlEncodeRegexTag`(^${url.protocol}//${url.username}:.+@)?${url.hostname}`
|
||||
},
|
||||
replacement: `$1${replacement || asterisk()}`,
|
||||
})
|
||||
|
||||
/**
|
||||
* creates a matcher for redacting url search / query parameter values
|
||||
*/
|
||||
const redactUrlSearchParamsMatcher = ({ param, replacement } = {}) => ({
|
||||
type: TYPE_URL,
|
||||
predicate: ({ url }) => url.searchParams.has(param),
|
||||
pattern: ({ url }) => urlEncodeRegexTag`(${param}=)${url.searchParams.get(param)}`,
|
||||
replacement: `$1${replacement || asterisk()}`,
|
||||
})
|
||||
|
||||
/** creates a matcher for redacting the url password */
|
||||
const redactUrlPasswordMatcher = ({ replacement } = {}) => ({
|
||||
type: TYPE_URL,
|
||||
predicate: ({ url }) => url.password,
|
||||
pattern: ({ url }) => urlEncodeRegexTag`(^${url.protocol}//${url.username}:)${url.password}`,
|
||||
replacement: `$1${replacement || asterisk()}`,
|
||||
})
|
||||
|
||||
const redactUrlReplacement = (...matchers) => (subValue) => {
|
||||
try {
|
||||
const url = new URL(subValue)
|
||||
return redactMatchers(...matchers)(subValue, { url })
|
||||
} catch (err) {
|
||||
return subValue
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* creates a matcher / submatcher for urls, this function allows you to first
|
||||
* collect all urls within a larger string and then pass those urls to a
|
||||
* submatcher
|
||||
*
|
||||
* @example
|
||||
* console.log("this will first match all urls, then pass those urls to the password patcher")
|
||||
* redactMatchers(redactUrlMatcher(redactUrlPasswordMatcher()))
|
||||
*
|
||||
* @example
|
||||
* console.log(
|
||||
* "this will assume you are passing in a string that is a url, and will redact the password"
|
||||
* )
|
||||
* redactMatchers(redactUrlPasswordMatcher())
|
||||
*
|
||||
*/
|
||||
const redactUrlMatcher = (...matchers) => {
|
||||
return {
|
||||
...URL_MATCHER,
|
||||
replacement: redactUrlReplacement(...matchers),
|
||||
}
|
||||
}
|
||||
|
||||
const matcherFunctions = {
|
||||
[TYPE_REGEX]: (matcher) => (value) => {
|
||||
if (typeof value === 'string') {
|
||||
value = value.replace(matcher.pattern, matcher.replacement)
|
||||
}
|
||||
return value
|
||||
},
|
||||
[TYPE_URL]: (matcher) => (value, ctx) => {
|
||||
if (typeof value === 'string') {
|
||||
try {
|
||||
const url = ctx?.url || new URL(value)
|
||||
const { predicate, pattern } = matcher
|
||||
const predicateValue = predicate({ url })
|
||||
if (predicateValue) {
|
||||
value = value.replace(pattern({ url }), matcher.replacement)
|
||||
}
|
||||
} catch (_e) {
|
||||
return value
|
||||
}
|
||||
}
|
||||
return value
|
||||
},
|
||||
[TYPE_PATH]: (matcher) => (value, ctx) => {
|
||||
const rawPath = ctx?.path
|
||||
const path = rawPath.join('.').toLowerCase()
|
||||
const { predicate, replacement } = matcher
|
||||
const replace = typeof replacement === 'function' ? replacement : () => replacement
|
||||
const shouldRun = predicate({ rawPath, path })
|
||||
if (shouldRun) {
|
||||
value = replace(value, { rawPath, path })
|
||||
}
|
||||
return value
|
||||
},
|
||||
}
|
||||
|
||||
/** converts a matcher to a function */
|
||||
const redactMatcher = (matcher) => {
|
||||
return matcherFunctions[matcher.type](matcher)
|
||||
}
|
||||
|
||||
/** converts a series of matchers to a function */
|
||||
const redactMatchers = (...matchers) => (value, ctx) => {
|
||||
const flatMatchers = matchers.flat()
|
||||
return flatMatchers.reduce((result, matcher) => {
|
||||
const fn = (typeof matcher === 'function') ? matcher : redactMatcher(matcher)
|
||||
return fn(result, ctx)
|
||||
}, value)
|
||||
}
|
||||
|
||||
/**
|
||||
* replacement handler, keeping $1 (if it exists) and replacing the
|
||||
* rest of the string with asterisks, maintaining string length
|
||||
*/
|
||||
const redactDynamicReplacement = () => (value, start) => {
|
||||
if (typeof start === 'number') {
|
||||
return asterisk(value)
|
||||
}
|
||||
return start + asterisk(value.substring(start.length).length)
|
||||
}
|
||||
|
||||
/**
|
||||
* replacement handler, keeping $1 (if it exists) and replacing the
|
||||
* rest of the string with a fixed number of asterisks
|
||||
*/
|
||||
const redactFixedReplacement = (length) => (_value, start) => {
|
||||
if (typeof start === 'number') {
|
||||
return asterisk(length)
|
||||
}
|
||||
return start + asterisk(length)
|
||||
}
|
||||
|
||||
const redactUrlPassword = (value, replacement) => {
|
||||
return redactMatchers(redactUrlPasswordMatcher({ replacement }))(value)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
asterisk,
|
||||
escapeRegExp,
|
||||
urlEncodeRegexGroup,
|
||||
urlEncodeRegexTag,
|
||||
redactUrlHostnameMatcher,
|
||||
redactUrlSearchParamsMatcher,
|
||||
redactUrlPasswordMatcher,
|
||||
redactUrlMatcher,
|
||||
redactUrlReplacement,
|
||||
redactDynamicReplacement,
|
||||
redactFixedReplacement,
|
||||
redactMatchers,
|
||||
redactUrlPassword,
|
||||
}
|
51
node_modules/@npmcli/redact/package.json
generated
vendored
Normal file
51
node_modules/@npmcli/redact/package.json
generated
vendored
Normal file
|
@ -0,0 +1,51 @@
|
|||
{
|
||||
"name": "@npmcli/redact",
|
||||
"version": "2.0.1",
|
||||
"description": "Redact sensitive npm information from output",
|
||||
"main": "lib/index.js",
|
||||
"exports": {
|
||||
".": "./lib/index.js",
|
||||
"./server": "./lib/server.js",
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "tap",
|
||||
"lint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"",
|
||||
"postlint": "template-oss-check",
|
||||
"template-oss-apply": "template-oss-apply --force",
|
||||
"lintfix": "npm run lint -- --fix",
|
||||
"snap": "tap",
|
||||
"posttest": "npm run lint"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "GitHub Inc.",
|
||||
"license": "ISC",
|
||||
"files": [
|
||||
"bin/",
|
||||
"lib/"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/npm/redact.git"
|
||||
},
|
||||
"templateOSS": {
|
||||
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
|
||||
"version": "4.21.3",
|
||||
"publish": true
|
||||
},
|
||||
"tap": {
|
||||
"nyc-arg": [
|
||||
"--exclude",
|
||||
"tap-snapshots/**"
|
||||
],
|
||||
"timeout": 120
|
||||
},
|
||||
"devDependencies": {
|
||||
"@npmcli/eslint-config": "^4.0.2",
|
||||
"@npmcli/template-oss": "4.21.3",
|
||||
"tap": "^16.3.10"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.14.0 || >=18.0.0"
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue