agentaudit 3.9.38 → 3.9.40

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 +46 -4
  2. package/package.json +1 -1
package/cli.mjs CHANGED
@@ -537,6 +537,19 @@ const SKIP_EXTENSIONS = new Set([
537
537
  '.woff2', '.ttf', '.eot', '.mp3', '.mp4', '.zip', '.tar', '.gz',
538
538
  '.map', '.min.js', '.min.css', '.d.ts', '.pyc', '.pyo', '.so',
539
539
  '.dylib', '.dll', '.exe', '.bin', '.dat', '.db', '.sqlite',
540
+ '.snap', '.patch', '.diff', '.log', '.csv', '.tsv', '.parquet',
541
+ ]);
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.
545
+ 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
+ '.gitignore', '.gitattributes', '.npmignore', '.dockerignore',
551
+ '.editorconfig', '.browserslistrc', '.nvmrc', '.node-version',
552
+ '.prettierignore', '.eslintignore',
540
553
  ]);
541
554
 
542
555
  function collectFiles(dir, basePath = '', collected = [], totalSize = { bytes: 0 }) {
@@ -555,6 +568,7 @@ function collectFiles(dir, basePath = '', collected = [], totalSize = { bytes: 0
555
568
  } else {
556
569
  const ext = path.extname(entry.name).toLowerCase();
557
570
  if (SKIP_EXTENSIONS.has(ext)) continue;
571
+ if (SKIP_FILES.has(entry.name.toLowerCase())) continue;
558
572
  try {
559
573
  const stat = fs.statSync(fullPath);
560
574
  if (stat.size > MAX_FILE_SIZE || stat.size === 0) continue;
@@ -1575,6 +1589,34 @@ async function auditRepo(url) {
1575
1589
  }
1576
1590
 
1577
1591
  // ── LLM call helper (reused for multi-pass) ──
1592
+ // Determine optimal max_tokens based on model context size
1593
+ // For large-context models (128k+) we can afford 8192 output tokens
1594
+ // For medium (32k-128k) use 4096, for small (<32k) use 2048
1595
+ let outputTokenBudget = 4096; // safe default
1596
+ if (resolvedProvider.id === 'openrouter') {
1597
+ try {
1598
+ const modelInfoRes = await fetch(`https://openrouter.ai/api/v1/models`, {
1599
+ signal: AbortSignal.timeout(5000),
1600
+ headers: { 'HTTP-Referer': 'https://agentaudit.dev' },
1601
+ });
1602
+ if (modelInfoRes.ok) {
1603
+ const modelData = await modelInfoRes.json();
1604
+ const modelInfo = modelData.data?.find(m => m.id === actualModel);
1605
+ if (modelInfo?.context_length) {
1606
+ const ctx = modelInfo.context_length;
1607
+ outputTokenBudget = ctx >= 128_000 ? 8192 : ctx >= 64_000 ? 4096 : ctx >= 32_000 ? 2048 : 1024;
1608
+ if (process.argv.includes('--debug')) {
1609
+ console.log(` ${c.dim} Model context: ${ctx.toLocaleString()} tokens → max_tokens: ${outputTokenBudget}${c.reset}`);
1610
+ }
1611
+ }
1612
+ }
1613
+ } catch { /* ignore — use default */ }
1614
+ } else if (resolvedProvider.id === 'anthropic') {
1615
+ outputTokenBudget = 8192; // Claude models have 200k context
1616
+ } else if (resolvedProvider.id === 'openai') {
1617
+ outputTokenBudget = 8192; // GPT-4o has 128k context
1618
+ }
1619
+
1578
1620
  async function callLLM(codeContent, passLabel) {
1579
1621
  const systemPrompt = auditPrompt || 'You are a security auditor. Analyze the code and report findings as JSON.';
1580
1622
  const userMessage = [
@@ -1605,11 +1647,11 @@ async function auditRepo(url) {
1605
1647
  },
1606
1648
  body: JSON.stringify({
1607
1649
  model: modelOverride || 'claude-sonnet-4-20250514',
1608
- max_tokens: 4096,
1650
+ max_tokens: outputTokenBudget,
1609
1651
  system: systemPrompt,
1610
1652
  messages: [{ role: 'user', content: userMessage }],
1611
1653
  }),
1612
- signal: AbortSignal.timeout(120_000),
1654
+ signal: AbortSignal.timeout(180_000),
1613
1655
  });
1614
1656
  const data = await res.json();
1615
1657
  if (data.error) {
@@ -1653,13 +1695,13 @@ async function auditRepo(url) {
1653
1695
  headers: { 'Content-Type': 'application/json', ...authHeaders },
1654
1696
  body: JSON.stringify({
1655
1697
  model: modelName,
1656
- max_tokens: 4096,
1698
+ max_tokens: outputTokenBudget,
1657
1699
  messages: [
1658
1700
  { role: 'system', content: systemPrompt },
1659
1701
  { role: 'user', content: userMessage },
1660
1702
  ],
1661
1703
  }),
1662
- signal: AbortSignal.timeout(resolvedProvider.id === 'ollama' ? 300_000 : 120_000),
1704
+ signal: AbortSignal.timeout(resolvedProvider.id === 'ollama' ? 300_000 : 180_000),
1663
1705
  });
1664
1706
  const data = await res.json();
1665
1707
  if (data.error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentaudit",
3
- "version": "3.9.38",
3
+ "version": "3.9.40",
4
4
  "description": "Security scanner for AI packages — MCP server + CLI",
5
5
  "type": "module",
6
6
  "bin": {