agentaudit 3.9.39 → 3.9.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli.mjs +31 -20
- package/package.json +1 -1
package/cli.mjs
CHANGED
|
@@ -525,12 +525,20 @@ function extractJSON(text) {
|
|
|
525
525
|
|
|
526
526
|
const MAX_FILE_SIZE = 50_000;
|
|
527
527
|
const MAX_TOTAL_SIZE = 300_000;
|
|
528
|
+
// Directories safe to skip: dependencies, caches, build artifacts, editor config.
|
|
529
|
+
// SECURITY RULE: If a directory can contain source code, workflow files, or
|
|
530
|
+
// prose (prompt injection), it MUST be scanned.
|
|
531
|
+
// Reviewed 2026-02-17:
|
|
532
|
+
// - RESTORED: test/tests/__tests__/spec/specs/e2e (malware in test hooks)
|
|
533
|
+
// - RESTORED: .github (workflow injection, supply chain attacks)
|
|
534
|
+
// - RESTORED: examples/example (hidden backdoors in "example" code)
|
|
535
|
+
// - RESTORED: docs/doc (prompt injection in documentation)
|
|
536
|
+
// - RESTORED: fixtures (test data can contain malicious payloads)
|
|
528
537
|
const SKIP_DIRS = new Set([
|
|
529
|
-
'node_modules', '.git', '__pycache__', '.venv', 'venv', '
|
|
530
|
-
'
|
|
531
|
-
'
|
|
532
|
-
'
|
|
533
|
-
'e2e', 'benchmark', 'benchmarks', '.tox', '.eggs', 'htmlcov',
|
|
538
|
+
'node_modules', '.git', '__pycache__', '.venv', 'venv', 'vendor',
|
|
539
|
+
'dist', 'build', '.next', '.nuxt',
|
|
540
|
+
'coverage', '.pytest_cache', '.mypy_cache', '.tox', '.eggs', 'htmlcov',
|
|
541
|
+
'.vscode', '.idea',
|
|
534
542
|
]);
|
|
535
543
|
const SKIP_EXTENSIONS = new Set([
|
|
536
544
|
'.lock', '.png', '.jpg', '.jpeg', '.gif', '.svg', '.ico', '.woff',
|
|
@@ -539,20 +547,15 @@ const SKIP_EXTENSIONS = new Set([
|
|
|
539
547
|
'.dylib', '.dll', '.exe', '.bin', '.dat', '.db', '.sqlite',
|
|
540
548
|
'.snap', '.patch', '.diff', '.log', '.csv', '.tsv', '.parquet',
|
|
541
549
|
]);
|
|
542
|
-
// Files
|
|
550
|
+
// Files safe to skip: ONLY inert line-based config that cannot execute code
|
|
551
|
+
// and cannot contain prompt injections (no prose, no markdown, no scripts).
|
|
552
|
+
// SECURITY RULE: When in doubt, SCAN IT. False positives > false negatives.
|
|
553
|
+
// Reviewed 2026-02-17: All .md files removed from skip list (prompt injection vector).
|
|
554
|
+
// All executable configs removed (malware vector). Only line-based dotfiles remain.
|
|
543
555
|
const SKIP_FILES = new Set([
|
|
544
|
-
'
|
|
545
|
-
'changelog.md', 'changelog', 'changes.md', 'history.md',
|
|
546
|
-
'contributing.md', 'contributors.md', 'authors', 'authors.md',
|
|
547
|
-
'code_of_conduct.md', 'security.md', 'funding.yml',
|
|
548
|
-
'.prettierrc', '.prettierrc.json', '.prettierrc.js', '.prettierignore',
|
|
549
|
-
'.eslintignore', '.gitignore', '.gitattributes', '.npmignore',
|
|
556
|
+
'.gitignore', '.gitattributes', '.npmignore', '.dockerignore',
|
|
550
557
|
'.editorconfig', '.browserslistrc', '.nvmrc', '.node-version',
|
|
551
|
-
'.
|
|
552
|
-
'jest.config.js', 'jest.config.ts', 'vitest.config.ts', 'vitest.config.js',
|
|
553
|
-
'.babelrc', 'babel.config.js', 'babel.config.json',
|
|
554
|
-
'postcss.config.js', 'postcss.config.mjs', 'tailwind.config.js', 'tailwind.config.ts',
|
|
555
|
-
'prettier.config.js', 'prettier.config.mjs',
|
|
558
|
+
'.prettierignore', '.eslintignore',
|
|
556
559
|
]);
|
|
557
560
|
|
|
558
561
|
function collectFiles(dir, basePath = '', collected = [], totalSize = { bytes: 0 }) {
|
|
@@ -1467,12 +1470,16 @@ async function auditRepo(url) {
|
|
|
1467
1470
|
// with room for system prompt (~2k tokens) + output (4k tokens)
|
|
1468
1471
|
const MAX_CHUNK_CHARS = 60_000;
|
|
1469
1472
|
const chunks = []; // array of code block strings
|
|
1473
|
+
const chunkFileNames = []; // track which files are in each chunk for error reporting
|
|
1470
1474
|
let currentChunk = '';
|
|
1471
1475
|
let currentChars = 0;
|
|
1476
|
+
let currentFiles = [];
|
|
1472
1477
|
for (const file of files) {
|
|
1473
1478
|
const entry = `\n### FILE: ${file.path}\n\`\`\`\n${file.content}\n\`\`\`\n`;
|
|
1474
1479
|
if (currentChars + entry.length > MAX_CHUNK_CHARS && currentChars > 0) {
|
|
1475
1480
|
chunks.push(currentChunk);
|
|
1481
|
+
chunkFileNames.push([...currentFiles]);
|
|
1482
|
+
currentFiles = [];
|
|
1476
1483
|
currentChunk = '';
|
|
1477
1484
|
currentChars = 0;
|
|
1478
1485
|
}
|
|
@@ -1485,8 +1492,9 @@ async function auditRepo(url) {
|
|
|
1485
1492
|
currentChunk += entry;
|
|
1486
1493
|
currentChars += entry.length;
|
|
1487
1494
|
}
|
|
1495
|
+
currentFiles.push(file.path);
|
|
1488
1496
|
}
|
|
1489
|
-
if (currentChunk) chunks.push(currentChunk);
|
|
1497
|
+
if (currentChunk) { chunks.push(currentChunk); chunkFileNames.push([...currentFiles]); }
|
|
1490
1498
|
|
|
1491
1499
|
const needsMultiPass = chunks.length > 1;
|
|
1492
1500
|
if (needsMultiPass) {
|
|
@@ -1607,7 +1615,7 @@ async function auditRepo(url) {
|
|
|
1607
1615
|
const modelInfo = modelData.data?.find(m => m.id === actualModel);
|
|
1608
1616
|
if (modelInfo?.context_length) {
|
|
1609
1617
|
const ctx = modelInfo.context_length;
|
|
1610
|
-
outputTokenBudget = ctx >= 128_000 ? 8192 : ctx >= 64_000 ? 4096 : ctx >= 32_000 ? 2048 :
|
|
1618
|
+
outputTokenBudget = ctx >= 128_000 ? 8192 : ctx >= 64_000 ? 4096 : ctx >= 32_000 ? 2048 : 2048;
|
|
1611
1619
|
if (process.argv.includes('--debug')) {
|
|
1612
1620
|
console.log(` ${c.dim} Model context: ${ctx.toLocaleString()} tokens → max_tokens: ${outputTokenBudget}${c.reset}`);
|
|
1613
1621
|
}
|
|
@@ -1747,8 +1755,11 @@ async function auditRepo(url) {
|
|
|
1747
1755
|
const result = await callLLM(chunks[i], `pass ${i + 1}`);
|
|
1748
1756
|
|
|
1749
1757
|
if (result.error) {
|
|
1758
|
+
const failedFiles = chunkFileNames[i] || [];
|
|
1750
1759
|
console.log(` ${c.red}failed${c.reset} ${c.dim}(${result.error.slice(0, 80)})${c.reset}`);
|
|
1751
|
-
|
|
1760
|
+
if (failedFiles.length > 0) {
|
|
1761
|
+
console.log(` ${c.yellow}⚠ ${failedFiles.length} files NOT analyzed:${c.reset} ${c.dim}${failedFiles.slice(0, 5).join(', ')}${failedFiles.length > 5 ? ` (+${failedFiles.length - 5} more)` : ''}${c.reset}`);
|
|
1762
|
+
}
|
|
1752
1763
|
continue;
|
|
1753
1764
|
}
|
|
1754
1765
|
|