Skip to content

Commit c54a060

Browse files
authored
fix: scrubbing more aggressively anything in the logs (#9182)
1 parent 7c7fd6c commit c54a060

File tree

5 files changed

+162
-7
lines changed

5 files changed

+162
-7
lines changed

.changeset/shaggy-garlics-joke.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"builder-util": patch
3+
---
4+
5+
fix: scrubbing more aggressively anything in the logs that MIGHT be password affiliated (handling spaces in secrets)

.github/workflows/test.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ jobs:
6767
fail-fast: false
6868
matrix:
6969
testFiles:
70-
- ArtifactPublisherTest,BuildTest,ExtraBuildTest,RepoSlugTest,binDownloadTest,configurationValidationTest,filenameUtilTest,filesTest,globTest,httpExecutorTest,ignoreTest,macroExpanderTest,mainEntryTest,urlUtilTest,extraMetadataTest,linuxArchiveTest,linuxPackagerTest,HoistedNodeModuleTest,MemoLazyTest,HoistTest,ExtraBuildResourcesTest
70+
- ArtifactPublisherTest,BuildTest,ExtraBuildTest,RepoSlugTest,binDownloadTest,configurationValidationTest,filenameUtilTest,filesTest,globTest,httpExecutorTest,ignoreTest,macroExpanderTest,mainEntryTest,urlUtilTest,extraMetadataTest,linuxArchiveTest,linuxPackagerTest,HoistedNodeModuleTest,MemoLazyTest,HoistTest,ExtraBuildResourcesTest,utilTest
7171
- snapTest,debTest,fpmTest,protonTest
7272
- winPackagerTest,winCodeSignTest,webInstallerTest
7373
- oneClickInstallerTest,assistedInstallerTest

packages/builder-util/src/util.ts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,29 @@ export function serializeToYaml(object: any, skipInvalid = false, noRefs = false
4242
})
4343
}
4444

45-
export function removePassword(input: string) {
46-
return input.replace(/(-String |-P |pass:| \/p |-pass |--secretKey |--accessKey |-p )([^ ]+)/g, (match, p1, p2) => {
47-
if (p1.trim() === "/p" && p2.startsWith("\\\\Mac\\Host\\\\")) {
48-
// appx /p
49-
return `${p1}${p2}`
45+
export function removePassword(input: string): string {
46+
const blockList = ["--accessKey", "--secretKey", "-P", "-p", "-pass", "-String", "/p", "pass:"]
47+
48+
// Create a regex pattern that supports:
49+
// - space-separated unquoted values: --key value
50+
// - quoted values: --key "value with spaces" or 'value with spaces'
51+
const blockPattern = new RegExp(`(${blockList.map(s => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|")})\\s*(?:(["'])(.*?)\\2|([^\\s]+))`, "g")
52+
53+
input = input.replace(blockPattern, (_match, prefix, quote, quotedVal, unquotedVal) => {
54+
const value = quotedVal ?? unquotedVal
55+
56+
if (prefix.trim() === "/p" && value.startsWith("\\\\Mac\\Host\\\\")) {
57+
return `${prefix} ${quote ?? ""}${value}${quote ?? ""}`
5058
}
51-
return `${p1}${createHash("sha256").update(p2).digest("hex")} (sha256 hash)`
59+
60+
const hashed = createHash("sha256").update(value).digest("hex")
61+
return `${prefix} ${quote ?? ""}${hashed} (sha256 hash)${quote ?? ""}`
62+
})
63+
64+
// Also handle `/b ... /c` block format
65+
return input.replace(/(\/b\s+)(.*?)(\s+\/c)/g, (_match, p1, p2, p3) => {
66+
const hashed = createHash("sha256").update(p2).digest("hex")
67+
return `${p1}${hashed} (sha256 hash)${p3}`
5268
})
5369
}
5470

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`removePassword: /b … /c block > handles /b … /c block (snapshot) 1`] = `"/b f2ef4a8a9ab5b2021260622b256a52005822ddb3de11985e382b6243166d3c60 (sha256 hash) /c"`;
4+
5+
exports[`removePassword: /p > handles Mac host path without hashing (snapshot) 1`] = `"/p 7692bad00279b4b3c87898de51da122d987a060f244ae38340bbf1b587c8d4c3 (sha256 hash)"`;
6+
7+
exports[`removePassword: /p > handles double-quoted value (snapshot) 1`] = `"/p "643dc0c1c3f4f28bd42a534af23ddea45ff9021a53c8d1cd88a01e2611ecf511 (sha256 hash)""`;
8+
9+
exports[`removePassword: /p > handles single-quoted value (snapshot) 1`] = `"/p '643dc0c1c3f4f28bd42a534af23ddea45ff9021a53c8d1cd88a01e2611ecf511 (sha256 hash)'"`;
10+
11+
exports[`removePassword: /p > handles unquoted value (snapshot) 1`] = `"/p 916925d896d4e9b97f81aab67a3f7f916b39135db74bf4cbf03d4c4b49a411e4 (sha256 hash)"`;
12+
13+
exports[`removePassword: --accessKey > handles double-quoted value (snapshot) 1`] = `"--accessKey "643dc0c1c3f4f28bd42a534af23ddea45ff9021a53c8d1cd88a01e2611ecf511 (sha256 hash)""`;
14+
15+
exports[`removePassword: --accessKey > handles single-quoted value (snapshot) 1`] = `"--accessKey '643dc0c1c3f4f28bd42a534af23ddea45ff9021a53c8d1cd88a01e2611ecf511 (sha256 hash)'"`;
16+
17+
exports[`removePassword: --accessKey > handles unquoted value (snapshot) 1`] = `"--accessKey 916925d896d4e9b97f81aab67a3f7f916b39135db74bf4cbf03d4c4b49a411e4 (sha256 hash)"`;
18+
19+
exports[`removePassword: --secretKey > handles double-quoted value (snapshot) 1`] = `"--secretKey "643dc0c1c3f4f28bd42a534af23ddea45ff9021a53c8d1cd88a01e2611ecf511 (sha256 hash)""`;
20+
21+
exports[`removePassword: --secretKey > handles single-quoted value (snapshot) 1`] = `"--secretKey '643dc0c1c3f4f28bd42a534af23ddea45ff9021a53c8d1cd88a01e2611ecf511 (sha256 hash)'"`;
22+
23+
exports[`removePassword: --secretKey > handles unquoted value (snapshot) 1`] = `"--secretKey 916925d896d4e9b97f81aab67a3f7f916b39135db74bf4cbf03d4c4b49a411e4 (sha256 hash)"`;
24+
25+
exports[`removePassword: -P > handles double-quoted value (snapshot) 1`] = `"-P "643dc0c1c3f4f28bd42a534af23ddea45ff9021a53c8d1cd88a01e2611ecf511 (sha256 hash)""`;
26+
27+
exports[`removePassword: -P > handles single-quoted value (snapshot) 1`] = `"-P '643dc0c1c3f4f28bd42a534af23ddea45ff9021a53c8d1cd88a01e2611ecf511 (sha256 hash)'"`;
28+
29+
exports[`removePassword: -P > handles unquoted value (snapshot) 1`] = `"-P 916925d896d4e9b97f81aab67a3f7f916b39135db74bf4cbf03d4c4b49a411e4 (sha256 hash)"`;
30+
31+
exports[`removePassword: -String > handles double-quoted value (snapshot) 1`] = `"-String "643dc0c1c3f4f28bd42a534af23ddea45ff9021a53c8d1cd88a01e2611ecf511 (sha256 hash)""`;
32+
33+
exports[`removePassword: -String > handles single-quoted value (snapshot) 1`] = `"-String '643dc0c1c3f4f28bd42a534af23ddea45ff9021a53c8d1cd88a01e2611ecf511 (sha256 hash)'"`;
34+
35+
exports[`removePassword: -String > handles unquoted value (snapshot) 1`] = `"-String 916925d896d4e9b97f81aab67a3f7f916b39135db74bf4cbf03d4c4b49a411e4 (sha256 hash)"`;
36+
37+
exports[`removePassword: -p > handles double-quoted value (snapshot) 1`] = `"-p "643dc0c1c3f4f28bd42a534af23ddea45ff9021a53c8d1cd88a01e2611ecf511 (sha256 hash)""`;
38+
39+
exports[`removePassword: -p > handles single-quoted value (snapshot) 1`] = `"-p '643dc0c1c3f4f28bd42a534af23ddea45ff9021a53c8d1cd88a01e2611ecf511 (sha256 hash)'"`;
40+
41+
exports[`removePassword: -p > handles unquoted value (snapshot) 1`] = `"-p 916925d896d4e9b97f81aab67a3f7f916b39135db74bf4cbf03d4c4b49a411e4 (sha256 hash)"`;
42+
43+
exports[`removePassword: -pass > handles double-quoted value (snapshot) 1`] = `"-p 2062f80093066633876b542212c496501a5e79523cc4ea9b28667dff065afd8f (sha256 hash) "secret with spaces""`;
44+
45+
exports[`removePassword: -pass > handles single-quoted value (snapshot) 1`] = `"-p 2062f80093066633876b542212c496501a5e79523cc4ea9b28667dff065afd8f (sha256 hash) 'secret with spaces'"`;
46+
47+
exports[`removePassword: -pass > handles unquoted value (snapshot) 1`] = `"-p 2062f80093066633876b542212c496501a5e79523cc4ea9b28667dff065afd8f (sha256 hash) secretValue"`;
48+
49+
exports[`removePassword: multiple keys in one string > handles mixed quoted and unquoted keys (snapshot) 1`] = `"-p '9014b632e87590ac0b58afc11dd044f17c7d5e3766e1b76275329450320f3ed6 (sha256 hash)' -p 2062f80093066633876b542212c496501a5e79523cc4ea9b28667dff065afd8f (sha256 hash) unquoted"`;
50+
51+
exports[`removePassword: multiple keys in one string > handles several keys and /b … /c block (snapshot) 1`] = `"pass: cc1d9c865e8380c2d566dc724c66369051acfaa3e9e8f36ad6c67d7d9b8461a5 (sha256 hash) --accessKey "3fafdea1e2907edbaf937e22a71a27217ddb22399f7558c57551bd60a466b1ed (sha256 hash)" /b 61403ebadd9d565f57fea9b275ab739c2f1e60072e6011e92ae82934eba43bda (sha256 hash) /c"`;
52+
53+
exports[`removePassword: multiple keys in one string > handles two keys unquoted (snapshot) 1`] = `"--accessKey 8174099687a26621f4e2cdd7cc03b3dacedb3fb962255b1aafd033cabe831530 (sha256 hash) --secretKey b10253764c8b233fb37542e23401c7b450e5a6f9751f3b5a014f6f67e8bc999d (sha256 hash)"`;
54+
55+
exports[`removePassword: pass: > handles double-quoted value (snapshot) 1`] = `"pass: "643dc0c1c3f4f28bd42a534af23ddea45ff9021a53c8d1cd88a01e2611ecf511 (sha256 hash)""`;
56+
57+
exports[`removePassword: pass: > handles single-quoted value (snapshot) 1`] = `"pass: '643dc0c1c3f4f28bd42a534af23ddea45ff9021a53c8d1cd88a01e2611ecf511 (sha256 hash)'"`;
58+
59+
exports[`removePassword: pass: > handles unquoted value (snapshot) 1`] = `"pass: 916925d896d4e9b97f81aab67a3f7f916b39135db74bf4cbf03d4c4b49a411e4 (sha256 hash)"`;

test/src/builder-util/utilTest.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { removePassword } from "builder-util"
2+
import { describe, it } from "vitest"
3+
4+
const testValue = "secretValue"
5+
const testQuoted = "secret with spaces"
6+
7+
const keys = ["--accessKey", "--secretKey", "-P", "-p", "-pass", "-String", "/p", "pass:"]
8+
9+
keys.forEach(key => {
10+
describe(`removePassword: ${key}`, () => {
11+
it("handles unquoted value (snapshot)", ({ expect }) => {
12+
const input = `${key} ${testValue}`
13+
const output = removePassword(input)
14+
15+
expect(output).toMatchSnapshot()
16+
})
17+
18+
it("handles double-quoted value (snapshot)", ({ expect }) => {
19+
const input = `${key} "${testQuoted}"`
20+
const output = removePassword(input)
21+
22+
expect(output).toMatchSnapshot()
23+
})
24+
25+
it("handles single-quoted value (snapshot)", ({ expect }) => {
26+
const input = `${key} '${testQuoted}'`
27+
const output = removePassword(input)
28+
29+
expect(output).toMatchSnapshot()
30+
})
31+
32+
if (key === "/p") {
33+
it("handles Mac host path without hashing (snapshot)", ({ expect }) => {
34+
const macPath = "\\\\Mac\\Host\\Users\\user"
35+
const input = `${key} ${macPath}`
36+
const output = removePassword(input)
37+
38+
expect(output).toMatchSnapshot()
39+
})
40+
}
41+
})
42+
})
43+
44+
describe("removePassword: /b … /c block", () => {
45+
it("handles /b … /c block (snapshot)", ({ expect }) => {
46+
const secret = "blockSecret"
47+
const input = `/b ${secret} /c`
48+
const output = removePassword(input)
49+
50+
expect(output).toMatchSnapshot()
51+
})
52+
})
53+
54+
describe("removePassword: multiple keys in one string", () => {
55+
it("handles two keys unquoted (snapshot)", ({ expect }) => {
56+
const input = `--accessKey key1 --secretKey key2`
57+
const output = removePassword(input)
58+
59+
expect(output).toMatchSnapshot()
60+
})
61+
62+
it("handles mixed quoted and unquoted keys (snapshot)", ({ expect }) => {
63+
const input = `-p 'quoted secret' -pass unquoted`
64+
const output = removePassword(input)
65+
66+
expect(output).toMatchSnapshot()
67+
})
68+
69+
it("handles several keys and /b … /c block (snapshot)", ({ expect }) => {
70+
const input = `pass: val1 --accessKey "val two" /b blockpass /c`
71+
const output = removePassword(input)
72+
73+
expect(output).toMatchSnapshot()
74+
})
75+
})

0 commit comments

Comments
 (0)