Skip to content

Commit 8e67656

Browse files
committed
Redact OTP values from argv logs
1 parent 99068a6 commit 8e67656

3 files changed

Lines changed: 58 additions & 1 deletion

File tree

lib/utils/clean-argv.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ const { redactLog: replaceInfo } = require('@npmcli/redact')
22
const { isProtected } = require('./protected-config.js')
33

44
const REDACTED = '***'
5+
const isProtectedArg = key => isProtected(key) || key === 'otp'
56

67
const cleanArgv = (argv) => {
78
const cleaned = replaceInfo(argv)
@@ -14,7 +15,7 @@ const cleanArgv = (argv) => {
1415
const raw = arg.slice(2)
1516
const equalsIndex = raw.indexOf('=')
1617
const key = equalsIndex === -1 ? raw : raw.slice(0, equalsIndex)
17-
if (!isProtected(key)) {
18+
if (!isProtectedArg(key)) {
1819
continue
1920
}
2021

test/lib/cli/entry.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ t.test('logged argv redacts protected config values', async t => {
115115
'--//registry.npmjs.org/:_authToken=plain-secret',
116116
'--_password',
117117
'hunter2',
118+
'--otp=123456',
118119
],
119120
},
120121
})
@@ -123,8 +124,10 @@ t.test('logged argv redacts protected config values', async t => {
123124
const argv = logs.verbose.byTitle('argv')[0]
124125
t.notMatch(argv, 'plain-secret')
125126
t.notMatch(argv, 'hunter2')
127+
t.notMatch(argv, '123456')
126128
t.match(argv, '"--//registry.npmjs.org/:_authToken" "***"')
127129
t.match(argv, '"--_password" "***"')
130+
t.match(argv, '"--otp" "***"')
128131
})
129132

130133
t.test('print usage if no params provided', async t => {

test/lib/utils/clean-argv.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
const t = require('tap')
2+
const { cleanArgv } = require('../../../lib/utils/clean-argv.js')
3+
4+
t.test('redacts protected config values', t => {
5+
t.strictSame(cleanArgv([
6+
'--password=secret',
7+
'--otp',
8+
'123456',
9+
'--//registry.npmjs.org/:_authToken',
10+
'plain-secret',
11+
'--registry',
12+
'https://user:pass@registry.npmjs.org',
13+
]), [
14+
'--password=***',
15+
'--otp',
16+
'***',
17+
'--//registry.npmjs.org/:_authToken',
18+
'***',
19+
'--registry',
20+
'https://user:***@registry.npmjs.org',
21+
])
22+
t.end()
23+
})
24+
25+
t.test('redacts protected config values with equals', t => {
26+
t.strictSame(cleanArgv([
27+
'--otp=123456',
28+
'--_authToken=plain-secret',
29+
'--//registry.npmjs.org/:_password=hunter2',
30+
]), [
31+
'--otp=***',
32+
'--_authToken=***',
33+
'--//registry.npmjs.org/:_password=***',
34+
])
35+
t.end()
36+
})
37+
38+
t.test('leaves non-protected config values intact', t => {
39+
t.strictSame(cleanArgv([
40+
'--registry',
41+
'https://registry.npmjs.org',
42+
'--auth-type',
43+
'legacy',
44+
'--scope=@npmcli',
45+
]), [
46+
'--registry',
47+
'https://registry.npmjs.org',
48+
'--auth-type',
49+
'legacy',
50+
'--scope=@npmcli',
51+
])
52+
t.end()
53+
})

0 commit comments

Comments
 (0)