Skip to content

Commit cd000a0

Browse files
committed
Fix powered up mask-secrets deaultRules!
1 parent e2b95d0 commit cd000a0

2 files changed

Lines changed: 84 additions & 9 deletions

File tree

internal/secrets/mod.go

Lines changed: 72 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,21 +72,84 @@ type ValueMaskRule struct {
7272
}
7373

7474
func defaultValueMaskRule() *ValueMaskRule {
75-
pat := `(?i)(\b(?:secret|password|passwd|pass|pw|token|api[_\-]?key|access[_\-]?key|private[_\-]?key)\b)(\s*)([=:\-])(\s*)(['"]?)([^\s'"]+)(['"]?)`
75+
pat := `(?i)(\b[A-Za-z0-9_\-\$]*(?:secret|password|passwd|pass|pw|token|api[_\-]?key|access[_\-]?key|private[_\-]?key)\b)\s*(:=|==|\|\||&&|=|:|\-)\s*(['"]?)`
7676
return &ValueMaskRule{
7777
KeyPattern: regexp.MustCompile(pat),
7878
}
7979
}
8080

8181
func (r *ValueMaskRule) MaskLine(line string) string {
82-
return r.KeyPattern.ReplaceAllStringFunc(line, func(s string) string {
83-
sub := r.KeyPattern.FindStringSubmatch(s)
84-
if len(sub) >= 8 {
85-
// [1]=key, [2]=space_before, [3]=delim, [4]=space_after, [5]=quote, [6]=value, [7]=quote
86-
return fmt.Sprintf("%s%s%s%s%s*****MASKED*****%s", sub[1], sub[2], sub[3], sub[4], sub[5], sub[7])
82+
result := ""
83+
rest := line
84+
for {
85+
m := r.KeyPattern.FindStringSubmatchIndex(rest)
86+
if m == nil {
87+
result += rest
88+
break
8789
}
88-
return s
89-
})
90+
// m[0] = full match start, m[1] = full match end,
91+
// m[2]=key start, m[3]=key end, m[4]=delimiter start,
92+
// m[5]=delimiter end, m[6]=quote start, m[7]=quote end
93+
94+
// 1. llways output the part after the previous match up to the key (commas, spaces, etc. can be entered here)
95+
result += rest[:m[2]]
96+
97+
// 2. print key, separator, leading space, and opening quote
98+
result += rest[m[2]:m[6]]
99+
quote := ""
100+
if m[6] != -1 && m[7] != -1 {
101+
quote = rest[m[6]:m[7]]
102+
result += quote
103+
}
104+
105+
maskedValue := "*****MASKED*****"
106+
valStart := m[7] // starting index of the value body (immediately after the quote)
107+
val := rest[valStart:]
108+
109+
if quote == `"` || quote == `'` {
110+
//With quotes: up to closing quote
111+
runes := []rune(val)
112+
escaped := false
113+
closingIdx := -1
114+
for i := range len(runes) {
115+
c := runes[i]
116+
if escaped {
117+
escaped = false
118+
continue
119+
}
120+
if c == '\\' {
121+
escaped = true
122+
continue
123+
}
124+
if string(c) == quote {
125+
closingIdx = i
126+
break
127+
}
128+
}
129+
result += maskedValue
130+
if closingIdx != -1 {
131+
result += quote
132+
valStart += len(string(runes[:closingIdx+1]))
133+
} else {
134+
valStart += len(val)
135+
}
136+
} else {
137+
// no quoted
138+
end := len(val)
139+
for i, c := range val {
140+
if c == ',' || c == ';' || c == ' ' {
141+
end = i
142+
break
143+
}
144+
}
145+
result += maskedValue
146+
valStart += end
147+
}
148+
149+
// remainder is rest.
150+
rest = rest[valStart:]
151+
}
152+
return result
90153
}
91154

92155
type RuleSet struct {
@@ -131,7 +194,7 @@ func (r *RuleSet) AddValueMaskKey(keywordList []string) {
131194
}
132195
keyword := strings.Join(quoted, "|")
133196
// e.g. (?i)(secret|password|api_key)\s*([=:\-])\s*(['"]?)([^\s'"]+)(['"]?)
134-
pat := fmt.Sprintf(`(?i)(%s)\s*([=:\-])\s*(['"]?)([^\s'"]+)(['"]?)`, keyword)
197+
pat := fmt.Sprintf(`(?i)(%s)\s*([=:\-])\s*(['"]?)([^'"]+)(['"]?)`, keyword)
135198
r.ValueMaskRules = append(r.ValueMaskRules, &ValueMaskRule{
136199
KeyPattern: regexp.MustCompile(pat),
137200
})

internal/secrets/mod_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,15 +96,27 @@ func TestMaskAll(t *testing.T) {
9696
hogehoge
9797
-----END ENCRYPTED PRIVATE KEY-----
9898
secret = "hogehoge"
99+
1secret := "hogehoge"
100+
2secret = "hoge\'\"hoge"
101+
3secret = num[0], secret = pass
99102
token: abcdefg
103+
token == abcdefg
104+
token || abcdefg
105+
token && abcdefg
100106
AWS_ACCESS_KEY_ID=AKIA1234567890ABCDEF
101107
normal = value
102108
normal_hoge = "ghp_abcdefghijklmnopqrstuvwxyz0123456789abcd"
103109
`
104110
want := `
105111
*****MASKED*****
106112
secret = "*****MASKED*****"
113+
1secret := "*****MASKED*****"
114+
2secret = "*****MASKED*****"
115+
3secret = *****MASKED*****, secret = *****MASKED*****
107116
token: *****MASKED*****
117+
token == *****MASKED*****
118+
token || *****MASKED*****
119+
token && *****MASKED*****
108120
AWS_ACCESS_KEY_ID=*****MASKED*****
109121
normal = value
110122
normal_hoge = "*****MASKED*****"

0 commit comments

Comments
 (0)