fix(redact): keep the credential heuristics off ordinary files
Path layer: patterns now match with a right boundary (must not continue into [a-z0-9]) and list only store-plural forms (credentials/secrets/ passwords, not tokens), so tokenizer.ts / dev.environment.ts / style.keys.ts / api-tokens.md are no longer masked whole while .env.local / credentials.json / mytoken.yaml still are. Content layer: drop the bare key/auth/token/pass/bearer field names — they label far more ordinary content (keyboard keys, CSS custom properties, lexical tokens) than secrets; qualified names stay and Bearer schemes remain covered by BEARER_RE. Adds the over-masking regression cases; fixes the spec's source import extension to .ts (repo convention).
This commit is contained in:
+22
-1
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { isSensitivePath, redactContentText, redactText, REDACTED } from '../src/client/redact.js'
|
||||
import { isSensitivePath, redactContentText, redactText, REDACTED } from '../src/client/redact.ts'
|
||||
|
||||
describe('isSensitivePath', () => {
|
||||
it('marks credential-shaped filenames', () => {
|
||||
@@ -15,6 +15,17 @@ describe('isSensitivePath', () => {
|
||||
expect(isSensitivePath('docs/readme.md')).toBe(false)
|
||||
expect(isSensitivePath('package.json')).toBe(false)
|
||||
})
|
||||
it('does not mask files whose names merely CONTAIN a pattern inside a longer word', () => {
|
||||
expect(isSensitivePath('src/tokenizer.ts')).toBe(false)
|
||||
expect(isSensitivePath('config/dev.environment.ts')).toBe(false)
|
||||
expect(isSensitivePath('src/style.keys.ts')).toBe(false)
|
||||
expect(isSensitivePath('docs/api-tokens.md')).toBe(false)
|
||||
})
|
||||
it('still masks pattern matches at a word boundary', () => {
|
||||
expect(isSensitivePath('deploy/.env.local')).toBe(true)
|
||||
expect(isSensitivePath('app/mytoken.yaml')).toBe(true)
|
||||
expect(isSensitivePath('config/passwords.yml')).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('redactContentText', () => {
|
||||
@@ -43,6 +54,16 @@ describe('redactContentText', () => {
|
||||
const code = 'const x = 42\nconsole.log("count", x)'
|
||||
expect(redactContentText(code)).toBe(code)
|
||||
})
|
||||
it('leaves generic bare-word assignments alone (key/auth/token/pass label ordinary content too)', () => {
|
||||
expect(redactContentText("key: 'ArrowUp'")).toBe("key: 'ArrowUp'")
|
||||
expect(redactContentText('--key: red')).toBe('--key: red')
|
||||
expect(redactContentText('token: a lexical unit')).toBe('token: a lexical unit')
|
||||
expect(redactContentText('auth: none')).toBe('auth: none')
|
||||
})
|
||||
it('still masks qualified secret field names', () => {
|
||||
expect(redactContentText('access_token: ghp_abcdefghijklmnopqrst')).toBe('access_token: ' + REDACTED)
|
||||
expect(redactContentText('client_secret: shhh-1234567890')).toBe('client_secret: ' + REDACTED)
|
||||
})
|
||||
})
|
||||
|
||||
describe('redactText', () => {
|
||||
|
||||
Reference in New Issue
Block a user