Skip to content

Commit 17d97d2

Browse files
committed
fix: use @npmcli/redact for log redactions
Closes #7314
1 parent 5469614 commit 17d97d2

16 files changed

+149
-155
lines changed

DEPENDENCIES.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ graph LR;
127127
npm-->npmcli-mock-registry["@npmcli/mock-registry"];
128128
npm-->npmcli-package-json["@npmcli/package-json"];
129129
npm-->npmcli-promise-spawn["@npmcli/promise-spawn"];
130+
npm-->npmcli-redact["@npmcli/redact"];
130131
npm-->npmcli-run-script["@npmcli/run-script"];
131132
npm-->npmcli-smoke-tests["@npmcli/smoke-tests"];
132133
npm-->npmcli-template-oss["@npmcli/template-oss"];
@@ -541,6 +542,7 @@ graph LR;
541542
npm-->npmcli-mock-registry["@npmcli/mock-registry"];
542543
npm-->npmcli-package-json["@npmcli/package-json"];
543544
npm-->npmcli-promise-spawn["@npmcli/promise-spawn"];
545+
npm-->npmcli-redact["@npmcli/redact"];
544546
npm-->npmcli-run-script["@npmcli/run-script"];
545547
npm-->npmcli-smoke-tests["@npmcli/smoke-tests"];
546548
npm-->npmcli-template-oss["@npmcli/template-oss"];
@@ -831,4 +833,4 @@ packages higher up the chain.
831833
- @npmcli/git, make-fetch-happen, @npmcli/config
832834
- @npmcli/installed-package-contents, @npmcli/map-workspaces, cacache, npm-pick-manifest, read-package-json, promzard
833835
- @npmcli/docs, @npmcli/fs, npm-bundled, read-package-json-fast, unique-filename, npm-install-checks, npm-package-arg, normalize-package-data, npm-packlist, bin-links, nopt, npmlog, parse-conflict-json, @npmcli/mock-globals, read
834-
- @npmcli/eslint-config, @npmcli/template-oss, ignore-walk, semver, npm-normalize-package-bin, @npmcli/name-from-folder, json-parse-even-better-errors, fs-minipass, ssri, unique-slug, @npmcli/promise-spawn, hosted-git-info, proc-log, validate-npm-package-name, @npmcli/node-gyp, @npmcli/agent, minipass-fetch, @npmcli/query, cmd-shim, read-cmd-shim, write-file-atomic, abbrev, are-we-there-yet, gauge, minify-registry-metadata, ini, @npmcli/disparity-colors, mute-stream, npm-audit-report, npm-user-validate
836+
- @npmcli/eslint-config, @npmcli/template-oss, ignore-walk, semver, npm-normalize-package-bin, @npmcli/name-from-folder, json-parse-even-better-errors, fs-minipass, ssri, unique-slug, @npmcli/promise-spawn, hosted-git-info, proc-log, validate-npm-package-name, @npmcli/node-gyp, @npmcli/agent, minipass-fetch, @npmcli/query, cmd-shim, read-cmd-shim, write-file-atomic, abbrev, are-we-there-yet, gauge, minify-registry-metadata, ini, @npmcli/disparity-colors, mute-stream, @npmcli/redact, npm-audit-report, npm-user-validate

lib/commands/adduser.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const log = require('../utils/log-shim.js')
2-
const replaceInfo = require('../utils/replace-info.js')
2+
const { redactLog: replaceInfo } = require('@npmcli/redact')
33
const auth = require('../utils/auth.js')
44

55
const BaseCommand = require('../base-command.js')

lib/commands/login.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const log = require('../utils/log-shim.js')
2-
const replaceInfo = require('../utils/replace-info.js')
2+
const { redactLog: replaceInfo } = require('@npmcli/redact')
33
const auth = require('../utils/auth.js')
44

55
const BaseCommand = require('../base-command.js')

lib/commands/publish.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const runScript = require('@npmcli/run-script')
66
const pacote = require('pacote')
77
const npa = require('npm-package-arg')
88
const npmFetch = require('npm-registry-fetch')
9-
const replaceInfo = require('../utils/replace-info.js')
9+
const { redactLog: replaceInfo } = require('@npmcli/redact')
1010

1111
const otplease = require('../utils/otplease.js')
1212
const { getContents, logTar } = require('../utils/tar.js')

lib/npm.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const LogFile = require('./utils/log-file.js')
1212
const Timers = require('./utils/timers.js')
1313
const Display = require('./utils/display.js')
1414
const log = require('./utils/log-shim')
15-
const replaceInfo = require('./utils/replace-info.js')
15+
const { redactLog: replaceInfo } = require('@npmcli/redact')
1616
const updateNotifier = require('./utils/update-notifier.js')
1717
const pkg = require('../package.json')
1818
const { deref } = require('./utils/cmd-list.js')

lib/utils/audit-error.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const log = require('./log-shim')
2-
const replaceInfo = require('./replace-info.js')
2+
const { redactLog: replaceInfo } = require('@npmcli/redact')
33

44
// print an error or just nothing if the audit report has an error
55
// this is called by the audit command, and by the reify-output util

lib/utils/error-message.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const { format } = require('util')
22
const { resolve } = require('path')
33
const nameValidator = require('validate-npm-package-name')
4-
const replaceInfo = require('./replace-info.js')
4+
const { redactLog: replaceInfo } = require('@npmcli/redact')
55
const { report } = require('./explain-eresolve.js')
66
const log = require('./log-shim')
77

lib/utils/exit-handler.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ const fs = require('fs')
33

44
const log = require('./log-shim.js')
55
const errorMessage = require('./error-message.js')
6-
const replaceInfo = require('./replace-info.js')
6+
const { redactLog: replaceInfo } = require('@npmcli/redact')
77

88
let npm = null // set by the cli
99
let exitHandlerCalled = false

lib/utils/replace-info.js

-31
This file was deleted.

node_modules/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
!/@npmcli/package-json
3434
!/@npmcli/promise-spawn
3535
!/@npmcli/query
36+
!/@npmcli/redact
3637
!/@npmcli/run-script
3738
!/@pkgjs/
3839
/@pkgjs/*

node_modules/@npmcli/redact/LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 npm
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
const { URL } = require('url')
2+
3+
const REPLACE = '***'
4+
const TOKEN_REGEX = /\bnpm_[a-zA-Z0-9]{36}\b/g
5+
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
6+
7+
const redact = (value) => {
8+
if (typeof value !== 'string' || !value) {
9+
return value
10+
}
11+
12+
let urlValue
13+
try {
14+
urlValue = new URL(value)
15+
} catch {
16+
// If it's not a URL then we can ignore all errors
17+
}
18+
19+
if (urlValue?.password) {
20+
urlValue.password = REPLACE
21+
value = urlValue.toString()
22+
}
23+
24+
return value
25+
.replace(TOKEN_REGEX, `npm_${REPLACE}`)
26+
.replace(GUID_REGEX, REPLACE)
27+
}
28+
29+
// split on \s|= similar to how nopt parses options
30+
const splitAndRedact = (str) => {
31+
// stateful regex, don't move out of this scope
32+
const splitChars = /[\s=]/g
33+
34+
let match = null
35+
let result = ''
36+
let index = 0
37+
while (match = splitChars.exec(str)) {
38+
result += redact(str.slice(index, match.index)) + match[0]
39+
index = splitChars.lastIndex
40+
}
41+
42+
return result + redact(str.slice(index))
43+
}
44+
45+
// replaces auth info in an array of arguments or in a strings
46+
const redactLog = (arg) => {
47+
if (typeof arg === 'string') {
48+
return splitAndRedact(arg)
49+
} else if (Array.isArray(arg)) {
50+
return arg.map((a) => typeof a === 'string' ? splitAndRedact(a) : a)
51+
}
52+
53+
return arg
54+
}
55+
56+
module.exports = {
57+
redact,
58+
redactLog,
59+
}
+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"name": "@npmcli/redact",
3+
"version": "1.1.0",
4+
"description": "Redact sensitive npm information from output",
5+
"main": "lib/index.js",
6+
"scripts": {
7+
"test": "tap",
8+
"lint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"",
9+
"postlint": "template-oss-check",
10+
"template-oss-apply": "template-oss-apply --force",
11+
"lintfix": "npm run lint -- --fix",
12+
"snap": "tap",
13+
"posttest": "npm run lint"
14+
},
15+
"keywords": [],
16+
"author": "GitHub Inc.",
17+
"license": "ISC",
18+
"files": [
19+
"bin/",
20+
"lib/"
21+
],
22+
"repository": {
23+
"type": "git",
24+
"url": "https://github.com/npm/redact.git"
25+
},
26+
"templateOSS": {
27+
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
28+
"version": "4.21.3",
29+
"publish": true
30+
},
31+
"tap": {
32+
"nyc-arg": [
33+
"--exclude",
34+
"tap-snapshots/**"
35+
]
36+
},
37+
"devDependencies": {
38+
"@npmcli/eslint-config": "^4.0.2",
39+
"@npmcli/template-oss": "4.21.3",
40+
"tap": "^16.3.10"
41+
},
42+
"engines": {
43+
"node": "^16.14.0 || >=18.0.0"
44+
}
45+
}

package-lock.json

+11
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"@npmcli/map-workspaces",
1616
"@npmcli/package-json",
1717
"@npmcli/promise-spawn",
18+
"@npmcli/redact",
1819
"@npmcli/run-script",
1920
"@sigstore/tuf",
2021
"abbrev",
@@ -95,6 +96,7 @@
9596
"@npmcli/map-workspaces": "^3.0.4",
9697
"@npmcli/package-json": "^5.0.0",
9798
"@npmcli/promise-spawn": "^7.0.1",
99+
"@npmcli/redact": "^1.1.0",
98100
"@npmcli/run-script": "^7.0.4",
99101
"@sigstore/tuf": "^2.3.2",
100102
"abbrev": "^2.0.0",
@@ -1904,6 +1906,15 @@
19041906
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
19051907
}
19061908
},
1909+
"node_modules/@npmcli/redact": {
1910+
"version": "1.1.0",
1911+
"resolved": "https://registry.npmjs.org/@npmcli/redact/-/redact-1.1.0.tgz",
1912+
"integrity": "sha512-PfnWuOkQgu7gCbnSsAisaX7hKOdZ4wSAhAzH3/ph5dSGau52kCRrMMGbiSQLwyTZpgldkZ49b0brkOr1AzGBHQ==",
1913+
"inBundle": true,
1914+
"engines": {
1915+
"node": "^16.14.0 || >=18.0.0"
1916+
}
1917+
},
19071918
"node_modules/@npmcli/run-script": {
19081919
"version": "7.0.4",
19091920
"resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-7.0.4.tgz",

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
"@npmcli/map-workspaces": "^3.0.4",
5959
"@npmcli/package-json": "^5.0.0",
6060
"@npmcli/promise-spawn": "^7.0.1",
61+
"@npmcli/redact": "^1.1.0",
6162
"@npmcli/run-script": "^7.0.4",
6263
"@sigstore/tuf": "^2.3.2",
6364
"abbrev": "^2.0.0",
@@ -130,6 +131,7 @@
130131
"@npmcli/map-workspaces",
131132
"@npmcli/package-json",
132133
"@npmcli/promise-spawn",
134+
"@npmcli/redact",
133135
"@npmcli/run-script",
134136
"@sigstore/tuf",
135137
"abbrev",

0 commit comments

Comments
 (0)