sapper-ai 0.2.2 → 0.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/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +128 -4
- package/dist/report.d.ts +3 -0
- package/dist/report.d.ts.map +1 -0
- package/dist/report.js +651 -0
- package/dist/scan.d.ts +30 -0
- package/dist/scan.d.ts.map +1 -1
- package/dist/scan.js +395 -38
- package/package.json +2 -1
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAaA,wBAAsB,MAAM,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,CAiCpF"}
|
package/dist/cli.js
CHANGED
|
@@ -33,12 +33,17 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
return result;
|
|
34
34
|
};
|
|
35
35
|
})();
|
|
36
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
37
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
|
+
};
|
|
36
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
40
|
exports.runCli = runCli;
|
|
38
41
|
const node_fs_1 = require("node:fs");
|
|
39
42
|
const node_child_process_1 = require("node:child_process");
|
|
43
|
+
const node_os_1 = require("node:os");
|
|
40
44
|
const node_path_1 = require("node:path");
|
|
41
45
|
const readline = __importStar(require("node:readline"));
|
|
46
|
+
const select_1 = __importDefault(require("@inquirer/select"));
|
|
42
47
|
const presets_1 = require("./presets");
|
|
43
48
|
const scan_1 = require("./scan");
|
|
44
49
|
async function runCli(argv = process.argv.slice(2)) {
|
|
@@ -52,7 +57,12 @@ async function runCli(argv = process.argv.slice(2)) {
|
|
|
52
57
|
printUsage();
|
|
53
58
|
return 1;
|
|
54
59
|
}
|
|
55
|
-
|
|
60
|
+
const scanOptions = await resolveScanOptions(parsed);
|
|
61
|
+
if (!scanOptions) {
|
|
62
|
+
printUsage();
|
|
63
|
+
return 1;
|
|
64
|
+
}
|
|
65
|
+
return (0, scan_1.runScan)(scanOptions);
|
|
56
66
|
}
|
|
57
67
|
if (argv[0] === 'dashboard') {
|
|
58
68
|
return runDashboard();
|
|
@@ -69,8 +79,15 @@ function printUsage() {
|
|
|
69
79
|
sapper-ai - AI security guardrails
|
|
70
80
|
|
|
71
81
|
Usage:
|
|
72
|
-
sapper-ai scan
|
|
73
|
-
sapper-ai scan
|
|
82
|
+
sapper-ai scan Interactive scan scope (TTY only)
|
|
83
|
+
sapper-ai scan . Current directory only (no subdirectories)
|
|
84
|
+
sapper-ai scan --deep Current directory + subdirectories
|
|
85
|
+
sapper-ai scan --system AI system paths (~/.claude, ~/.cursor, ...)
|
|
86
|
+
sapper-ai scan ./path Scan a specific file/directory
|
|
87
|
+
sapper-ai scan --fix Quarantine blocked files
|
|
88
|
+
sapper-ai scan --ai Deep scan with AI analysis (requires OPENAI_API_KEY)
|
|
89
|
+
sapper-ai scan --report Generate HTML report and open in browser
|
|
90
|
+
sapper-ai scan --no-save Skip saving scan results to ~/.sapperai/scans/
|
|
74
91
|
sapper-ai init Interactive setup wizard
|
|
75
92
|
sapper-ai dashboard Launch web dashboard
|
|
76
93
|
sapper-ai --help Show this help
|
|
@@ -81,17 +98,124 @@ Learn more: https://github.com/sapper-ai/sapperai
|
|
|
81
98
|
function parseScanArgs(argv) {
|
|
82
99
|
const targets = [];
|
|
83
100
|
let fix = false;
|
|
101
|
+
let deep = false;
|
|
102
|
+
let system = false;
|
|
103
|
+
let ai = false;
|
|
104
|
+
let report = false;
|
|
105
|
+
let noSave = false;
|
|
84
106
|
for (const arg of argv) {
|
|
85
107
|
if (arg === '--fix') {
|
|
86
108
|
fix = true;
|
|
87
109
|
continue;
|
|
88
110
|
}
|
|
111
|
+
if (arg === '--deep') {
|
|
112
|
+
deep = true;
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
if (arg === '--system') {
|
|
116
|
+
system = true;
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (arg === '--ai') {
|
|
120
|
+
ai = true;
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if (arg === '--report') {
|
|
124
|
+
report = true;
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
if (arg === '--no-save') {
|
|
128
|
+
noSave = true;
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
89
131
|
if (arg.startsWith('-')) {
|
|
90
132
|
return null;
|
|
91
133
|
}
|
|
92
134
|
targets.push(arg);
|
|
93
135
|
}
|
|
94
|
-
return { targets, fix };
|
|
136
|
+
return { targets, fix, deep, system, ai, report, noSave };
|
|
137
|
+
}
|
|
138
|
+
function displayPath(path) {
|
|
139
|
+
const home = (0, node_os_1.homedir)();
|
|
140
|
+
if (path === home)
|
|
141
|
+
return '~';
|
|
142
|
+
return path.startsWith(home + '/') ? `~/${path.slice(home.length + 1)}` : path;
|
|
143
|
+
}
|
|
144
|
+
async function promptScanScope(cwd) {
|
|
145
|
+
const answer = await (0, select_1.default)({
|
|
146
|
+
message: 'Scan scope:',
|
|
147
|
+
choices: [
|
|
148
|
+
{ name: `Current directory only ${displayPath(cwd)}`, value: 'shallow' },
|
|
149
|
+
{ name: `Current + subdirectories ${displayPath((0, node_path_1.join)(cwd, '**'))}`, value: 'deep' },
|
|
150
|
+
{
|
|
151
|
+
name: 'AI system scan ~/.claude, ~/.cursor, ~/.vscode ...',
|
|
152
|
+
value: 'system',
|
|
153
|
+
},
|
|
154
|
+
],
|
|
155
|
+
default: 'deep',
|
|
156
|
+
});
|
|
157
|
+
return answer;
|
|
158
|
+
}
|
|
159
|
+
async function promptScanDepth() {
|
|
160
|
+
const answer = await (0, select_1.default)({
|
|
161
|
+
message: 'Scan depth:',
|
|
162
|
+
choices: [
|
|
163
|
+
{ name: 'Quick scan (rules only) Fast regex pattern matching', value: false },
|
|
164
|
+
{
|
|
165
|
+
name: 'Deep scan (rules + AI) AI-powered analysis (requires OPENAI_API_KEY)',
|
|
166
|
+
value: true,
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
default: false,
|
|
170
|
+
});
|
|
171
|
+
return answer;
|
|
172
|
+
}
|
|
173
|
+
async function resolveScanOptions(args) {
|
|
174
|
+
const cwd = process.cwd();
|
|
175
|
+
const common = {
|
|
176
|
+
fix: args.fix,
|
|
177
|
+
report: args.report,
|
|
178
|
+
noSave: args.noSave,
|
|
179
|
+
};
|
|
180
|
+
if (args.system) {
|
|
181
|
+
if (args.targets.length > 0) {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
return { ...common, system: true, ai: args.ai, scopeLabel: 'AI system scan' };
|
|
185
|
+
}
|
|
186
|
+
if (args.targets.length > 0) {
|
|
187
|
+
if (args.targets.length === 1 && args.targets[0] === '.' && !args.deep) {
|
|
188
|
+
return {
|
|
189
|
+
...common,
|
|
190
|
+
targets: [cwd],
|
|
191
|
+
deep: false,
|
|
192
|
+
ai: args.ai,
|
|
193
|
+
scopeLabel: 'Current directory only',
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
return {
|
|
197
|
+
...common,
|
|
198
|
+
targets: args.targets,
|
|
199
|
+
deep: true,
|
|
200
|
+
ai: args.ai,
|
|
201
|
+
scopeLabel: args.targets.length === 1 && args.targets[0] === '.' ? 'Current + subdirectories' : 'Custom path',
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
if (args.deep) {
|
|
205
|
+
return { ...common, targets: [cwd], deep: true, ai: args.ai, scopeLabel: 'Current + subdirectories' };
|
|
206
|
+
}
|
|
207
|
+
if (process.stdout.isTTY !== true) {
|
|
208
|
+
return { ...common, targets: [cwd], deep: true, ai: false, scopeLabel: 'Current + subdirectories' };
|
|
209
|
+
}
|
|
210
|
+
const scope = await promptScanScope(cwd);
|
|
211
|
+
const ai = args.ai ? true : await promptScanDepth();
|
|
212
|
+
if (scope === 'system') {
|
|
213
|
+
return { ...common, system: true, ai, scopeLabel: 'AI system scan' };
|
|
214
|
+
}
|
|
215
|
+
if (scope === 'shallow') {
|
|
216
|
+
return { ...common, targets: [cwd], deep: false, ai, scopeLabel: 'Current directory only' };
|
|
217
|
+
}
|
|
218
|
+
return { ...common, targets: [cwd], deep: true, ai, scopeLabel: 'Current + subdirectories' };
|
|
95
219
|
}
|
|
96
220
|
async function runDashboard() {
|
|
97
221
|
const configuredPort = process.env.PORT;
|
package/dist/report.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AA2nBxC,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAoB7D"}
|