Skip to content

Commit 016cdf1

Browse files
authored
fix: false warning for secret detector (#487)
* fix: false warning for secret detector * chore: removed comments
1 parent 6a33006 commit 016cdf1

3 files changed

Lines changed: 48 additions & 0 deletions

File tree

.changeset/chilly-windows-tease.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'dotenv-diff': patch
3+
---
4+
5+
fix secret detector false warnings

packages/cli/src/core/security/secretDetectors.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,22 @@ function characterClassCount(v: string): number {
292292
return count;
293293
}
294294

295+
/**
296+
* Checks if a value is a delimited identifier — lowercase words/numbers joined by
297+
* `-`, `_`, or `.` (e.g. `secret-rotation-v2-rotate-secrets`, `inject-k8s-sa-auth-token`).
298+
*
299+
* These kebab/snake/dot slugs and enum constants are not credentials, but a version
300+
* suffix like `v2` or a token like `k8s` sneaks a digit in, pushing them to two
301+
* character classes (lowercase + digit) — which would otherwise trip the class-count
302+
* check in {@link looksLikeSecretValue}. Rejecting the whole shape up front keeps that
303+
* heuristic honest to its documented promise of ignoring identifier slugs.
304+
* @param v - The value to check.
305+
* @returns True when the value is a lowercase delimited identifier.
306+
*/
307+
function isDelimitedIdentifier(v: string): boolean {
308+
return /^[a-z0-9]+([._-][a-z0-9]+)+$/.test(v);
309+
}
310+
295311
/**
296312
* Decides whether a value assigned to a suspiciously-named key actually looks like a
297313
* credential rather than a kebab/snake-case identifier or enum slug.
@@ -306,6 +322,7 @@ function characterClassCount(v: string): number {
306322
*/
307323
function looksLikeSecretValue(v: string): boolean {
308324
if (SECRET_VALUE_PREFIXES.test(v)) return true;
325+
if (isDelimitedIdentifier(v)) return false;
309326
if (characterClassCount(v) >= 2) return true;
310327
return (
311328
v.length >= SINGLE_CLASS_MIN_LENGTH &&

packages/cli/test/unit/core/security/secretDetectors.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,32 @@ const email = "user@example.com";
690690
expect(hasSuspiciousKeyFinding(findings)).toBe(true);
691691
});
692692

693+
// Regression: a version digit (v1/v2) or token like `k8s` inside an
694+
// otherwise lowercase kebab slug used to push it to two character classes
695+
// (lowercase + digit) and trip the class-count check. Delimited lowercase
696+
// identifiers must be rejected regardless of embedded digits.
697+
it.each([
698+
['secret-rotation-v2-rotate-secrets', 'src/queue-service.ts'],
699+
['secret-scanning-v2-full-scan', 'src/queue-service.ts'],
700+
['inject-k8s-sa-auth-token', 'src/gateway/types.ts'],
701+
['infisical-secret-value-blind-index-v1', 'src/blind-index.ts'],
702+
])(
703+
'does not flag a lowercase delimited slug with an embedded digit (%s)',
704+
(value, file) => {
705+
const source = `const SECRET_KIND = "${value}";`;
706+
const findings = detectSecretsInSource(file, source);
707+
708+
expect(hasSuspiciousKeyFinding(findings)).toBe(false);
709+
},
710+
);
711+
712+
it('does not flag a snake_case slug with an embedded digit', () => {
713+
const source = 'const TOKEN_KIND = "auth_token_rotation_v2";';
714+
const findings = detectSecretsInSource('src/enums.ts', source);
715+
716+
expect(hasSuspiciousKeyFinding(findings)).toBe(false);
717+
});
718+
693719
it('flags a single-class value carrying a known credential prefix', () => {
694720
// `xoxb-` prefix marks it as a real token even though it is lowercase-only
695721
// and below the entropy threshold, so the prefix branch must admit it.

0 commit comments

Comments
 (0)