Skip to content

Commit db62910

Browse files
authoredMay 10, 2024··
fix(config): be more aggressive about hiding protected values (#7504)
Err on the side of not displaying things even if they're not valid config
1 parent bdd2aae commit db62910

File tree

3 files changed

+214
-169
lines changed

3 files changed

+214
-169
lines changed
 

Diff for: ‎lib/commands/config.js

+34-5
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,33 @@ const { log, output } = require('proc-log')
99
const BaseCommand = require('../base-cmd.js')
1010

1111
// These are the configs that we can nerf-dart. Not all of them currently even
12-
// *have* config definitions so we have to explicitly validate them here
12+
// *have* config definitions so we have to explicitly validate them here.
13+
// This is used to validate during "npm config set"
1314
const nerfDarts = [
1415
'_auth',
1516
'_authToken',
16-
'username',
1717
'_password',
18+
'certfile',
1819
'email',
20+
'keyfile',
21+
'username',
22+
]
23+
// These are the config values to swap with "protected". It does not catch
24+
// every single sensitive thing a user may put in the npmrc file but it gets
25+
// the common ones. This is distinct from nerfDarts because that is used to
26+
// validate valid configs during "npm config set", and folks may have old
27+
// invalid entries lying around in a config file that we still want to protect
28+
// when running "npm config list"
29+
// This is a more general list of values to consider protected. You can not
30+
// "npm config get" them, and they will not display during "npm config list"
31+
const protected = [
32+
'auth',
33+
'authToken',
1934
'certfile',
35+
'email',
2036
'keyfile',
37+
'password',
38+
'username',
2139
]
2240

2341
// take an array of `[key, value, k2=v2, k3, v3, ...]` and turn into
@@ -40,10 +58,21 @@ const publicVar = k => {
4058
if (k.startsWith('_')) {
4159
return false
4260
}
43-
// //localhost:8080/:_password
44-
if (k.startsWith('//') && k.includes(':_')) {
61+
if (protected.includes(k)) {
4562
return false
4663
}
64+
// //localhost:8080/:_password
65+
if (k.startsWith('//')) {
66+
if (k.includes(':_')) {
67+
return false
68+
}
69+
// //registry:_authToken or //registry:authToken
70+
for (const p of protected) {
71+
if (k.endsWith(`:${p}`) || k.endsWith(`:_${p}`)) {
72+
return false
73+
}
74+
}
75+
}
4776
return true
4877
}
4978

@@ -320,7 +349,7 @@ ${defData}
320349
const src = this.npm.config.find(k)
321350
const overridden = src !== where
322351
msg.push((overridden ? '; ' : '') +
323-
`${k} = ${v} ${overridden ? `; overridden by ${src}` : ''}`)
352+
`${k} = ${v}${overridden ? ` ; overridden by ${src}` : ''}`)
324353
}
325354
msg.push('')
326355
}

Diff for: ‎tap-snapshots/test/lib/commands/config.js.test.cjs

+167-163
Original file line numberDiff line numberDiff line change
@@ -173,198 +173,202 @@ exports[`test/lib/commands/config.js TAP config list --json > output matches sna
173173
exports[`test/lib/commands/config.js TAP config list --long > output matches snapshot 1`] = `
174174
; "default" config from default values
175175
176-
_auth = (protected)
177-
access = null
178-
all = false
179-
allow-same-version = false
180-
also = null
181-
audit = true
182-
audit-level = null
183-
auth-type = "web"
184-
before = null
185-
bin-links = true
186-
browser = null
187-
ca = null
176+
_auth = (protected)
177+
access = null
178+
all = false
179+
allow-same-version = false
180+
also = null
181+
audit = true
182+
audit-level = null
183+
auth-type = "web"
184+
before = null
185+
bin-links = true
186+
browser = null
187+
ca = null
188188
; cache = "{CACHE}" ; overridden by cli
189-
cache-max = null
190-
cache-min = 0
191-
cafile = null
192-
call = ""
193-
cert = null
194-
cidr = null
189+
cache-max = null
190+
cache-min = 0
191+
cafile = null
192+
call = ""
193+
cert = null
194+
cidr = null
195195
; color = {COLOR}
196-
commit-hooks = true
197-
cpu = null
198-
depth = null
199-
description = true
200-
dev = false
201-
diff = []
202-
diff-dst-prefix = "b/"
203-
diff-ignore-all-space = false
204-
diff-name-only = false
205-
diff-no-prefix = false
206-
diff-src-prefix = "a/"
207-
diff-text = false
208-
diff-unified = 3
209-
dry-run = false
210-
editor = "{EDITOR}"
211-
engine-strict = false
212-
expect-result-count = null
213-
expect-results = null
214-
fetch-retries = 2
215-
fetch-retry-factor = 10
216-
fetch-retry-maxtimeout = 60000
217-
fetch-retry-mintimeout = 10000
218-
fetch-timeout = 300000
219-
force = false
220-
foreground-scripts = false
221-
format-package-lock = true
222-
fund = true
223-
git = "git"
224-
git-tag-version = true
225-
global = false
226-
global-style = false
227-
globalconfig = "{CWD}/global/etc/npmrc"
228-
heading = "npm"
229-
https-proxy = null
230-
if-present = false
231-
ignore-scripts = false
232-
include = []
233-
include-staged = false
234-
include-workspace-root = false
235-
init-author-email = ""
236-
init-author-name = ""
237-
init-author-url = ""
238-
init-license = "ISC"
239-
init-module = "{CWD}/home/.npm-init.js"
240-
init-version = "1.0.0"
241-
init.author.email = ""
242-
init.author.name = ""
243-
init.author.url = ""
244-
init.license = "ISC"
245-
init.module = "{CWD}/home/.npm-init.js"
246-
init.version = "1.0.0"
247-
install-links = false
248-
install-strategy = "hoisted"
249-
json = false
250-
key = null
251-
legacy-bundling = false
252-
legacy-peer-deps = false
253-
libc = null
254-
link = false
255-
local-address = null
256-
location = "user"
257-
lockfile-version = null
258-
loglevel = "notice"
259-
logs-dir = null
260-
logs-max = 10
196+
commit-hooks = true
197+
cpu = null
198+
depth = null
199+
description = true
200+
dev = false
201+
diff = []
202+
diff-dst-prefix = "b/"
203+
diff-ignore-all-space = false
204+
diff-name-only = false
205+
diff-no-prefix = false
206+
diff-src-prefix = "a/"
207+
diff-text = false
208+
diff-unified = 3
209+
dry-run = false
210+
editor = "{EDITOR}"
211+
engine-strict = false
212+
expect-result-count = null
213+
expect-results = null
214+
fetch-retries = 2
215+
fetch-retry-factor = 10
216+
fetch-retry-maxtimeout = 60000
217+
fetch-retry-mintimeout = 10000
218+
fetch-timeout = 300000
219+
force = false
220+
foreground-scripts = false
221+
format-package-lock = true
222+
fund = true
223+
git = "git"
224+
git-tag-version = true
225+
global = false
226+
global-style = false
227+
globalconfig = "{CWD}/global/etc/npmrc"
228+
heading = "npm"
229+
https-proxy = null
230+
if-present = false
231+
ignore-scripts = false
232+
include = []
233+
include-staged = false
234+
include-workspace-root = false
235+
init-author-email = ""
236+
init-author-name = ""
237+
init-author-url = ""
238+
init-license = "ISC"
239+
init-module = "{CWD}/home/.npm-init.js"
240+
init-version = "1.0.0"
241+
init.author.email = ""
242+
init.author.name = ""
243+
init.author.url = ""
244+
init.license = "ISC"
245+
init.module = "{CWD}/home/.npm-init.js"
246+
init.version = "1.0.0"
247+
install-links = false
248+
install-strategy = "hoisted"
249+
json = false
250+
key = null
251+
legacy-bundling = false
252+
legacy-peer-deps = false
253+
libc = null
254+
link = false
255+
local-address = null
256+
location = "user"
257+
lockfile-version = null
258+
loglevel = "notice"
259+
logs-dir = null
260+
logs-max = 10
261261
; long = false ; overridden by cli
262-
maxsockets = 15
263-
message = "%s"
264-
node-options = null
265-
noproxy = [""]
266-
npm-version = "{NPM-VERSION}"
267-
offline = false
268-
omit = []
269-
omit-lockfile-registry-resolved = false
270-
only = null
271-
optional = null
272-
os = null
273-
otp = null
274-
pack-destination = "."
275-
package = []
276-
package-lock = true
277-
package-lock-only = false
278-
parseable = false
279-
prefer-dedupe = false
280-
prefer-offline = false
281-
prefer-online = false
282-
prefix = "{CWD}/global"
283-
preid = ""
284-
production = null
262+
maxsockets = 15
263+
message = "%s"
264+
node-options = null
265+
noproxy = [""]
266+
npm-version = "{NPM-VERSION}"
267+
offline = false
268+
omit = []
269+
omit-lockfile-registry-resolved = false
270+
only = null
271+
optional = null
272+
os = null
273+
otp = null
274+
pack-destination = "."
275+
package = []
276+
package-lock = true
277+
package-lock-only = false
278+
parseable = false
279+
prefer-dedupe = false
280+
prefer-offline = false
281+
prefer-online = false
282+
prefix = "{CWD}/global"
283+
preid = ""
284+
production = null
285285
progress = {PROGRESS}
286-
provenance = false
287-
provenance-file = null
288-
proxy = null
289-
read-only = false
290-
rebuild-bundle = true
291-
registry = "https://registry.npmjs.org/"
292-
replace-registry-host = "npmjs"
293-
save = true
294-
save-bundle = false
295-
save-dev = false
296-
save-exact = false
297-
save-optional = false
298-
save-peer = false
299-
save-prefix = "^"
300-
save-prod = false
301-
sbom-format = null
302-
sbom-type = "library"
303-
scope = ""
304-
script-shell = null
305-
searchexclude = ""
306-
searchlimit = 20
307-
searchopts = ""
308-
searchstaleness = 900
309-
shell = "{SHELL}"
310-
shrinkwrap = true
311-
sign-git-commit = false
312-
sign-git-tag = false
313-
strict-peer-deps = false
314-
strict-ssl = true
315-
tag = "latest"
316-
tag-version-prefix = "v"
317-
timing = false
318-
umask = 0
319-
unicode = false
320-
update-notifier = true
321-
usage = false
322-
user-agent = "npm/{npm-version} node/{node-version} {platform} {arch} workspaces/{workspaces} {ci}"
323-
userconfig = "{CWD}/home/.npmrc"
324-
version = false
325-
versions = false
326-
viewer = "{VIEWER}"
327-
which = null
328-
workspace = []
329-
workspaces = null
330-
workspaces-update = true
331-
yes = null
286+
provenance = false
287+
provenance-file = null
288+
proxy = null
289+
read-only = false
290+
rebuild-bundle = true
291+
registry = "https://registry.npmjs.org/"
292+
replace-registry-host = "npmjs"
293+
save = true
294+
save-bundle = false
295+
save-dev = false
296+
save-exact = false
297+
save-optional = false
298+
save-peer = false
299+
save-prefix = "^"
300+
save-prod = false
301+
sbom-format = null
302+
sbom-type = "library"
303+
scope = ""
304+
script-shell = null
305+
searchexclude = ""
306+
searchlimit = 20
307+
searchopts = ""
308+
searchstaleness = 900
309+
shell = "{SHELL}"
310+
shrinkwrap = true
311+
sign-git-commit = false
312+
sign-git-tag = false
313+
strict-peer-deps = false
314+
strict-ssl = true
315+
tag = "latest"
316+
tag-version-prefix = "v"
317+
timing = false
318+
umask = 0
319+
unicode = false
320+
update-notifier = true
321+
usage = false
322+
user-agent = "npm/{npm-version} node/{node-version} {platform} {arch} workspaces/{workspaces} {ci}"
323+
userconfig = "{CWD}/home/.npmrc"
324+
version = false
325+
versions = false
326+
viewer = "{VIEWER}"
327+
which = null
328+
workspace = []
329+
workspaces = null
330+
workspaces-update = true
331+
yes = null
332332
333333
; "global" config from {CWD}/global/etc/npmrc
334334
335-
globalloaded = "yes"
335+
globalloaded = "yes"
336336
337337
; "user" config from {CWD}/home/.npmrc
338338
339-
userloaded = "yes"
339+
userloaded = "yes"
340340
341341
; "project" config from {CWD}/prefix/.npmrc
342342
343-
projectloaded = "yes"
343+
projectloaded = "yes"
344344
345345
; "cli" config from command line options
346346
347-
cache = "{CACHE}"
347+
cache = "{CACHE}"
348348
color = {COLOR}
349349
long = true
350350
`
351351

352352
exports[`test/lib/commands/config.js TAP config list > output matches snapshot 1`] = `
353353
; "global" config from {CWD}/global/etc/npmrc
354354
355-
globalloaded = "yes"
355+
globalloaded = "yes"
356356
357357
; "user" config from {CWD}/home/.npmrc
358358
359-
userloaded = "yes"
359+
_auth = (protected)
360+
//nerfdart:_auth = (protected)
361+
//nerfdart:auth = (protected)
362+
auth = (protected)
363+
userloaded = "yes"
360364
361365
; "project" config from {CWD}/prefix/.npmrc
362366
363-
projectloaded = "yes"
367+
projectloaded = "yes"
364368
365369
; "cli" config from command line options
366370
367-
cache = "{CACHE}"
371+
cache = "{CACHE}"
368372
color = {COLOR}
369373
370374
; node bin location = {NODE-BIN-LOCATION}
@@ -379,9 +383,9 @@ color = {COLOR}
379383
exports[`test/lib/commands/config.js TAP config list with publishConfig global > output matches snapshot 1`] = `
380384
; "cli" config from command line options
381385
382-
cache = "{CACHE}"
386+
cache = "{CACHE}"
383387
color = {COLOR}
384-
global = true
388+
global = true
385389
386390
; node bin location = {NODE-BIN-LOCATION}
387391
; node version = {NODE-VERSION}
@@ -395,7 +399,7 @@ global = true
395399
exports[`test/lib/commands/config.js TAP config list with publishConfig local > output matches snapshot 1`] = `
396400
; "cli" config from command line options
397401
398-
cache = "{CACHE}"
402+
cache = "{CACHE}"
399403
color = {COLOR}
400404
401405
; node bin location = {NODE-BIN-LOCATION}

Diff for: ‎test/lib/commands/config.js

+13-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,13 @@ t.test('config list', async t => {
8080
},
8181
},
8282
homeDir: {
83-
'.npmrc': 'userloaded=yes',
83+
'.npmrc': [
84+
'userloaded=yes',
85+
'auth=bad',
86+
'_auth=bad',
87+
'//nerfdart:auth=bad',
88+
'//nerfdart:_auth=bad',
89+
].join('\n'),
8490
},
8591
})
8692

@@ -486,6 +492,12 @@ t.test('config get private key', async t => {
486492
'rejects with protected string'
487493
)
488494

495+
await t.rejects(
496+
npm.exec('config', ['get', 'authToken']),
497+
/authToken option is protected/,
498+
'rejects with protected string'
499+
)
500+
489501
await t.rejects(
490502
npm.exec('config', ['get', '//localhost:8080/:_password']),
491503
/_password option is protected/,

0 commit comments

Comments
 (0)
Please sign in to comment.