agentaudit 3.9.40 → 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.
Files changed (2) hide show
  1. package/cli.mjs +29 -15
  2. 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', 'dist', 'build',
530
- '.next', '.nuxt', 'coverage', '.pytest_cache', '.mypy_cache', 'vendor',
531
- 'test', 'tests', '__tests__', 'spec', 'specs', 'docs', 'doc',
532
- 'examples', 'example', 'fixtures', '.github', '.vscode', '.idea',
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,14 +547,12 @@ 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 that are never security-relevant (pure text/metadata only NO executable files!)
543
- // Rule: if it CAN execute code (.js, .ts, .mjs, .py etc.), it MUST be scanned.
544
- // An attacker could hide malware in any executable config file.
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.
545
555
  const SKIP_FILES = new Set([
546
- 'license', 'license.md', 'license.txt', 'licence', 'licence.md',
547
- 'changelog.md', 'changelog', 'changes.md', 'history.md',
548
- 'contributing.md', 'contributors.md', 'authors', 'authors.md',
549
- 'code_of_conduct.md', 'security.md', 'funding.yml',
550
556
  '.gitignore', '.gitattributes', '.npmignore', '.dockerignore',
551
557
  '.editorconfig', '.browserslistrc', '.nvmrc', '.node-version',
552
558
  '.prettierignore', '.eslintignore',
@@ -1464,12 +1470,16 @@ async function auditRepo(url) {
1464
1470
  // with room for system prompt (~2k tokens) + output (4k tokens)
1465
1471
  const MAX_CHUNK_CHARS = 60_000;
1466
1472
  const chunks = []; // array of code block strings
1473
+ const chunkFileNames = []; // track which files are in each chunk for error reporting
1467
1474
  let currentChunk = '';
1468
1475
  let currentChars = 0;
1476
+ let currentFiles = [];
1469
1477
  for (const file of files) {
1470
1478
  const entry = `\n### FILE: ${file.path}\n\`\`\`\n${file.content}\n\`\`\`\n`;
1471
1479
  if (currentChars + entry.length > MAX_CHUNK_CHARS && currentChars > 0) {
1472
1480
  chunks.push(currentChunk);
1481
+ chunkFileNames.push([...currentFiles]);
1482
+ currentFiles = [];
1473
1483
  currentChunk = '';
1474
1484
  currentChars = 0;
1475
1485
  }
@@ -1482,8 +1492,9 @@ async function auditRepo(url) {
1482
1492
  currentChunk += entry;
1483
1493
  currentChars += entry.length;
1484
1494
  }
1495
+ currentFiles.push(file.path);
1485
1496
  }
1486
- if (currentChunk) chunks.push(currentChunk);
1497
+ if (currentChunk) { chunks.push(currentChunk); chunkFileNames.push([...currentFiles]); }
1487
1498
 
1488
1499
  const needsMultiPass = chunks.length > 1;
1489
1500
  if (needsMultiPass) {
@@ -1604,7 +1615,7 @@ async function auditRepo(url) {
1604
1615
  const modelInfo = modelData.data?.find(m => m.id === actualModel);
1605
1616
  if (modelInfo?.context_length) {
1606
1617
  const ctx = modelInfo.context_length;
1607
- outputTokenBudget = ctx >= 128_000 ? 8192 : ctx >= 64_000 ? 4096 : ctx >= 32_000 ? 2048 : 1024;
1618
+ outputTokenBudget = ctx >= 128_000 ? 8192 : ctx >= 64_000 ? 4096 : ctx >= 32_000 ? 2048 : 2048;
1608
1619
  if (process.argv.includes('--debug')) {
1609
1620
  console.log(` ${c.dim} Model context: ${ctx.toLocaleString()} tokens → max_tokens: ${outputTokenBudget}${c.reset}`);
1610
1621
  }
@@ -1744,8 +1755,11 @@ async function auditRepo(url) {
1744
1755
  const result = await callLLM(chunks[i], `pass ${i + 1}`);
1745
1756
 
1746
1757
  if (result.error) {
1758
+ const failedFiles = chunkFileNames[i] || [];
1747
1759
  console.log(` ${c.red}failed${c.reset} ${c.dim}(${result.error.slice(0, 80)})${c.reset}`);
1748
- // Don't abort on individual pass failures — continue with remaining chunks
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
+ }
1749
1763
  continue;
1750
1764
  }
1751
1765
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentaudit",
3
- "version": "3.9.40",
3
+ "version": "3.9.41",
4
4
  "description": "Security scanner for AI packages — MCP server + CLI",
5
5
  "type": "module",
6
6
  "bin": {