fullcourtdefense-cli 1.14.16 → 1.14.17

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.
@@ -867,19 +867,6 @@ async function discoverCommand(args, config) {
867
867
  })
868
868
  : undefined;
869
869
  const host = buildHostMetadata(args.userEmail, deep && found.some(s => s.probeMode === 'deep') ? 'deep' : 'config');
870
- if (args.json === 'true') {
871
- console.log(JSON.stringify({
872
- host,
873
- surfaces: [...surfaces],
874
- scannedFiles: scanned.map(s => `${s.source} → ${s.path}`),
875
- clientCoverage,
876
- servers: found,
877
- secrets,
878
- agentFiles,
879
- posture,
880
- }, null, 2));
881
- return;
882
- }
883
870
  const home = os.homedir();
884
871
  const uploadExtras = {
885
872
  secrets,
@@ -919,6 +906,20 @@ async function discoverCommand(args, config) {
919
906
  }
920
907
  await upload(found, host, clientCoverage, creds.apiUrl, { apiKey: creds.apiKey, shieldId: creds.shieldId, shieldKey: creds.shieldKey, preferApiKey: !!args.apiKey }, args.connectorName, uploadExtras);
921
908
  }
909
+ if (args.json === 'true') {
910
+ await maybeUpload();
911
+ console.log(JSON.stringify({
912
+ host,
913
+ surfaces: [...surfaces],
914
+ scannedFiles: scanned.map(s => `${s.source} → ${s.path}`),
915
+ clientCoverage,
916
+ servers: found,
917
+ secrets,
918
+ agentFiles,
919
+ posture,
920
+ }, null, 2));
921
+ return;
922
+ }
922
923
  if (silent) {
923
924
  if (uploadRequested) {
924
925
  const creds = (0, config_1.resolveCliCredentials)(config, { apiKey: args.apiKey, apiUrl: args.apiUrl });
@@ -402,6 +402,48 @@ function collectEnvFiles(roots, maxDepth) {
402
402
  }
403
403
  return found;
404
404
  }
405
+ function collectProjectCredentialFiles(roots, maxDepth) {
406
+ const found = [];
407
+ const queue = roots.map(dir => ({ dir, depth: 0 }));
408
+ const isCredentialFile = (filePath) => {
409
+ const normalized = filePath.replace(/\\/g, '/').toLowerCase();
410
+ const base = path.basename(normalized);
411
+ return base === '.npmrc'
412
+ || base === '.pypirc'
413
+ || base === '.netrc'
414
+ || normalized.endsWith('/.docker/config.json')
415
+ || normalized.endsWith('/.kube/config')
416
+ || normalized.endsWith('/gcloud/application_default_credentials.json');
417
+ };
418
+ while (queue.length > 0 && found.length < MAX_ENV_FILES) {
419
+ const { dir, depth } = queue.shift();
420
+ let entries;
421
+ try {
422
+ entries = fs.readdirSync(dir, { withFileTypes: true });
423
+ }
424
+ catch {
425
+ continue;
426
+ }
427
+ for (const entry of entries) {
428
+ if (found.length >= MAX_ENV_FILES)
429
+ break;
430
+ const full = path.join(dir, entry.name);
431
+ if (entry.isDirectory()) {
432
+ if (depth >= maxDepth)
433
+ continue;
434
+ if (SKIP_DIR_NAMES.has(entry.name))
435
+ continue;
436
+ if (entry.name.startsWith('.') && !['.cursor', '.claude', '.codex', '.vscode', '.docker', '.kube', '.config'].includes(entry.name))
437
+ continue;
438
+ queue.push({ dir: full, depth: depth + 1 });
439
+ continue;
440
+ }
441
+ if (entry.isFile() && isCredentialFile(full))
442
+ found.push(full);
443
+ }
444
+ }
445
+ return found;
446
+ }
405
447
  function scanSecrets(options = {}) {
406
448
  const home = os.homedir();
407
449
  const cwd = options.cwd || process.cwd();
@@ -451,6 +493,16 @@ function scanSecrets(options = {}) {
451
493
  scannedFiles += 1;
452
494
  scanTextLines(envFile, content, 'env_file', findings, seen);
453
495
  }
496
+ for (const credentialFile of collectProjectCredentialFiles([cwd, ...extraRoots], maxDepth)) {
497
+ if (findings.length >= MAX_FINDINGS)
498
+ break;
499
+ const content = readTextFile(credentialFile);
500
+ if (!content)
501
+ continue;
502
+ scannedFiles += 1;
503
+ scanTextLines(credentialFile, content, 'credential_store', findings, seen);
504
+ scanCredentialStorePosture(credentialFile, content, 'credential_store', findings, seen);
505
+ }
454
506
  // MCP/client config files are already discovered by the MCP inventory pass.
455
507
  // Scan only those known files for embedded env/header/arg secrets; this catches
456
508
  // real-world mistakes like GitHub/Slack tokens in MCP `env`, DB URLs in `args`,
@@ -759,6 +759,7 @@ class McpGatewayServer {
759
759
  shieldKey: this.gatewayConfig.shieldKey,
760
760
  developerName: this.gatewayConfig.developerName,
761
761
  machineName: os.hostname(),
762
+ force: true,
762
763
  });
763
764
  if (bundle.source !== 'default')
764
765
  expectedPolicyHash = bundle.policyHash || bundle.version;
@@ -1159,7 +1160,7 @@ async function installMcpGatewayCommand(args, config) {
1159
1160
  shieldId: args.shieldId,
1160
1161
  shieldKey: args.shieldKey,
1161
1162
  apiUrl: args.apiUrl,
1162
- }, { requireOrganizationId: false });
1163
+ }, { requireApiKey: false, requireOrganizationId: false });
1163
1164
  const cursorProject = args.cursorProject === 'true';
1164
1165
  const selection = parseClientList(args.clients);
1165
1166
  const clients = selection === 'auto'
@@ -1748,7 +1749,7 @@ function protectAllTargetFiles(extra, allowedClientKeys) {
1748
1749
  return files;
1749
1750
  }
1750
1751
  async function protectAllCommand(args, config) {
1751
- (0, config_1.requireCliSetup)(config, { shieldId: args.shieldId, shieldKey: args.shieldKey, apiUrl: args.apiUrl }, { requireOrganizationId: false });
1752
+ (0, config_1.requireCliSetup)(config, { shieldId: args.shieldId, shieldKey: args.shieldKey, apiUrl: args.apiUrl }, { requireApiKey: false, requireOrganizationId: false });
1752
1753
  const gatewayConfig = resolveGatewayConfig(args, config);
1753
1754
  const dryRun = args.dryRun === 'true';
1754
1755
  const allowedClientKeys = resolveProtectClientKeys(args.clients);
package/dist/version.json CHANGED
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": "1.14.16"
2
+ "version": "1.14.17"
3
3
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fullcourtdefense-cli",
3
- "version": "1.14.16",
3
+ "version": "1.14.17",
4
4
  "description": "Full Court Defense CLI — security scanning for AI agents from your terminal",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -26,6 +26,7 @@
26
26
  "test:discover-stdio-mcp": "npm run build && node scripts/test-discover-stdio-mcp-tools.js",
27
27
  "test:per-server-agent-name": "npm run build && node scripts/test-per-server-agent-name.js",
28
28
  "test:remote-mcp-gateway": "npm run build && node scripts/test-remote-mcp-gateway.js",
29
+ "test:e2e-onboarding-personas": "npm run build && node scripts/test-e2e-onboarding-personas.js",
29
30
  "test:posture-blast": "npm run build && node scripts/test-posture-blast-radius.js",
30
31
  "test:ping-e2e": "npm run build && node scripts/test-ping-e2e.js",
31
32
  "prepublishOnly": "npm run build"