@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.
- package/LICENSE.md +35 -0
- package/README.md +417 -0
- package/bin/scd.js +140 -0
- package/lib/audit-report.js +93 -0
- package/lib/audit-sync.js +172 -0
- package/lib/audit.js +356 -0
- package/lib/cli-helpers.js +108 -0
- package/lib/commands/accept.js +28 -0
- package/lib/commands/audit.js +17 -0
- package/lib/commands/configure.js +200 -0
- package/lib/commands/doctor.js +14 -0
- package/lib/commands/exceptions.js +19 -0
- package/lib/commands/export-findings.js +46 -0
- package/lib/commands/findings.js +306 -0
- package/lib/commands/ignore.js +28 -0
- package/lib/commands/init.js +16 -0
- package/lib/commands/insights.js +24 -0
- package/lib/commands/install.js +15 -0
- package/lib/commands/list.js +109 -0
- package/lib/commands/remove.js +16 -0
- package/lib/commands/repo.js +862 -0
- package/lib/commands/report.js +234 -0
- package/lib/commands/resolve.js +25 -0
- package/lib/commands/rules.js +185 -0
- package/lib/commands/scan.js +519 -0
- package/lib/commands/scope.js +341 -0
- package/lib/commands/sync.js +40 -0
- package/lib/commands/uninstall.js +15 -0
- package/lib/commands/version.js +33 -0
- package/lib/comment-map.js +388 -0
- package/lib/config.js +325 -0
- package/lib/context-modifiers.js +211 -0
- package/lib/deep-analyzer.js +225 -0
- package/lib/doctor.js +236 -0
- package/lib/exception-manager.js +675 -0
- package/lib/export-findings.js +376 -0
- package/lib/file-context.js +380 -0
- package/lib/file-filter.js +204 -0
- package/lib/file-manifest.js +145 -0
- package/lib/git-utils.js +102 -0
- package/lib/global-config.js +239 -0
- package/lib/hooks-manager.js +130 -0
- package/lib/init-repo.js +147 -0
- package/lib/insights-analyzer.js +416 -0
- package/lib/insights-output.js +160 -0
- package/lib/installer.js +128 -0
- package/lib/output-constants.js +32 -0
- package/lib/output-terminal.js +407 -0
- package/lib/push-queue.js +322 -0
- package/lib/remove-repo.js +108 -0
- package/lib/repo-context.js +187 -0
- package/lib/report-html.js +1154 -0
- package/lib/report-index.js +157 -0
- package/lib/report-json.js +136 -0
- package/lib/report-markdown.js +250 -0
- package/lib/resolve-manager.js +148 -0
- package/lib/rule-registry.js +205 -0
- package/lib/scan-cache.js +171 -0
- package/lib/scan-context.js +312 -0
- package/lib/scan-schema.js +67 -0
- package/lib/scanner-full.js +681 -0
- package/lib/scanner-manual.js +348 -0
- package/lib/scanner-secrets.js +83 -0
- package/lib/scope.js +331 -0
- package/lib/store-verify.js +395 -0
- package/lib/store.js +310 -0
- package/lib/taint-register.js +196 -0
- package/lib/version-check.js +46 -0
- package/package.json +37 -0
- package/rules/rule-loader.js +324 -0
- package/rules/rules-aspx-cs.json +399 -0
- package/rules/rules-aspx.json +222 -0
- package/rules/rules-infra-leakage.json +434 -0
- package/rules/rules-js.json +664 -0
- package/rules/rules-php.json +521 -0
- package/rules/rules-python.json +466 -0
- package/rules/rules-secrets.json +99 -0
- package/rules/rules-sensitive-files.json +475 -0
- 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
|
+
}
|