Skip to content

Commit

Permalink
Changes to partial masking rules
Browse files Browse the repository at this point in the history
  • Loading branch information
romain-gaillard committed Jan 2, 2025
1 parent c27fb75 commit 7fb2246
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 14 deletions.
13 changes: 9 additions & 4 deletions internal/component/loki/secretfilter/secretfilter.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,15 +238,20 @@ func (c *Component) redactLine(line string, secret string, ruleName string) stri
redactWith = strings.ReplaceAll(redactWith, "$SECRET_HASH", hashSecret(secret))
}

// If partialMask is set, show the first N characters of the secret
partialMask := int(c.args.PartialMask)
if partialMask < 0 {
partialMask = 0
}
if partialMask > 0 {
// Don't apply partial masking if the secret is too short
if len(secret) >= 3 && len(secret) >= partialMask*2 {
redactWith = secret[:partialMask] + redactWith
runesSecret := []rune(secret)
// Only do it if the secret is long enough
if partialMask > 0 && len(runesSecret) >= 6 {
// Show at most half of the secret
if partialMask > len(runesSecret)/2 {
partialMask = len(runesSecret) / 2
}
prefix := string(runesSecret[:partialMask])
redactWith = prefix + redactWith
}

line = strings.ReplaceAll(line, secret, redactWith)
Expand Down
37 changes: 27 additions & 10 deletions internal/component/loki/secretfilter/secretfilter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -396,9 +396,13 @@ func TestPartialMasking(t *testing.T) {
require.Equal(t, "This is a very short secret <REDACTED-SECRET:test-rule> in a log line", redacted)

// Too short to be partially masked
redacted = component.redactLine("This is a short secret abc123 in a log line", "abc123", "test-rule")
redacted = component.redactLine("This is a short secret abc12 in a log line", "abc12", "test-rule")
require.Equal(t, "This is a short secret <REDACTED-SECRET:test-rule> in a log line", redacted)

// Will be partially masked (limited by secret length)
redacted = component.redactLine("This is a longer secret abc123 in a log line", "abc123", "test-rule")
require.Equal(t, "This is a longer secret abc<REDACTED-SECRET:test-rule> in a log line", redacted)

// Will be partially masked
redacted = component.redactLine("This is a long enough secret abcd1234 in a log line", "abcd1234", "test-rule")
require.Equal(t, "This is a long enough secret abcd<REDACTED-SECRET:test-rule> in a log line", redacted)
Expand All @@ -407,31 +411,44 @@ func TestPartialMasking(t *testing.T) {
redacted = component.redactLine("This is the longest secret abcdef12345678 in a log line", "abcdef12345678", "test-rule")
require.Equal(t, "This is the longest secret abcd<REDACTED-SECRET:test-rule> in a log line", redacted)

// Test with a non-ASCII character
redacted = component.redactLine("This is a line with a complex secret aBc\U0001f512De\U0001f5124 in a log line", "aBc\U0001f512De\U0001f5124", "test-rule")
require.Equal(t, "This is a line with a complex secret aBc\U0001f512<REDACTED-SECRET:test-rule> in a log line", redacted)

// Test with different secret lengths and partial masking values
for _, partialMasking := range []int{1, 2, 3, 4, 5, 9} {
for secretLength := range 30 {
for partialMasking := range 20 {
for secretLength := range 50 {
if secretLength < 2 {
continue
}
expected := secretLength >= 3 && secretLength >= partialMasking*2
checkPartialMasking(t, partialMasking, secretLength, expected)
expectedPrefixLength := 0
if secretLength >= 6 {
expectedPrefixLength = min(secretLength/2, partialMasking)
}
checkPartialMasking(t, partialMasking, secretLength, expectedPrefixLength)
}
}
}

func checkPartialMasking(t *testing.T, partialMasking int, secretLength int, partialRedactionExpected bool) {
func checkPartialMasking(t *testing.T, partialMasking int, secretLength int, expectedPrefixLength int) {
component := &Component{}
component.args = Arguments{PartialMask: uint(partialMasking)}
secret := strings.Repeat("A", secretLength)
inputLog := fmt.Sprintf("This is a test with a secret %s in a log line", secret)
redacted := component.redactLine(inputLog, secret, "test-rule")

prefix := ""
if partialRedactionExpected {
prefix = strings.Repeat("A", partialMasking)
}
// Test with a simple ASCII character
prefix := strings.Repeat("A", expectedPrefixLength)
expectedLog := fmt.Sprintf("This is a test with a secret %s<REDACTED-SECRET:test-rule> in a log line", prefix)
require.Equal(t, expectedLog, redacted)

// Test with a non-ASCII character
secret = strings.Repeat("\U0001f512", secretLength)
inputLog = fmt.Sprintf("This is a test with a secret %s in a log line", secret)
redacted = component.redactLine(inputLog, secret, "test-rule")
prefix = strings.Repeat("\U0001f512", expectedPrefixLength)
expectedLog = fmt.Sprintf("This is a test with a secret %s<REDACTED-SECRET:test-rule> in a log line", prefix)
require.Equal(t, expectedLog, redacted)
}

func runTest(t *testing.T, config string, gitLeaksConfigContent string, inputLog string, expectedLog string) {
Expand Down

0 comments on commit 7fb2246

Please sign in to comment.