@activemind/scd 1.4.0

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 (79) hide show
  1. package/LICENSE.md +35 -0
  2. package/README.md +417 -0
  3. package/bin/scd.js +140 -0
  4. package/lib/audit-report.js +93 -0
  5. package/lib/audit-sync.js +172 -0
  6. package/lib/audit.js +356 -0
  7. package/lib/cli-helpers.js +108 -0
  8. package/lib/commands/accept.js +28 -0
  9. package/lib/commands/audit.js +17 -0
  10. package/lib/commands/configure.js +200 -0
  11. package/lib/commands/doctor.js +14 -0
  12. package/lib/commands/exceptions.js +19 -0
  13. package/lib/commands/export-findings.js +46 -0
  14. package/lib/commands/findings.js +306 -0
  15. package/lib/commands/ignore.js +28 -0
  16. package/lib/commands/init.js +16 -0
  17. package/lib/commands/insights.js +24 -0
  18. package/lib/commands/install.js +15 -0
  19. package/lib/commands/list.js +109 -0
  20. package/lib/commands/remove.js +16 -0
  21. package/lib/commands/repo.js +862 -0
  22. package/lib/commands/report.js +234 -0
  23. package/lib/commands/resolve.js +25 -0
  24. package/lib/commands/rules.js +185 -0
  25. package/lib/commands/scan.js +519 -0
  26. package/lib/commands/scope.js +341 -0
  27. package/lib/commands/sync.js +40 -0
  28. package/lib/commands/uninstall.js +15 -0
  29. package/lib/commands/version.js +33 -0
  30. package/lib/comment-map.js +388 -0
  31. package/lib/config.js +325 -0
  32. package/lib/context-modifiers.js +211 -0
  33. package/lib/deep-analyzer.js +225 -0
  34. package/lib/doctor.js +236 -0
  35. package/lib/exception-manager.js +675 -0
  36. package/lib/export-findings.js +376 -0
  37. package/lib/file-context.js +380 -0
  38. package/lib/file-filter.js +204 -0
  39. package/lib/file-manifest.js +145 -0
  40. package/lib/git-utils.js +102 -0
  41. package/lib/global-config.js +239 -0
  42. package/lib/hooks-manager.js +130 -0
  43. package/lib/init-repo.js +147 -0
  44. package/lib/insights-analyzer.js +416 -0
  45. package/lib/insights-output.js +160 -0
  46. package/lib/installer.js +128 -0
  47. package/lib/output-constants.js +32 -0
  48. package/lib/output-terminal.js +407 -0
  49. package/lib/push-queue.js +322 -0
  50. package/lib/remove-repo.js +108 -0
  51. package/lib/repo-context.js +187 -0
  52. package/lib/report-html.js +1154 -0
  53. package/lib/report-index.js +157 -0
  54. package/lib/report-json.js +136 -0
  55. package/lib/report-markdown.js +250 -0
  56. package/lib/resolve-manager.js +148 -0
  57. package/lib/rule-registry.js +205 -0
  58. package/lib/scan-cache.js +171 -0
  59. package/lib/scan-context.js +312 -0
  60. package/lib/scan-schema.js +67 -0
  61. package/lib/scanner-full.js +681 -0
  62. package/lib/scanner-manual.js +348 -0
  63. package/lib/scanner-secrets.js +83 -0
  64. package/lib/scope.js +331 -0
  65. package/lib/store-verify.js +395 -0
  66. package/lib/store.js +310 -0
  67. package/lib/taint-register.js +196 -0
  68. package/lib/version-check.js +46 -0
  69. package/package.json +37 -0
  70. package/rules/rule-loader.js +324 -0
  71. package/rules/rules-aspx-cs.json +399 -0
  72. package/rules/rules-aspx.json +222 -0
  73. package/rules/rules-infra-leakage.json +434 -0
  74. package/rules/rules-js.json +664 -0
  75. package/rules/rules-php.json +521 -0
  76. package/rules/rules-python.json +466 -0
  77. package/rules/rules-secrets.json +99 -0
  78. package/rules/rules-sensitive-files.json +475 -0
  79. package/rules/rules-ts.json +76 -0
@@ -0,0 +1,109 @@
1
+ 'use strict';
2
+ const { RESET, BOLD, DIM, RED, YELLOW } = require('../output-constants');
3
+ // lib/commands/list.js
4
+
5
+ module.exports = { register };
6
+
7
+ function register(program) {
8
+ const { Command } = require('commander');
9
+
10
+ const listCmd = new Command('list')
11
+ .description('List all repos registered with Secure Code by Design')
12
+ .option('--json', 'Output as JSON')
13
+ .action((opts) => {
14
+ const store = require('../store');
15
+ const repos = store.listRepos();
16
+
17
+ if (opts.json) {
18
+ console.log(JSON.stringify(repos, null, 2));
19
+ return;
20
+ }
21
+
22
+ if (repos.length === 0) {
23
+ console.log(DIM + '\n No repos found. Run scd init in a project to get started.' + RESET + '\n');
24
+ return;
25
+ }
26
+
27
+ const { cacheAge } = require('../scan-cache');
28
+
29
+ console.log('\n' + BOLD + 'Secure Code by Design – Known repos' + RESET);
30
+ console.log(DIM + '─'.repeat(72) + RESET);
31
+
32
+ const namW = 24, scanW = 18, findW = 10;
33
+ console.log(
34
+ DIM +
35
+ 'Name'.padEnd(namW) +
36
+ 'Last scan'.padEnd(scanW) +
37
+ 'Findings'.padEnd(findW) +
38
+ 'Type'.padEnd(10) +
39
+ 'Store ID' +
40
+ RESET
41
+ );
42
+ console.log(DIM + '─'.repeat(72) + RESET);
43
+
44
+ for (const r of repos.sort((a, b) => (b.lastSeen || '').localeCompare(a.lastSeen || ''))) {
45
+ const name = (r.name || r.repoId).slice(0, namW - 1).padEnd(namW);
46
+ const lastScan = r.lastScan ? cacheAge(r.lastScan).padEnd(scanW) : DIM + '(never)' + RESET.padEnd(scanW + 8);
47
+ const findings = r.lastScanFindings != null
48
+ ? (String(r.lastScanFindings) + (r.lastScanCritical ? ' ' + RED + '(' + r.lastScanCritical + 'C)' + RESET : '')).padEnd(findW + (r.lastScanCritical ? 12 : 0))
49
+ : DIM + '–' + RESET.padEnd(findW + 4);
50
+ const type = r.type === 'path-based' ? YELLOW + 'path' + RESET + ' ' : DIM + 'git' + RESET + ' ';
51
+ const id = DIM + r.repoId + RESET;
52
+
53
+ console.log(name + lastScan + findings + type + id);
54
+ }
55
+ console.log();
56
+
57
+ const pathBased = repos.filter(r => r.type === 'path-based');
58
+ if (pathBased.length > 0) {
59
+ console.log(YELLOW + '⚠ ' + pathBased.length + ' repo(s) use path-based IDs (no git remote).');
60
+ console.log(' IDs may change if the folder is renamed or moved.' + RESET + '\n');
61
+ }
62
+ });
63
+
64
+ // ── scd list verify ────────────────────────────────────────────────────────
65
+ const listVerifyCmd = new Command('verify')
66
+ .description('Verify all registered repos still exist on disk')
67
+ .option('--clean', 'Interactive cleanup of missing/stale repos')
68
+ .option('--verbose', 'Show detail lines for each issue')
69
+ .option('--json', 'Output results as JSON')
70
+ .action(async (opts) => {
71
+ const { verifyAll, renderResults, promptClean } = require('../store-verify');
72
+ const results = verifyAll();
73
+
74
+ if (results.length === 0) {
75
+ console.log(DIM + ' No repos found in store.' + RESET + '\n');
76
+ return;
77
+ }
78
+
79
+ if (opts.json) {
80
+ console.log(JSON.stringify(results.map(r => ({
81
+ repoId: r.repoId,
82
+ name: r.name,
83
+ status: r.status,
84
+ localPath: r.localPath,
85
+ remote: r.remote,
86
+ type: r.type,
87
+ daysSinceLastSeen: r.daysSinceLastSeen,
88
+ lastScan: r.lastScan,
89
+ detail: r.detail,
90
+ stats: r.stats,
91
+ })), null, 2));
92
+ return;
93
+ }
94
+
95
+ const issues = results.filter(r => r.status !== 'OK');
96
+ console.log('\n' + BOLD + 'Secure Code by Design – Store verify' + RESET);
97
+ console.log(DIM + '─'.repeat(60) + RESET);
98
+ console.log(DIM + ' Checking ' + results.length + ' repo' + (results.length !== 1 ? 's' : '') + ' in store…' + RESET);
99
+
100
+ renderResults(results, { verbose: opts.verbose || opts.clean });
101
+
102
+ if (opts.clean && issues.length > 0) {
103
+ await promptClean(results);
104
+ }
105
+ });
106
+
107
+ listCmd.addCommand(listVerifyCmd);
108
+ program.addCommand(listCmd);
109
+ }
@@ -0,0 +1,16 @@
1
+ 'use strict';
2
+ // lib/commands/remove.js
3
+
4
+ module.exports = { register };
5
+
6
+ function register(program) {
7
+ program
8
+ .command('remove')
9
+ .description('Remove this repo from scd — marks as inactive and optionally deletes scan history')
10
+ .action(async () => {
11
+ const { removeRepo } = require('../remove-repo');
12
+ const { getRepoRoot } = require('../config');
13
+ const repoRoot = getRepoRoot();
14
+ await removeRepo(repoRoot);
15
+ });
16
+ }