import { execFileSync } from 'node:child_process' import { readFileSync } from 'node:fs' const candidateOutput = execFileSync( 'git', ['ls-files', '--cached', '--others', '--exclude-standard', '-z'], { encoding: 'utf8' }, ) const supportedFile = /\.(?:bat|cjs|cs|gradle|html|js|json|mjs|pem|properties|ps1|sh|toml|ts|tsx|ya?ml)$/i const excludedPath = /(?:^|\/)(?:bin|build|dist|node_modules|obj|playwright-report|scratch)(?:\/|$)|(?:^|\/)(?:__tests__|fixtures?|tests?)(?:\/|$)|\.test\.[cm]?[jt]sx?$|\.spec\.[cm]?[jt]sx?$|(?:^|\/)migrations(?:\/|$)|(?:^|\/)package-lock\.json$|(?:^|\/)deno\.lock$|\.example\.(?:txt|json|ya?ml)$/i const rules = [ { name: 'basic-auth-literal', pattern: /Buffer\.from\(\s*(['"])[^\r\n'"]{1,100}:[^\r\n'"]{4,}\1/, }, { name: 'browser-credential-literal', pathPattern: /^scripts\//, pattern: /(?:page\.fill\([^\r\n,]*(?:password|user_name|email)[^\r\n,]*,|(?:password|username|email|login)\w*\.fill\()\s*(['"])(?!\$|replace|example|dummy|test|changeme|your_|android)(?:(?!\1).){2,}\1/i, }, { name: 'browser-operator-email-literal', pathPattern: /^scripts\//, pattern: /(?:email|user_name|username|login|operator)[^\r\n]{0,120}(['"])[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\1/i, }, { name: 'keystore-password-literal', pattern: /--(?:ks|key)-pass\s+pass:[^\s'"`]+|(['"])-(?:store|key)pass\1\s*,\s*(['"])(?:(?!\2).){4,}\2|-?(?:store|key)pass\s+[^\s$%"'`][^\s"'`]*/i, }, { name: 'google-oauth-client-secret', pattern: /GOCSPX-[A-Za-z0-9_-]{20,}/, }, { name: 'google-oauth-client-id', pattern: /[0-9]{6,}-[A-Za-z0-9_-]{8,}\.apps\.googleusercontent\.com/, }, { name: 'google-api-key', pattern: /AIza[A-Za-z0-9_-]{20,}/, }, { name: 'private-key-material', pattern: /-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----\r?\n[A-Za-z0-9+/=\r\n]{40,}-----END (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/, }, { name: 'legacy-license-prefix-fail-open', pattern: /\.startsWith\(\s*(['"])D3RO-(?:PRO|PLUS|TEAM)-\1\s*\)\s*&&\s*[A-Za-z_$][\w$]*\.length\s*>=/, }, { name: 'known-live-token-prefix', pattern: /(?:ghp_|github_pat_|glpat-|rk_live_|sk_live_)[A-Za-z0-9_-]{12,}/, }, { name: 'credential-in-url', pattern: /https?:\/\/[^\s\/@:]+:[^\s\/@]+@/, }, { name: 'credential-assignment-literal', pattern: /(?:password|passwd|client[_-]?secret|api[_-]?secret|service[_-]?key|jwt[_-]?(?:secret|key)|admin[_-]?(?:bootstrap[_-]?token|session[_-]?secret)|service[_-]?role[_-]?key)\s*[:=]\s*(['"])(?!\s*(?:\$|\{\{|%[A-Z_][A-Z0-9_]*%|(?:replace|example|dummy|test|ci[-_]|changeme|your_|android)\b))(?:(?!\1).){8,}\1/i, }, ] function scanSource(path, source) { return rules .filter((rule) => !rule.pathPattern || rule.pathPattern.test(path)) .filter((rule) => rule.pattern.test(source)) .map((rule) => `${path}: ${rule.name}`) } if (process.argv.includes('--self-test')) { const legacyLicensePrefix = ['D3RO', 'PRO', ''].join('-') const unsafeCases = [ ['scripts/login.mjs', ['await emailInput.', 'fill(', "'operator", '@', "example.com')"].join('')], ['scripts/login.mjs', `const secret = '${'GOCSPX-'}abcdefghijklmnopqrstuvwxyz'`], ['scripts/login.mjs', `const id = '1234567890-abcdefghijklmnop.${'apps.'}googleusercontent.com'`], ['scripts/release.mjs', `const token = '${'ghp_'}abcdefghijklmnopqrstuvwxyz'`], ['scripts/deploy.ps1', `$JWT_SECRET = '${'a-fixed-'}jwt-signing-secret-value'`], ['scripts/gen-keystore.js', `const args = ['-storepass', '${'fixed-keystore-password'}']`], [ 'release/evidence-private.pem', ['-----BEGIN ', 'PRIVATE KEY-----\n', 'A'.repeat(64), '\n-----END ', 'PRIVATE KEY-----'].join(''), ], [ 'packages/core/src/license.ts', `if (trimmed.startsWith('${legacyLicensePrefix}') && trimmed.length >= 14) return { valid: true }`, ], ] const safeCases = [ ['scripts/login.mjs', `await emailInput.fill(requireEnvironment('D3RO_PORTAL_OPERATOR_EMAIL'))`], ['scripts/release.mjs', `const token = process.env.FORGEJO_TOKEN?.trim()`], ['scripts/deploy.sh', `JWT_SECRET="$JWT_SECRET"`], ['.github/workflows/ci.yml', `MOBILE_E2E_PASSWORD: \${{ secrets.MOBILE_E2E_PASSWORD }}`], ['.forgejo/workflows/release.yml', `WIN_CSC_KEY_${'PASS' + 'WORD'}: "\${{ secrets.WIN_CSC_KEY_PASSWORD }}"`], ['.env.example', 'JWT_SECRET='], [ 'release/evidence-public.pem', ['-----BEGIN ', 'PUBLIC KEY-----\n', 'A'.repeat(64), '\n-----END ', 'PUBLIC KEY-----'].join(''), ], ] const failures = [] for (const [path, source] of unsafeCases) { if (scanSource(path, source).length === 0) failures.push(`missed unsafe fixture: ${path}`) } for (const [path, source] of safeCases) { if (scanSource(path, source).length > 0) failures.push(`flagged safe fixture: ${path}`) } if (failures.length > 0) { for (const failure of failures) console.error(failure) process.exit(1) } console.log('Hard-coded credential scanner self-test passed.') process.exit(0) } const findings = [] for (const path of candidateOutput.split('\0').filter(Boolean)) { const normalized = path.replaceAll('\\', '/') if ((!supportedFile.test(normalized) && normalized !== '.env.example') || excludedPath.test(normalized)) continue let source try { source = readFileSync(path, 'utf8') } catch { continue } findings.push(...scanSource(normalized, source)) } if (findings.length > 0) { console.error('Potential hard-coded credentials were found:') for (const finding of findings.sort()) console.error(`- ${finding}`) process.exit(1) } console.log('No hard-coded credential patterns found in source-controlled runtime files.')