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.
- package/cli.mjs +46 -4
- 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:
|
|
1650
|
+
max_tokens: outputTokenBudget,
|
|
1609
1651
|
system: systemPrompt,
|
|
1610
1652
|
messages: [{ role: 'user', content: userMessage }],
|
|
1611
1653
|
}),
|
|
1612
|
-
signal: AbortSignal.timeout(
|
|
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:
|
|
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 :
|
|
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) {
|