@scantrix/cli 1.0.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 +21 -0
- package/README.md +219 -0
- package/dist/astConfigParser.js +308 -0
- package/dist/astRuleHelpers.js +1451 -0
- package/dist/auditConfig.js +81 -0
- package/dist/ciExtractor.js +327 -0
- package/dist/cli.js +156 -0
- package/dist/configExtractor.js +261 -0
- package/dist/cypressExtractor.js +217 -0
- package/dist/diffTracker.js +310 -0
- package/dist/report.js +1904 -0
- package/dist/sarifFormatter.js +88 -0
- package/dist/scanResult.js +45 -0
- package/dist/scanner.js +3519 -0
- package/dist/scoring.js +206 -0
- package/dist/sinks/index.js +29 -0
- package/dist/sinks/jsonSink.js +28 -0
- package/dist/sinks/types.js +2 -0
- package/docs/high-res-icon.svg +26 -0
- package/docs/scantrix-logo-light.svg +64 -0
- package/docs/scantrix-logo.svg +64 -0
- package/package.json +55 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toSarif = toSarif;
|
|
4
|
+
function toSarifLevel(severity) {
|
|
5
|
+
switch (severity) {
|
|
6
|
+
case "high":
|
|
7
|
+
return "error";
|
|
8
|
+
case "medium":
|
|
9
|
+
return "warning";
|
|
10
|
+
case "low":
|
|
11
|
+
return "note";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Convert ScanResults into a SARIF 2.1.0 document.
|
|
16
|
+
* Usable with GitHub Code Scanning, Azure DevOps, and VS Code SARIF Viewer.
|
|
17
|
+
*/
|
|
18
|
+
function toSarif(results) {
|
|
19
|
+
const repoPath = results.repoPath.replace(/\\/g, "/");
|
|
20
|
+
// Deduplicate rules by findingId
|
|
21
|
+
const seenRuleIds = new Set();
|
|
22
|
+
const rules = [];
|
|
23
|
+
for (const f of results.findings) {
|
|
24
|
+
if (seenRuleIds.has(f.findingId))
|
|
25
|
+
continue;
|
|
26
|
+
seenRuleIds.add(f.findingId);
|
|
27
|
+
const rule = {
|
|
28
|
+
id: f.findingId,
|
|
29
|
+
shortDescription: { text: f.title },
|
|
30
|
+
fullDescription: { text: f.description },
|
|
31
|
+
defaultConfiguration: { level: toSarifLevel(f.severity) },
|
|
32
|
+
help: { text: f.recommendation, markdown: f.recommendation },
|
|
33
|
+
};
|
|
34
|
+
if (f.baseSeverity) {
|
|
35
|
+
rule.properties = {
|
|
36
|
+
baseSeverity: f.baseSeverity,
|
|
37
|
+
escalationReason: f.escalationReason,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
rules.push(rule);
|
|
41
|
+
}
|
|
42
|
+
const sarifResults = [];
|
|
43
|
+
for (const f of results.findings) {
|
|
44
|
+
for (const e of f.evidence) {
|
|
45
|
+
const uri = e.file.replace(/\\/g, "/");
|
|
46
|
+
// Make path relative to repo root when possible
|
|
47
|
+
const relativeUri = uri.startsWith(repoPath)
|
|
48
|
+
? uri.slice(repoPath.length + 1)
|
|
49
|
+
: uri;
|
|
50
|
+
// Skip synthetic/summary evidence that doesn't point to real files
|
|
51
|
+
if (relativeUri.includes("(CI summary)") ||
|
|
52
|
+
relativeUri.includes("(correlation") ||
|
|
53
|
+
relativeUri.includes("(analysis summary)")) {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
sarifResults.push({
|
|
57
|
+
ruleId: f.findingId,
|
|
58
|
+
level: toSarifLevel(f.severity),
|
|
59
|
+
message: { text: `${f.title}: ${e.snippet}` },
|
|
60
|
+
locations: [
|
|
61
|
+
{
|
|
62
|
+
physicalLocation: {
|
|
63
|
+
artifactLocation: { uri: relativeUri },
|
|
64
|
+
region: { startLine: Math.max(e.line, 1) },
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
$schema: "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/main/sarif-2.1/schema/sarif-schema-2.1.0.json",
|
|
73
|
+
version: "2.1.0",
|
|
74
|
+
runs: [
|
|
75
|
+
{
|
|
76
|
+
tool: {
|
|
77
|
+
driver: {
|
|
78
|
+
name: "scantrix",
|
|
79
|
+
version: "6.3.0",
|
|
80
|
+
informationUri: "https://github.com/scantrix/scantrix",
|
|
81
|
+
rules,
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
results: sarifResults,
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
};
|
|
88
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildScanResult = buildScanResult;
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
5
|
+
const scoring_1 = require("./scoring");
|
|
6
|
+
/**
|
|
7
|
+
* Build a canonical {@link ScanResult} from the raw scanner output.
|
|
8
|
+
*
|
|
9
|
+
* Call this after `scanRepo()` completes. The function deterministically
|
|
10
|
+
* maps the scanner's internal types to the stable external contract.
|
|
11
|
+
*/
|
|
12
|
+
function buildScanResult(raw, opts) {
|
|
13
|
+
const risk = (0, scoring_1.calculateRiskScore)(raw.findings, {
|
|
14
|
+
testFiles: raw.inventory.testFiles,
|
|
15
|
+
cypressTestFiles: raw.inventory.cypressTestFiles,
|
|
16
|
+
seleniumTestFiles: raw.inventory.seleniumTestFiles,
|
|
17
|
+
});
|
|
18
|
+
const effectivePath = opts.repoPath ?? raw.repoPath;
|
|
19
|
+
// Use explicit display name if provided, otherwise derive from path
|
|
20
|
+
const repoName = raw.repoDisplayName ?? (effectivePath.split(/[/\\]/).pop() || "unknown").toLowerCase();
|
|
21
|
+
return {
|
|
22
|
+
tool: "scantrix",
|
|
23
|
+
version: opts.version,
|
|
24
|
+
runId: (0, crypto_1.randomUUID)(),
|
|
25
|
+
startedAt: opts.startedAt,
|
|
26
|
+
completedAt: new Date().toISOString(),
|
|
27
|
+
repo: {
|
|
28
|
+
path: effectivePath,
|
|
29
|
+
name: repoName,
|
|
30
|
+
branch: raw.gitBranch,
|
|
31
|
+
commit: raw.gitCommit,
|
|
32
|
+
},
|
|
33
|
+
findings: raw.findings,
|
|
34
|
+
summary: {
|
|
35
|
+
total: raw.findings.length,
|
|
36
|
+
high: raw.findings.filter(f => f.severity === "high").length,
|
|
37
|
+
medium: raw.findings.filter(f => f.severity === "medium").length,
|
|
38
|
+
low: raw.findings.filter(f => f.severity === "low").length,
|
|
39
|
+
riskScore: risk.riskScore,
|
|
40
|
+
riskGrade: risk.grade,
|
|
41
|
+
densityAdjustment: risk.densityInfo,
|
|
42
|
+
},
|
|
43
|
+
inventory: raw.inventory,
|
|
44
|
+
};
|
|
45
|
+
}
|