mirror of
https://github.com/BradGroux/veritas-kanban.git
synced 2026-08-28 02:44:59 +00:00
Fixes case-sensitivity regression where prohibited paths like '.VERITAS-KANBAN/security.json' would not be caught on Linux CI, even though they alias protected paths on case-insensitive systems. Changes: - Normalize candidate paths to lowercase in findSecurityArtifactViolations() - Add comprehensive test file (security-artifacts-guard.test.ts) with: * Unit tests for path normalization and matching * Mixed-case variant detection * NUL-delimited Git output handling * Integration tests with isolated temporary Git repositories * Edge cases: spaces, nested paths, untracked files * Diagnostic message validation Security verification: - All security-related tests pass - Auth middleware tests pass - Typecheck passes - Lint budget at 600 (limit) - Guard invocation verified against live repository Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
55 lines
1.6 KiB
JavaScript
55 lines
1.6 KiB
JavaScript
#!/usr/bin/env node
|
|
import { spawnSync } from 'node:child_process';
|
|
import { fileURLToPath } from 'node:url';
|
|
import path from 'node:path';
|
|
|
|
const RUNTIME_SECURITY_CONFIG = /(?:^|\/)\.veritas-kanban\/security\.json$/;
|
|
|
|
export function normalizeGitPath(filePath) {
|
|
return filePath.replaceAll('\\', '/');
|
|
}
|
|
|
|
export function findSecurityArtifactViolations(paths) {
|
|
return paths
|
|
.map(normalizeGitPath)
|
|
.filter((filePath) => RUNTIME_SECURITY_CONFIG.test(filePath.toLowerCase()));
|
|
}
|
|
|
|
function listTrackedFiles() {
|
|
const result = spawnSync('git', ['ls-files', '-z', '--full-name'], {
|
|
encoding: 'utf8',
|
|
maxBuffer: 20 * 1024 * 1024,
|
|
});
|
|
|
|
if (result.error || result.status !== 0) {
|
|
const detail = result.stderr?.trim() || result.error?.message || 'unknown error';
|
|
throw new Error(`failed to list tracked files: ${detail}`);
|
|
}
|
|
|
|
return result.stdout.split('\0').filter(Boolean);
|
|
}
|
|
|
|
export function runSecurityArtifactCheck(paths = listTrackedFiles()) {
|
|
const violations = findSecurityArtifactViolations(paths);
|
|
|
|
if (violations.length > 0) {
|
|
console.error('Security artifact check failed.');
|
|
console.error('Runtime security configuration files must not be tracked:');
|
|
for (const filePath of violations) {
|
|
console.error(`- ${filePath}`);
|
|
}
|
|
process.exitCode = 1;
|
|
return false;
|
|
}
|
|
|
|
console.log(`Security artifact check passed (${paths.length} tracked files scanned).`);
|
|
return true;
|
|
}
|
|
|
|
function isDirectExecution() {
|
|
return process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url);
|
|
}
|
|
|
|
if (isDirectExecution()) {
|
|
runSecurityArtifactCheck();
|
|
}
|