diff --git a/.changeset/fair-places-care.md b/.changeset/fair-places-care.md new file mode 100644 index 00000000..c6eddcf6 --- /dev/null +++ b/.changeset/fair-places-care.md @@ -0,0 +1,5 @@ +--- +'dotenv-diff': patch +--- + +ignore minified lines for env usage diff --git a/docs/capabilities.md b/docs/capabilities.md index 5680f87b..0c786b8f 100644 --- a/docs/capabilities.md +++ b/docs/capabilities.md @@ -38,6 +38,8 @@ Default scanned file types: .ts, .js, jsx, tsx, vue, .mjs, .mts, .cjs, .cts, .sv ## What It Checks For +> **Note:** The scanner skips files containing any line over 500 characters, as these are likely minified or bundled — this avoids false positives across all checks below. + ### 1 Missing Variables Variables that are **used in code** but **not defined** in the selected env comparison file. diff --git a/packages/cli/src/core/helpers/isLikelyMinified.ts b/packages/cli/src/core/helpers/isLikelyMinified.ts new file mode 100644 index 00000000..e262a0b6 --- /dev/null +++ b/packages/cli/src/core/helpers/isLikelyMinified.ts @@ -0,0 +1,7 @@ +/** + * Returns true if a line looks like minified/bundled code. + * Used to skip entire files early in the pipeline. + */ +export function isLikelyMinified(content: string): boolean { + return content.split(/\r?\n/).some((line) => line.length > 500); +} diff --git a/packages/cli/src/core/scan/scanFile.ts b/packages/cli/src/core/scan/scanFile.ts index db425dab..b6ef9a5c 100644 --- a/packages/cli/src/core/scan/scanFile.ts +++ b/packages/cli/src/core/scan/scanFile.ts @@ -3,6 +3,7 @@ import type { EnvUsage, ScanOptions } from '../../config/types.js'; import { ENV_PATTERNS } from './patterns.js'; import { hasIgnoreComment } from '../security/secretDetectors.js'; import { normalizePath } from '../helpers/normalizePath.js'; +import { isLikelyMinified } from '../helpers/isLikelyMinified.js'; /** * Scans a file for environment variable usage. @@ -62,6 +63,9 @@ export function scanFile( // Get the context (the actual line) const contextLine = lines[lineNumber - 1]!; + // Ignore likely minified / bundled lines to avoid scan false positives + if (isLikelyMinified(contextLine)) continue; + // Determine previous line for ignore detection const prevLine = lines[lineNumber - 2] ?? ''; diff --git a/packages/cli/src/core/security/secretDetectors.ts b/packages/cli/src/core/security/secretDetectors.ts index df34f8a3..0f3808f9 100644 --- a/packages/cli/src/core/security/secretDetectors.ts +++ b/packages/cli/src/core/security/secretDetectors.ts @@ -1,4 +1,5 @@ import { shannonEntropyNormalized } from './entropy.js'; +import { isLikelyMinified } from '../helpers/isLikelyMinified.js'; /** * Severity levels for detected secrets @@ -55,11 +56,6 @@ const HARMLESS_URLS = [ const HARMLESS_ATTRIBUTE_KEYS = /\b(trackingId|trackingContext|data-testid|data-test|aria-label)\b/i; -// Ignore minified files -function isLikelyMinified(line: string): boolean { - return line.length > 500; // Extremely long line, likely minified -} - // Checks if a line is an HTML text node or tag function isHtmlTextNode(line: string): boolean { const trimmed = line.trim(); diff --git a/packages/cli/src/services/scanCodebase.ts b/packages/cli/src/services/scanCodebase.ts index 62984027..949b25f6 100644 --- a/packages/cli/src/services/scanCodebase.ts +++ b/packages/cli/src/services/scanCodebase.ts @@ -9,6 +9,7 @@ import { DEFAULT_EXCLUDE_PATTERNS } from '../core/scan/patterns.js'; import { scanFile } from '../core/scan/scanFile.js'; import { findFiles } from './fileWalker.js'; import { normalizePath } from '../core/helpers/normalizePath.js'; +import { isLikelyMinified } from '../core/helpers/isLikelyMinified.js'; /** * Scans the codebase for environment variable usage based on the provided options. @@ -30,6 +31,7 @@ export async function scanCodebase(opts: ScanOptions): Promise { for (const filePath of files) { const content = await safeReadFile(filePath); if (!content) continue; + if (isLikelyMinified(content)) continue; // Skip likely minified files // Scan the file for environment variable usages const fileUsages = scanFile(filePath, content, opts); diff --git a/packages/cli/test/unit/core/scan/scanFile.test.ts b/packages/cli/test/unit/core/scan/scanFile.test.ts index af570fdb..3e49d41b 100644 --- a/packages/cli/test/unit/core/scan/scanFile.test.ts +++ b/packages/cli/test/unit/core/scan/scanFile.test.ts @@ -105,6 +105,20 @@ const key = process.env.SECRET_KEY;`; expect(usages[0]?.isLogged).toBe(true); }); + it('ignores env usage on likely minified lines', () => { + const minifiedLine = `${'x'.repeat(520)}process.env.API_KEY`; + const usages = scanFile('/test/project/src/app.js', minifiedLine, baseOpts); + + expect(usages).toHaveLength(0); + }); + + it('ignores console.log env usage on likely minified lines', () => { + const minifiedLine = `${'x'.repeat(520)}console.log(process.env.API_KEY)`; + const usages = scanFile('/test/project/src/app.js', minifiedLine, baseOpts); + + expect(usages).toHaveLength(0); + }); + it('does not mark as logged when not in console statement', () => { const content = 'const key = process.env.API_KEY;'; const usages = scanFile('/test/project/src/app.js', content, baseOpts);