agentaudit 3.7.0 → 3.7.1

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 +44 -6
  2. package/package.json +1 -1
package/cli.mjs CHANGED
@@ -638,6 +638,11 @@ function findMcpConfigs() {
638
638
  { name: 'Continue', path: path.join(home, '.continue', 'config.json') },
639
639
  ];
640
640
 
641
+ // Also check AGENTAUDIT_TEST_CONFIG env for testing
642
+ if (process.env.AGENTAUDIT_TEST_CONFIG) {
643
+ candidates.push({ name: 'Test Config', path: process.env.AGENTAUDIT_TEST_CONFIG });
644
+ }
645
+
641
646
  // Also scan workspace .cursor/mcp.json, .vscode/mcp.json in cwd
642
647
  const cwd = process.cwd();
643
648
  candidates.push(
@@ -731,6 +736,22 @@ function serverSlug(server) {
731
736
  return server.name.toLowerCase().replace(/[^a-z0-9-]/gi, '-');
732
737
  }
733
738
 
739
+ async function searchGitHub(query) {
740
+ try {
741
+ const res = await fetch(`https://api.github.com/search/repositories?q=${encodeURIComponent(query)}&per_page=1`, {
742
+ signal: AbortSignal.timeout(5000),
743
+ headers: { 'Accept': 'application/vnd.github+json' },
744
+ });
745
+ if (res.ok) {
746
+ const data = await res.json();
747
+ if (data.items?.length > 0) {
748
+ return data.items[0].html_url;
749
+ }
750
+ }
751
+ } catch {}
752
+ return null;
753
+ }
754
+
734
755
  async function resolveSourceUrl(server) {
735
756
  // Already have it
736
757
  if (server.sourceUrl) return server.sourceUrl;
@@ -750,7 +771,9 @@ async function resolveSourceUrl(server) {
750
771
  }
751
772
  }
752
773
  } catch {}
753
- // Fallback: npm page
774
+ // Fallback: try GitHub search for the package name
775
+ const ghUrl = await searchGitHub(server.npmPackage);
776
+ if (ghUrl) return ghUrl;
754
777
  return `https://www.npmjs.com/package/${server.npmPackage}`;
755
778
  }
756
779
 
@@ -767,6 +790,9 @@ async function resolveSourceUrl(server) {
767
790
  if (source && source.startsWith('http')) return source;
768
791
  }
769
792
  } catch {}
793
+ // Fallback: GitHub search
794
+ const ghUrl = await searchGitHub(server.pyPackage);
795
+ if (ghUrl) return ghUrl;
770
796
  return `https://pypi.org/project/${server.pyPackage}/`;
771
797
  }
772
798
 
@@ -915,16 +941,28 @@ async function discoverCommand(options = {}) {
915
941
  if (unauditedServers > 0) console.log(` ${icons.caution} ${c.yellow}${unauditedServers} not audited${c.reset}`);
916
942
  console.log();
917
943
 
918
- // --scan: automatically scan all servers with resolved source URLs
944
+ // --scan: automatically scan all servers with resolved source URLs (git-cloneable only)
919
945
  if (autoScan) {
920
- const scanTargets = allServersWithUrls.filter(s => s.sourceUrl && s.sourceUrl.startsWith('http'));
921
- if (scanTargets.length > 0) {
946
+ const isCloneable = (url) => /^https?:\/\/(github\.com|gitlab\.com|bitbucket\.org)\//i.test(url);
947
+ const scanTargets = allServersWithUrls.filter(s => s.sourceUrl && isCloneable(s.sourceUrl));
948
+ // Deduplicate by sourceUrl
949
+ const seen = new Set();
950
+ const dedupedTargets = scanTargets.filter(s => {
951
+ if (seen.has(s.sourceUrl)) return false;
952
+ seen.add(s.sourceUrl);
953
+ return true;
954
+ });
955
+ const skipped = allServersWithUrls.filter(s => s.sourceUrl && !isCloneable(s.sourceUrl));
956
+ if (dedupedTargets.length > 0) {
922
957
  console.log(`${c.dim}${'─'.repeat(60)}${c.reset}`);
923
- console.log(` ${c.bold}${icons.scan} Auto-scanning ${scanTargets.length} server${scanTargets.length !== 1 ? 's' : ''}...${c.reset}`);
958
+ console.log(` ${c.bold}${icons.scan} Auto-scanning ${dedupedTargets.length} server${dedupedTargets.length !== 1 ? 's' : ''}...${c.reset}`);
959
+ if (skipped.length > 0) {
960
+ console.log(` ${c.dim}(${skipped.length} skipped — no cloneable source URL)${c.reset}`);
961
+ }
924
962
  console.log();
925
963
 
926
964
  const scanResults = [];
927
- for (const target of scanTargets) {
965
+ for (const target of dedupedTargets) {
928
966
  const result = await scanRepo(target.sourceUrl);
929
967
  if (result) scanResults.push({ ...result, serverName: target.name });
930
968
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentaudit",
3
- "version": "3.7.0",
3
+ "version": "3.7.1",
4
4
  "description": "Security scanner for AI packages — MCP server + CLI",
5
5
  "type": "module",
6
6
  "bin": {