agentaudit 3.9.31 → 3.9.33

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 (3) hide show
  1. package/cli.mjs +47 -1
  2. package/index.mjs +36 -2
  3. package/package.json +1 -1
package/cli.mjs CHANGED
@@ -1734,11 +1734,55 @@ async function auditRepo(url) {
1734
1734
  console.log(` ${c.dim}Report: ${REGISTRY_URL}/skills/${reportSlug}${c.reset}`);
1735
1735
  // Refresh stats cache in background
1736
1736
  if (creds.agent_name) refreshStatsCache(creds.agent_name).catch(() => {});
1737
+ // Fetch registry consensus after upload
1738
+ try {
1739
+ const regData = await checkRegistry(reportSlug);
1740
+ if (regData) {
1741
+ const regRisk = regData.latest_risk_score ?? regData.risk_score ?? 0;
1742
+ const regTrust = regData.trust_score ?? (100 - regRisk);
1743
+ const totalReports = regData.total_reports ?? 1;
1744
+ const uniqueAgents = regData.unique_agents ?? 1;
1745
+ const confidence = regData.confidence ?? 'unverified';
1746
+ const totalFindings = regData.total_findings ?? 0;
1747
+ const hasOfficial = regData.has_official_audit;
1748
+
1749
+ // Show registry consensus if different from own report or multiple reports exist
1750
+ if (totalReports > 1 || regRisk !== report.risk_score) {
1751
+ console.log();
1752
+ console.log(` ${c.bold}Registry Consensus${c.reset}`);
1753
+ const trustColor = regTrust >= 70 ? c.green : regTrust >= 40 ? c.yellow : c.red;
1754
+ const trustLabel = regTrust >= 70 ? 'SAFE' : regTrust >= 40 ? 'CAUTION' : 'UNSAFE';
1755
+ console.log(` ${trustColor}${c.bold}${trustLabel}${c.reset} Trust Score: ${trustColor}${regTrust}/100${c.reset} ${c.dim}(across ${totalReports} reports from ${uniqueAgents} auditor${uniqueAgents !== 1 ? 's' : ''})${c.reset}`);
1756
+ if (totalFindings > 0) {
1757
+ console.log(` ${c.dim}Total findings across all reports: ${totalFindings}${c.reset}`);
1758
+ }
1759
+ const confDisplay = {
1760
+ consensus: { icon: '🟢', label: 'Consensus Certified', color: c.green },
1761
+ verified: { icon: '🟢', label: 'Verified', color: c.green },
1762
+ low: { icon: '🟔', label: 'Low Confidence', color: c.yellow },
1763
+ unverified: { icon: 'šŸ”“', label: 'Unverified', color: c.yellow },
1764
+ }[confidence] || { icon: '⚪', label: confidence, color: c.dim };
1765
+ console.log(` ${confDisplay.icon} ${confDisplay.color}${confDisplay.label}${c.reset}`);
1766
+ if (hasOfficial) console.log(` ${c.green}āœ” Officially audited${c.reset}`);
1767
+
1768
+ // Warn if own report disagrees with consensus
1769
+ const ownRisk = report.risk_score || 0;
1770
+ if (Math.abs(ownRisk - regRisk) > 10) {
1771
+ console.log();
1772
+ console.log(` ${c.yellow}⚠ Your audit (risk ${ownRisk}) differs from registry consensus (risk ${regRisk}).${c.reset}`);
1773
+ console.log(` ${c.dim} This may indicate model-specific blind spots or a changing codebase.${c.reset}`);
1774
+ }
1775
+ }
1776
+ }
1777
+ } catch {}
1737
1778
  } else {
1779
+ const errBody = await res.text().catch(() => '');
1738
1780
  console.log(` ${c.yellow}failed (HTTP ${res.status})${c.reset}`);
1781
+ if (process.argv.includes('--debug')) console.log(` ${c.dim}Response: ${errBody.slice(0, 500)}${c.reset}`);
1739
1782
  }
1740
1783
  } catch (err) {
1741
1784
  console.log(` ${c.yellow}failed${c.reset}`);
1785
+ if (process.argv.includes('--debug')) console.log(` ${c.dim}Error: ${err.message}${c.reset}`);
1742
1786
  }
1743
1787
  } else {
1744
1788
  console.log(` ${c.dim}Run ${c.cyan}agentaudit setup${c.dim} to upload reports to the registry${c.reset}`);
@@ -1751,12 +1795,14 @@ async function auditRepo(url) {
1751
1795
  // ── Check command ───────────────────────────────────────
1752
1796
 
1753
1797
  async function checkPackage(name, { autoAudit = false } = {}) {
1798
+ // Derive slug from URL for registry lookup (URLs won't match as-is)
1799
+ const slug = (name.includes('github.com') || name.includes('://')) ? slugFromUrl(name) : name.toLowerCase();
1754
1800
  if (!jsonMode) {
1755
1801
  console.log(`${icons.info} Looking up ${c.bold}${name}${c.reset} in registry...`);
1756
1802
  console.log();
1757
1803
  }
1758
1804
 
1759
- const data = await checkRegistry(name);
1805
+ const data = await checkRegistry(slug);
1760
1806
  if (!data) {
1761
1807
  if (!jsonMode) {
1762
1808
  // Auto-audit: only when called from 'check' command AND input looks like a URL
package/index.mjs CHANGED
@@ -534,7 +534,27 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
534
534
  try { data = JSON.parse(body); } catch { data = { raw: body }; }
535
535
 
536
536
  if (res.ok) {
537
- return { content: [{ type: 'text', text: `āœ… Report submitted!\n\nReport ID: ${data.report_id || 'unknown'}\nURL: ${REGISTRY_URL}/skills/${report.skill_slug}\nRisk: ${report.risk_score}/100 (${report.result})\nFindings: ${report.findings_count}` }] };
537
+ const reportSlug = data?.skill_slug || report.skill_slug;
538
+ // Fetch registry consensus to give the agent full decision context
539
+ let consensusInfo = '';
540
+ try {
541
+ const regRes = await fetch(`${REGISTRY_URL}/api/skills/${encodeURIComponent(reportSlug)}`, { signal: AbortSignal.timeout(5000) });
542
+ if (regRes.ok) {
543
+ const reg = await regRes.json();
544
+ const regRisk = reg.latest_risk_score ?? 0;
545
+ const regTrust = reg.trust_score ?? (100 - regRisk);
546
+ const totalReports = reg.total_reports ?? 1;
547
+ const uniqueAgents = reg.unique_agents ?? 1;
548
+ const confidence = reg.confidence ?? 'unverified';
549
+ const totalFindings = reg.total_findings ?? 0;
550
+ const trustLabel = regTrust >= 70 ? 'SAFE' : regTrust >= 40 ? 'CAUTION' : 'UNSAFE';
551
+ consensusInfo = `\n\nšŸ“Š **Registry Consensus** (across ${totalReports} reports from ${uniqueAgents} auditor${uniqueAgents !== 1 ? 's' : ''}):\n- Trust Score: ${regTrust}/100 (${trustLabel})\n- Total Findings: ${totalFindings}\n- Confidence: ${confidence}${reg.has_official_audit ? '\n- āœ” Officially audited' : ''}`;
552
+ if (totalReports > 1) {
553
+ consensusInfo += `\n\nāš ļø IMPORTANT: Your audit is ONE data point. The registry consensus reflects ALL audits. If your result differs significantly, this may indicate model-specific blind spots. Agents should use the REGISTRY CONSENSUS (not just this single audit) when making install/trust decisions.`;
554
+ }
555
+ }
556
+ } catch {}
557
+ return { content: [{ type: 'text', text: `āœ… Report submitted!\n\nReport ID: ${data.report_id || 'unknown'}\nURL: ${REGISTRY_URL}/skills/${reportSlug}\nYour Audit: Risk ${report.risk_score}/100 (${report.result}), ${report.findings_count} findings${consensusInfo}` }] };
538
558
  } else {
539
559
  return { content: [{ type: 'text', text: `Upload failed (HTTP ${res.status}): ${JSON.stringify(data, null, 2)}` }] };
540
560
  }
@@ -584,8 +604,22 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
584
604
  summary += `āš ļø OUTDATED: The package has changed since the last audit. Consider running a fresh audit first.\n\n`;
585
605
  }
586
606
 
607
+ // Consensus section — critical for agent decision-making
608
+ const totalReports = data.total_reports ?? 1;
609
+ const uniqueAgents = data.unique_agents ?? 1;
610
+ const confidence = data.confidence ?? 'unverified';
611
+ const trustScore = data.trust_score ?? (100 - (risk || 0));
612
+ const trustLabel = trustScore >= 70 ? 'SAFE' : trustScore >= 40 ? 'CAUTION' : 'UNSAFE';
613
+
614
+ summary += `--- Registry Consensus ---\n`;
615
+ summary += `Trust Score: ${trustScore}/100 (${trustLabel})\n`;
616
+ summary += `Reports: ${totalReports} from ${uniqueAgents} independent auditor${uniqueAgents !== 1 ? 's' : ''}\n`;
617
+ summary += `Confidence: ${confidence}\n`;
618
+ if (confidence === 'unverified') summary += `āš ļø Only 1 audit exists — consider running your own for independent verification.\n`;
619
+ if (confidence === 'low') summary += `āš ļø Limited independent verification — more auditors needed for consensus.\n`;
620
+
587
621
  // Details section
588
- summary += `--- Details ---\n`;
622
+ summary += `\n--- Details ---\n`;
589
623
  summary += `Package: ${package_name}\n`;
590
624
  summary += `Status: ${official}\n`;
591
625
  summary += `Last Audited: ${auditedAt}\n`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentaudit",
3
- "version": "3.9.31",
3
+ "version": "3.9.33",
4
4
  "description": "Security scanner for AI packages — MCP server + CLI",
5
5
  "type": "module",
6
6
  "bin": {