@sectorzero/cli 0.0.0-stage → 1.0.5

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/dist/index.js ADDED
@@ -0,0 +1,225 @@
1
+ #!/usr/bin/env Node
2
+ #!/usr/bin/env node
3
+ "use strict";
4
+ var __create = Object.create;
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
+ var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getProtoOf = Object.getPrototypeOf;
9
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
19
+ // If the importer is in node compatibility mode or this is not an ESM
20
+ // file that has been converted to a CommonJS file using a Babel-
21
+ // compatible transform (i.e. "__esModule" has not been set), then set
22
+ // "default" to the CommonJS "module.exports" for node compatibility.
23
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
24
+ mod
25
+ ));
26
+
27
+ // src/index.ts
28
+ var import_commander = require("commander");
29
+ var import_picocolors = __toESM(require("picocolors"));
30
+ var import_ora = __toESM(require("ora"));
31
+ var path = __toESM(require("path"));
32
+ var fs = __toESM(require("fs"));
33
+ var import_engine_scanner = require("@sectorzero/engine-scanner");
34
+ var import_engine_analyzer = require("@sectorzero/engine-analyzer");
35
+ var import_engine_fixer = require("@sectorzero/engine-fixer");
36
+
37
+ // src/sarif.ts
38
+ function generateSarifReport(findings, rootDir) {
39
+ const ruleMap = /* @__PURE__ */ new Map();
40
+ for (const finding of findings) {
41
+ if (!ruleMap.has(finding.ruleId)) {
42
+ ruleMap.set(finding.ruleId, finding);
43
+ }
44
+ }
45
+ const sarifRules = Array.from(ruleMap.values()).map((finding) => {
46
+ let level = "warning";
47
+ if (finding.severity === "CRITICAL" || finding.severity === "HIGH") {
48
+ level = "error";
49
+ }
50
+ return {
51
+ id: finding.ruleId,
52
+ name: finding.ruleId,
53
+ shortDescription: {
54
+ text: finding.detailedExplanation?.summary || `Vulnerability detected: ${finding.ruleId}`
55
+ },
56
+ fullDescription: {
57
+ text: finding.detailedExplanation?.impact || `Reachable issue found for ${finding.ruleId}.`
58
+ },
59
+ defaultConfiguration: { level },
60
+ help: {
61
+ text: finding.detailedExplanation?.remediationGuide || "Remediate this issue using warden fix.",
62
+ markdown: `**Impact:** ${finding.detailedExplanation?.impact || "High"}
63
+
64
+ **Remediation:** ${finding.detailedExplanation?.remediationGuide || "Move secrets to environment variables or parameterize queries."}`
65
+ }
66
+ };
67
+ });
68
+ const sarifResults = findings.map((finding) => {
69
+ let level = "warning";
70
+ if (finding.severity === "CRITICAL" || finding.severity === "HIGH") {
71
+ level = "error";
72
+ }
73
+ let relativeUri = finding.location.file;
74
+ if (relativeUri.startsWith(rootDir)) {
75
+ relativeUri = relativeUri.replace(rootDir, "").replace(/^[/\\]/, "");
76
+ }
77
+ relativeUri = relativeUri.replace(/\\/g, "/");
78
+ return {
79
+ ruleId: finding.ruleId,
80
+ level,
81
+ message: {
82
+ text: finding.detailedExplanation?.summary || `Reachable ${finding.ruleId} vulnerability.`
83
+ },
84
+ locations: [
85
+ {
86
+ physicalLocation: {
87
+ artifactLocation: { uri: relativeUri },
88
+ region: {
89
+ startLine: finding.location.line || 1,
90
+ startColumn: finding.location.column || 1
91
+ }
92
+ }
93
+ }
94
+ ]
95
+ };
96
+ });
97
+ return {
98
+ $schema: "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
99
+ version: "2.1.0",
100
+ runs: [
101
+ {
102
+ tool: {
103
+ driver: {
104
+ name: "Warden AST Engine",
105
+ version: "1.0.0",
106
+ informationUri: "https://github.com/sectorzero-hq/warden",
107
+ rules: sarifRules
108
+ }
109
+ },
110
+ results: sarifResults
111
+ }
112
+ ]
113
+ };
114
+ }
115
+
116
+ // src/index.ts
117
+ var program = new import_commander.Command();
118
+ function getWidth() {
119
+ return Math.min(process.stdout.columns || 80, 100);
120
+ }
121
+ function centerText(text) {
122
+ const width = getWidth();
123
+ const padding = Math.max(0, Math.floor((width - text.length) / 2));
124
+ return " ".repeat(padding) + text;
125
+ }
126
+ function printHeader(targetPath) {
127
+ const width = getWidth();
128
+ const heavyDivider = import_picocolors.default.cyan("\u2550".repeat(width));
129
+ console.log(`
130
+ ${heavyDivider}`);
131
+ console.log(centerText(import_picocolors.default.bold(import_picocolors.default.cyan("SECTOR ZERO WARDEN CLI"))));
132
+ console.log(centerText(import_picocolors.default.gray(`Target Directory: ${targetPath}`)));
133
+ console.log(`${heavyDivider}
134
+ `);
135
+ }
136
+ program.name("warden").description("Sector Zero Warden - AST Security Scanner & Automated Remediation Pipeline").version("1.0.0");
137
+ program.command("scan").description("Run reachability analysis and AST scan on target directory").argument("[directory]", "Path to source code directory", ".").option("--fix", "Automatically apply AST codemod fixes in-place").option("--json", "Output results in raw JSON format").option("--sarif [outputPath]", "Export findings in SARIF v2.1.0 format (default: warden-results.sarif)").action((directory, options) => {
138
+ const targetDir = path.resolve(process.cwd(), directory);
139
+ if (!fs.existsSync(targetDir)) {
140
+ console.error(import_picocolors.default.red(`Directory not found: ${targetDir}`));
141
+ process.exit(1);
142
+ }
143
+ const isSilentMode = Boolean(options.json || options.sarif);
144
+ const spinner = (0, import_ora.default)({ text: "Scanning source files and building AST graph...", color: "cyan" });
145
+ if (!isSilentMode) {
146
+ printHeader(targetDir);
147
+ spinner.start();
148
+ }
149
+ try {
150
+ const scanner = new import_engine_scanner.ASTScanner();
151
+ const analyzer = new import_engine_analyzer.ReachabilityAnalyzer();
152
+ const fixer = new import_engine_fixer.RemediationEngine();
153
+ const rawFindings = scanner.scanDirectory(targetDir);
154
+ const validatedFindings = analyzer.analyzeRepository(rawFindings);
155
+ const reachableFindings = validatedFindings.filter((f) => f.isReachable);
156
+ if (options.json) {
157
+ console.log(JSON.stringify(validatedFindings, null, 2));
158
+ process.exit(reachableFindings.length > 0 ? 1 : 0);
159
+ }
160
+ if (options.sarif) {
161
+ const sarifLog = generateSarifReport(reachableFindings, targetDir);
162
+ const fileName = typeof options.sarif === "string" ? options.sarif : "warden-results.sarif";
163
+ const outputPath = path.resolve(process.cwd(), fileName);
164
+ fs.writeFileSync(outputPath, JSON.stringify(sarifLog, null, 2), "utf-8");
165
+ console.log(import_picocolors.default.green(`\u2714 Exported SARIF 2.1.0 report to: ${outputPath}`));
166
+ process.exit(reachableFindings.length > 0 ? 1 : 0);
167
+ }
168
+ spinner.succeed(import_picocolors.default.green("Analysis Complete!"));
169
+ console.log(`
170
+ ${import_picocolors.default.bold("Scan Summary:")}`);
171
+ console.log(` \u2022 Candidate Findings Found : ${import_picocolors.default.yellow(rawFindings.length.toString())}`);
172
+ console.log(
173
+ ` \u2022 Reachable Vulnerabilities: ${reachableFindings.length > 0 ? import_picocolors.default.red(reachableFindings.length.toString()) : import_picocolors.default.green("0")}
174
+ `
175
+ );
176
+ let successCount = 0;
177
+ let failCount = 0;
178
+ if (reachableFindings.length > 0) {
179
+ console.log(import_picocolors.default.bold(options.fix ? import_picocolors.default.yellow("Remediating Vulnerabilities:") : import_picocolors.default.red("Reachable Vulnerabilities Detected:")));
180
+ for (const finding of reachableFindings) {
181
+ if (options.fix) {
182
+ const fixResult = fixer.applyFixToFile(finding.location.file, finding);
183
+ const statusTag = fixResult.success ? import_picocolors.default.bgGreen(import_picocolors.default.black(import_picocolors.default.bold(" FIXED "))) : import_picocolors.default.bgRed(import_picocolors.default.white(import_picocolors.default.bold(" FAILED ")));
184
+ if (fixResult.success) successCount++;
185
+ else failCount++;
186
+ console.log(`
187
+ ${statusTag} ${import_picocolors.default.bold(finding.ruleId)}`);
188
+ console.log(` \u2022 File: ${import_picocolors.default.cyan(`${finding.location.file}:${finding.location.line}:${finding.location.column}`)}`);
189
+ console.log(` \u2022 Explanation: ${fixResult.explanation}`);
190
+ } else {
191
+ const statusTag = import_picocolors.default.bgRed(import_picocolors.default.white(import_picocolors.default.bold(" DETECTED ")));
192
+ console.log(`
193
+ ${statusTag} ${import_picocolors.default.bold(finding.ruleId)}`);
194
+ console.log(` \u2022 File: ${import_picocolors.default.cyan(`${finding.location.file}:${finding.location.line}:${finding.location.column}`)}`);
195
+ console.log(` \u2022 Category: ${finding.category} | Severity: ${import_picocolors.default.red(finding.severity)}`);
196
+ console.log(` \u2022 Summary: ${finding.detailedExplanation?.summary}`);
197
+ }
198
+ }
199
+ console.log("");
200
+ }
201
+ const heavyDivider = import_picocolors.default.cyan("\u2550".repeat(getWidth()));
202
+ console.log(centerText(import_picocolors.default.bold(import_picocolors.default.magenta("\u2500\u2500\u2500 EXECUTION COMPLETE \u2500\u2500\u2500"))));
203
+ if (options.fix) {
204
+ console.log(
205
+ centerText(
206
+ `Patched: ${import_picocolors.default.bold(import_picocolors.default.green(successCount.toString()))} \u2502 Failed: ${import_picocolors.default.bold(failCount > 0 ? import_picocolors.default.red(failCount.toString()) : import_picocolors.default.gray(failCount.toString()))}`
207
+ )
208
+ );
209
+ } else {
210
+ console.log(
211
+ centerText(
212
+ `Total Vulnerabilities: ${import_picocolors.default.bold(import_picocolors.default.red(reachableFindings.length.toString()))} (Run with --fix to remediate)`
213
+ )
214
+ );
215
+ }
216
+ console.log(`${heavyDivider}
217
+ `);
218
+ process.exit(reachableFindings.length > 0 && !options.fix ? 1 : 0);
219
+ } catch (err) {
220
+ if (spinner.isSpinning) spinner.fail(import_picocolors.default.red(`Scan failed: ${err.message}`));
221
+ else console.error(import_picocolors.default.red(`Scan failed: ${err.message}`));
222
+ process.exit(1);
223
+ }
224
+ });
225
+ program.parse(process.argv);
package/package.json CHANGED
@@ -1,6 +1,32 @@
1
- {
2
- "name": "@sectorzero/cli",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
1
+ {
2
+ "name": "@sectorzero/cli",
3
+ "version": "1.0.5",
4
+ "private": false,
5
+ "bin": {
6
+ "warden": "./dist/index.js",
7
+ "@sectorzero/cli": "./dist/index.js"
8
+ },
9
+ "main": "./dist/index.js",
10
+ "scripts": {
11
+ "build": "tsup src/index.ts --format cjs --clean",
12
+ "dev": "tsup src/index.ts --format cjs --watch"
13
+ },
14
+ "publishConfig": {
15
+ "access": "public",
16
+ "git-checks": false
17
+ },
18
+ "dependencies": {
19
+ "@sectorzero/engine-analyzer": "workspace:*",
20
+ "@sectorzero/engine-fixer": "workspace:*",
21
+ "@sectorzero/engine-scanner": "workspace:*",
22
+ "@sectorzero/shared-types": "workspace:*",
23
+ "commander": "^15.0.0",
24
+ "ora": "^9.4.1",
25
+ "picocolors": "^1.1.1"
26
+ },
27
+ "devDependencies": {
28
+ "@types/node": "^26.6.5",
29
+ "tsup": "^9.0.0",
30
+ "typescript": "^5.9.3"
31
+ }
32
+ }
package/src/index.ts ADDED
@@ -0,0 +1,154 @@
1
+ #!/usr/bin/env Node
2
+ // packages/cli/src/index.ts
3
+ import { Command } from 'commander';
4
+ import pc from 'picocolors';
5
+ import ora from 'ora';
6
+ import * as path from 'path';
7
+ import * as fs from 'fs';
8
+ import { ASTScanner } from '@sectorzero/engine-scanner';
9
+ import { ReachabilityAnalyzer } from '@sectorzero/engine-analyzer';
10
+ import { RemediationEngine } from '@sectorzero/engine-fixer';
11
+ import { generateSarifReport } from './sarif';
12
+
13
+ const program = new Command();
14
+
15
+ function getWidth(): number {
16
+ return Math.min(process.stdout.columns || 80, 100);
17
+ }
18
+
19
+ function centerText(text: string): string {
20
+ const width = getWidth();
21
+ const padding = Math.max(0, Math.floor((width - text.length) / 2));
22
+ return ' '.repeat(padding) + text;
23
+ }
24
+
25
+ function printHeader(targetPath: string): void {
26
+ const width = getWidth();
27
+ const heavyDivider = pc.cyan('═'.repeat(width));
28
+ console.log(`\n${heavyDivider}`);
29
+ console.log(centerText(pc.bold(pc.cyan('SECTOR ZERO WARDEN CLI'))));
30
+ console.log(centerText(pc.gray(`Target Directory: ${targetPath}`)));
31
+ console.log(`${heavyDivider}\n`);
32
+ }
33
+
34
+ program
35
+ .name('warden')
36
+ .description('Sector Zero Warden - AST Security Scanner & Automated Remediation Pipeline')
37
+ .version('1.0.0');
38
+
39
+ program
40
+ .command('scan')
41
+ .description('Run reachability analysis and AST scan on target directory')
42
+ .argument('[directory]', 'Path to source code directory', '.')
43
+ .option('--fix', 'Automatically apply AST codemod fixes in-place')
44
+ .option('--json', 'Output results in raw JSON format')
45
+ .option('--sarif [outputPath]', 'Export findings in SARIF v2.1.0 format (default: warden-results.sarif)')
46
+ .action((directory: string, options: { fix?: boolean; json?: boolean; sarif?: boolean | string }) => {
47
+ const targetDir = path.resolve(process.cwd(), directory);
48
+
49
+ if (!fs.existsSync(targetDir)) {
50
+ console.error(pc.red(`Directory not found: ${targetDir}`));
51
+ process.exit(1);
52
+ }
53
+
54
+ const isSilentMode = Boolean(options.json || options.sarif);
55
+ const spinner = ora({ text: 'Scanning source files and building AST graph...', color: 'cyan' });
56
+
57
+ if (!isSilentMode) {
58
+ printHeader(targetDir);
59
+ spinner.start();
60
+ }
61
+
62
+ try {
63
+ const scanner = new ASTScanner();
64
+ const analyzer = new ReachabilityAnalyzer();
65
+ const fixer = new RemediationEngine();
66
+
67
+ const rawFindings = scanner.scanDirectory(targetDir);
68
+ const validatedFindings = analyzer.analyzeRepository(rawFindings);
69
+ const reachableFindings = validatedFindings.filter((f) => f.isReachable);
70
+
71
+ // JSON Output Export
72
+ if (options.json) {
73
+ console.log(JSON.stringify(validatedFindings, null, 2));
74
+ process.exit(reachableFindings.length > 0 ? 1 : 0);
75
+ }
76
+
77
+ // SARIF 2.1.0 Export
78
+ if (options.sarif) {
79
+ const sarifLog = generateSarifReport(reachableFindings, targetDir);
80
+ const fileName = typeof options.sarif === 'string' ? options.sarif : 'warden-results.sarif';
81
+ const outputPath = path.resolve(process.cwd(), fileName);
82
+
83
+ fs.writeFileSync(outputPath, JSON.stringify(sarifLog, null, 2), 'utf-8');
84
+ console.log(pc.green(`✔ Exported SARIF 2.1.0 report to: ${outputPath}`));
85
+ process.exit(reachableFindings.length > 0 ? 1 : 0);
86
+ }
87
+
88
+ spinner.succeed(pc.green('Analysis Complete!'));
89
+
90
+ console.log(`\n${pc.bold('Scan Summary:')}`);
91
+ console.log(` • Candidate Findings Found : ${pc.yellow(rawFindings.length.toString())}`);
92
+ console.log(
93
+ ` • Reachable Vulnerabilities: ${
94
+ reachableFindings.length > 0 ? pc.red(reachableFindings.length.toString()) : pc.green('0')
95
+ }\n`
96
+ );
97
+
98
+ let successCount = 0;
99
+ let failCount = 0;
100
+
101
+ if (reachableFindings.length > 0) {
102
+ console.log(pc.bold(options.fix ? pc.yellow('Remediating Vulnerabilities:') : pc.red('Reachable Vulnerabilities Detected:')));
103
+
104
+ for (const finding of reachableFindings) {
105
+ if (options.fix) {
106
+ const fixResult = fixer.applyFixToFile(finding.location.file, finding);
107
+
108
+ const statusTag = fixResult.success
109
+ ? pc.bgGreen(pc.black(pc.bold(' FIXED ')))
110
+ : pc.bgRed(pc.white(pc.bold(' FAILED ')));
111
+
112
+ if (fixResult.success) successCount++;
113
+ else failCount++;
114
+
115
+ console.log(`\n ${statusTag} ${pc.bold(finding.ruleId)}`);
116
+ console.log(` • File: ${pc.cyan(`${finding.location.file}:${finding.location.line}:${finding.location.column}`)}`);
117
+ console.log(` • Explanation: ${fixResult.explanation}`);
118
+ } else {
119
+ const statusTag = pc.bgRed(pc.white(pc.bold(' DETECTED ')));
120
+ console.log(`\n ${statusTag} ${pc.bold(finding.ruleId)}`);
121
+ console.log(` • File: ${pc.cyan(`${finding.location.file}:${finding.location.line}:${finding.location.column}`)}`);
122
+ console.log(` • Category: ${finding.category} | Severity: ${pc.red(finding.severity)}`);
123
+ console.log(` • Summary: ${finding.detailedExplanation?.summary}`);
124
+ }
125
+ }
126
+ console.log('');
127
+ }
128
+
129
+ const heavyDivider = pc.cyan('═'.repeat(getWidth()));
130
+ console.log(centerText(pc.bold(pc.magenta('─── EXECUTION COMPLETE ───'))));
131
+ if (options.fix) {
132
+ console.log(
133
+ centerText(
134
+ `Patched: ${pc.bold(pc.green(successCount.toString()))} │ Failed: ${pc.bold(failCount > 0 ? pc.red(failCount.toString()) : pc.gray(failCount.toString()))}`
135
+ )
136
+ );
137
+ } else {
138
+ console.log(
139
+ centerText(
140
+ `Total Vulnerabilities: ${pc.bold(pc.red(reachableFindings.length.toString()))} (Run with --fix to remediate)`
141
+ )
142
+ );
143
+ }
144
+ console.log(`${heavyDivider}\n`);
145
+
146
+ process.exit(reachableFindings.length > 0 && !options.fix ? 1 : 0);
147
+ } catch (err: any) {
148
+ if (spinner.isSpinning) spinner.fail(pc.red(`Scan failed: ${err.message}`));
149
+ else console.error(pc.red(`Scan failed: ${err.message}`));
150
+ process.exit(1);
151
+ }
152
+ });
153
+
154
+ program.parse(process.argv);
package/src/sarif.ts ADDED
@@ -0,0 +1,145 @@
1
+ import { ValidatedFinding } from '@sectorzero/engine-analyzer';
2
+
3
+ export interface SarifLog {
4
+ $schema: string;
5
+ version: string;
6
+ runs: Array<{
7
+ tool: {
8
+ driver: {
9
+ name: string;
10
+ version: string;
11
+ informationUri: string;
12
+ rules: Array<{
13
+ id: string;
14
+ name: string;
15
+ shortDescription: {
16
+ text: string;
17
+ };
18
+ fullDescription: {
19
+ text: string;
20
+ };
21
+ defaultConfiguration: {
22
+ level: 'error' | 'warning' | 'note';
23
+ };
24
+ help: {
25
+ text: string;
26
+ markdown: string;
27
+ };
28
+ }>;
29
+ };
30
+ };
31
+ results: Array<{
32
+ ruleId: string;
33
+ level: 'error' | 'warning' | 'note';
34
+ message: {
35
+ text: string;
36
+ };
37
+ locations: Array<{
38
+ physicalLocation: {
39
+ artifactLocation: {
40
+ uri: string;
41
+ };
42
+ region: {
43
+ startLine: number;
44
+ startColumn: number;
45
+ };
46
+ };
47
+ }>;
48
+ }>;
49
+ }>;
50
+ }
51
+
52
+ export function generateSarifReport(
53
+ findings: ValidatedFinding[],
54
+ rootDir: string
55
+ ): SarifLog {
56
+ const ruleMap = new Map<string, ValidatedFinding>();
57
+
58
+ for (const finding of findings) {
59
+ if (!ruleMap.has(finding.ruleId)) {
60
+ ruleMap.set(finding.ruleId, finding);
61
+ }
62
+ }
63
+
64
+ const sarifRules = Array.from(ruleMap.values()).map((finding) => {
65
+ let level: 'error' | 'warning' | 'note' = 'warning';
66
+ if (finding.severity === 'CRITICAL' || finding.severity === 'HIGH') {
67
+ level = 'error';
68
+ }
69
+
70
+ return {
71
+ id: finding.ruleId,
72
+ name: finding.ruleId,
73
+ shortDescription: {
74
+ text:
75
+ finding.detailedExplanation?.summary ||
76
+ `Vulnerability detected: ${finding.ruleId}`,
77
+ },
78
+ fullDescription: {
79
+ text:
80
+ finding.detailedExplanation?.impact ||
81
+ `Reachable issue found for ${finding.ruleId}.`,
82
+ },
83
+ defaultConfiguration: { level },
84
+ help: {
85
+ text:
86
+ finding.detailedExplanation?.remediationGuide ||
87
+ 'Remediate this issue using warden fix.',
88
+ markdown: `**Impact:** ${finding.detailedExplanation?.impact || 'High'}\n\n**Remediation:** ${
89
+ finding.detailedExplanation?.remediationGuide ||
90
+ 'Move secrets to environment variables or parameterize queries.'
91
+ }`,
92
+ },
93
+ };
94
+ });
95
+
96
+ const sarifResults = findings.map((finding) => {
97
+ let level: 'error' | 'warning' | 'note' = 'warning'
98
+ if (finding.severity === 'CRITICAL' || finding.severity === 'HIGH') {
99
+ level = 'error'
100
+ }
101
+
102
+ let relativeUri = finding.location.file
103
+ if (relativeUri.startsWith(rootDir)) {
104
+ relativeUri = relativeUri.replace(rootDir, '').replace(/^[/\\]/, '')
105
+ }
106
+ relativeUri = relativeUri.replace(/\\/g, '/')
107
+
108
+ return {
109
+ ruleId: finding.ruleId,
110
+ level,
111
+ message: {
112
+ text: finding.detailedExplanation?.summary || `Reachable ${finding.ruleId} vulnerability.`
113
+ },
114
+ locations: [
115
+ {
116
+ physicalLocation: {
117
+ artifactLocation: { uri: relativeUri },
118
+ region: {
119
+ startLine: finding.location.line || 1,
120
+ startColumn: finding.location.column || 1,
121
+ }
122
+ }
123
+ }
124
+ ]
125
+ }
126
+ })
127
+
128
+ return {
129
+ $schema: 'https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json',
130
+ version: '2.1.0',
131
+ runs: [
132
+ {
133
+ tool: {
134
+ driver: {
135
+ name: 'Warden AST Engine',
136
+ version: '1.0.0',
137
+ informationUri: 'https://github.com/sectorzero-hq/warden',
138
+ rules: sarifRules,
139
+ },
140
+ },
141
+ results: sarifResults
142
+ }
143
+ ]
144
+ }
145
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "declaration": true,
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "types": ["node"]
14
+ },
15
+ "include": ["src/**/*"]
16
+ }
package/tsup.config.ts ADDED
@@ -0,0 +1,10 @@
1
+ import {defineConfig} from 'tsup'
2
+
3
+ export default defineConfig({
4
+ entry: ['src/index.js'],
5
+ format: ['cjs'],
6
+ clean: true,
7
+ banner: {
8
+ js: '#!/usr/bin/env node',
9
+ },
10
+ })
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.