@rexymayderio/sentinel 0.1.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/README.md +295 -0
- package/dist/acquire/acquirer.d.ts +38 -0
- package/dist/acquire/acquirer.d.ts.map +1 -0
- package/dist/acquire/acquirer.js +178 -0
- package/dist/acquire/acquirer.js.map +1 -0
- package/dist/adapters/cli-approval-prompt.d.ts +13 -0
- package/dist/adapters/cli-approval-prompt.d.ts.map +1 -0
- package/dist/adapters/cli-approval-prompt.js +44 -0
- package/dist/adapters/cli-approval-prompt.js.map +1 -0
- package/dist/adapters/github-repo-client.d.ts +9 -0
- package/dist/adapters/github-repo-client.d.ts.map +1 -0
- package/dist/adapters/github-repo-client.js +48 -0
- package/dist/adapters/github-repo-client.js.map +1 -0
- package/dist/adapters/index.d.ts +5 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +5 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/node-process-runner.d.ts +8 -0
- package/dist/adapters/node-process-runner.d.ts.map +1 -0
- package/dist/adapters/node-process-runner.js +21 -0
- package/dist/adapters/node-process-runner.js.map +1 -0
- package/dist/adapters/npm-registry-client.d.ts +8 -0
- package/dist/adapters/npm-registry-client.d.ts.map +1 -0
- package/dist/adapters/npm-registry-client.js +66 -0
- package/dist/adapters/npm-registry-client.js.map +1 -0
- package/dist/analyzers/ai-prompt-analyzer.d.ts +7 -0
- package/dist/analyzers/ai-prompt-analyzer.d.ts.map +1 -0
- package/dist/analyzers/ai-prompt-analyzer.js +88 -0
- package/dist/analyzers/ai-prompt-analyzer.js.map +1 -0
- package/dist/analyzers/analyzer.d.ts +14 -0
- package/dist/analyzers/analyzer.d.ts.map +1 -0
- package/dist/analyzers/analyzer.js +11 -0
- package/dist/analyzers/analyzer.js.map +1 -0
- package/dist/analyzers/dependency-analyzer.d.ts +10 -0
- package/dist/analyzers/dependency-analyzer.d.ts.map +1 -0
- package/dist/analyzers/dependency-analyzer.js +79 -0
- package/dist/analyzers/dependency-analyzer.js.map +1 -0
- package/dist/analyzers/index.d.ts +13 -0
- package/dist/analyzers/index.d.ts.map +1 -0
- package/dist/analyzers/index.js +30 -0
- package/dist/analyzers/index.js.map +1 -0
- package/dist/analyzers/install-script-analyzer.d.ts +7 -0
- package/dist/analyzers/install-script-analyzer.d.ts.map +1 -0
- package/dist/analyzers/install-script-analyzer.js +64 -0
- package/dist/analyzers/install-script-analyzer.js.map +1 -0
- package/dist/analyzers/match-evidence.d.ts +6 -0
- package/dist/analyzers/match-evidence.d.ts.map +1 -0
- package/dist/analyzers/match-evidence.js +15 -0
- package/dist/analyzers/match-evidence.js.map +1 -0
- package/dist/analyzers/metadata-analyzer.d.ts +7 -0
- package/dist/analyzers/metadata-analyzer.d.ts.map +1 -0
- package/dist/analyzers/metadata-analyzer.js +105 -0
- package/dist/analyzers/metadata-analyzer.js.map +1 -0
- package/dist/analyzers/network-analyzer.d.ts +7 -0
- package/dist/analyzers/network-analyzer.d.ts.map +1 -0
- package/dist/analyzers/network-analyzer.js +47 -0
- package/dist/analyzers/network-analyzer.js.map +1 -0
- package/dist/analyzers/rules/index.d.ts +19 -0
- package/dist/analyzers/rules/index.d.ts.map +1 -0
- package/dist/analyzers/rules/index.js +70 -0
- package/dist/analyzers/rules/index.js.map +1 -0
- package/dist/analyzers/secret-analyzer.d.ts +7 -0
- package/dist/analyzers/secret-analyzer.d.ts.map +1 -0
- package/dist/analyzers/secret-analyzer.js +33 -0
- package/dist/analyzers/secret-analyzer.js.map +1 -0
- package/dist/analyzers/source-analyzer.d.ts +7 -0
- package/dist/analyzers/source-analyzer.d.ts.map +1 -0
- package/dist/analyzers/source-analyzer.js +73 -0
- package/dist/analyzers/source-analyzer.js.map +1 -0
- package/dist/analyzers/static-code-analyzer.d.ts +7 -0
- package/dist/analyzers/static-code-analyzer.d.ts.map +1 -0
- package/dist/analyzers/static-code-analyzer.js +67 -0
- package/dist/analyzers/static-code-analyzer.js.map +1 -0
- package/dist/analyzers/test-path.d.ts +2 -0
- package/dist/analyzers/test-path.d.ts.map +1 -0
- package/dist/analyzers/test-path.js +32 -0
- package/dist/analyzers/test-path.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +176 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/spinner.d.ts +5 -0
- package/dist/cli/spinner.d.ts.map +1 -0
- package/dist/cli/spinner.js +39 -0
- package/dist/cli/spinner.js.map +1 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +3 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/permissions.d.ts +4 -0
- package/dist/core/permissions.d.ts.map +1 -0
- package/dist/core/permissions.js +28 -0
- package/dist/core/permissions.js.map +1 -0
- package/dist/core/sentinel.d.ts +32 -0
- package/dist/core/sentinel.d.ts.map +1 -0
- package/dist/core/sentinel.js +164 -0
- package/dist/core/sentinel.js.map +1 -0
- package/dist/domain/artifact.d.ts +34 -0
- package/dist/domain/artifact.d.ts.map +1 -0
- package/dist/domain/artifact.js +2 -0
- package/dist/domain/artifact.js.map +1 -0
- package/dist/domain/finding.d.ts +22 -0
- package/dist/domain/finding.d.ts.map +1 -0
- package/dist/domain/finding.js +30 -0
- package/dist/domain/finding.js.map +1 -0
- package/dist/domain/index.d.ts +7 -0
- package/dist/domain/index.d.ts.map +1 -0
- package/dist/domain/index.js +7 -0
- package/dist/domain/index.js.map +1 -0
- package/dist/domain/permission.d.ts +8 -0
- package/dist/domain/permission.d.ts.map +1 -0
- package/dist/domain/permission.js +21 -0
- package/dist/domain/permission.js.map +1 -0
- package/dist/domain/report.d.ts +35 -0
- package/dist/domain/report.d.ts.map +1 -0
- package/dist/domain/report.js +2 -0
- package/dist/domain/report.js.map +1 -0
- package/dist/domain/risk.d.ts +14 -0
- package/dist/domain/risk.d.ts.map +1 -0
- package/dist/domain/risk.js +15 -0
- package/dist/domain/risk.js.map +1 -0
- package/dist/domain/target.d.ts +12 -0
- package/dist/domain/target.d.ts.map +1 -0
- package/dist/domain/target.js +43 -0
- package/dist/domain/target.js.map +1 -0
- package/dist/engine/data-assessment.d.ts +10 -0
- package/dist/engine/data-assessment.d.ts.map +1 -0
- package/dist/engine/data-assessment.js +39 -0
- package/dist/engine/data-assessment.js.map +1 -0
- package/dist/engine/default-policy.d.ts +16 -0
- package/dist/engine/default-policy.d.ts.map +1 -0
- package/dist/engine/default-policy.js +15 -0
- package/dist/engine/default-policy.js.map +1 -0
- package/dist/engine/index.d.ts +4 -0
- package/dist/engine/index.d.ts.map +1 -0
- package/dist/engine/index.js +4 -0
- package/dist/engine/index.js.map +1 -0
- package/dist/engine/policy-engine.d.ts +13 -0
- package/dist/engine/policy-engine.d.ts.map +1 -0
- package/dist/engine/policy-engine.js +78 -0
- package/dist/engine/policy-engine.js.map +1 -0
- package/dist/engine/risk-calculator.d.ts +15 -0
- package/dist/engine/risk-calculator.d.ts.map +1 -0
- package/dist/engine/risk-calculator.js +57 -0
- package/dist/engine/risk-calculator.js.map +1 -0
- package/dist/factory.d.ts +14 -0
- package/dist/factory.d.ts.map +1 -0
- package/dist/factory.js +25 -0
- package/dist/factory.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/server.d.ts +3 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +151 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/ports/approval-prompt.d.ts +5 -0
- package/dist/ports/approval-prompt.d.ts.map +1 -0
- package/dist/ports/approval-prompt.js +2 -0
- package/dist/ports/approval-prompt.js.map +1 -0
- package/dist/ports/clock.d.ts +5 -0
- package/dist/ports/clock.d.ts.map +1 -0
- package/dist/ports/clock.js +4 -0
- package/dist/ports/clock.js.map +1 -0
- package/dist/ports/index.d.ts +6 -0
- package/dist/ports/index.d.ts.map +1 -0
- package/dist/ports/index.js +6 -0
- package/dist/ports/index.js.map +1 -0
- package/dist/ports/process-runner.d.ts +12 -0
- package/dist/ports/process-runner.d.ts.map +1 -0
- package/dist/ports/process-runner.js +2 -0
- package/dist/ports/process-runner.js.map +1 -0
- package/dist/ports/registry-client.d.ts +14 -0
- package/dist/ports/registry-client.d.ts.map +1 -0
- package/dist/ports/registry-client.js +2 -0
- package/dist/ports/registry-client.js.map +1 -0
- package/dist/ports/repo-client.d.ts +18 -0
- package/dist/ports/repo-client.d.ts.map +1 -0
- package/dist/ports/repo-client.js +2 -0
- package/dist/ports/repo-client.js.map +1 -0
- package/dist/report/index.d.ts +2 -0
- package/dist/report/index.d.ts.map +1 -0
- package/dist/report/index.js +2 -0
- package/dist/report/index.js.map +1 -0
- package/dist/report/report-generator.d.ts +29 -0
- package/dist/report/report-generator.d.ts.map +1 -0
- package/dist/report/report-generator.js +167 -0
- package/dist/report/report-generator.js.map +1 -0
- package/package.json +50 -0
- package/skills/sentinel/SKILL.md +525 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { readFile } from 'node:fs/promises';
|
|
4
|
+
import kleur from 'kleur';
|
|
5
|
+
import { createDefaultSentinel } from '../factory.js';
|
|
6
|
+
import { startSpinner } from './spinner.js';
|
|
7
|
+
const program = new Command();
|
|
8
|
+
const TARGET_TYPES_HELP = `
|
|
9
|
+
Target types:
|
|
10
|
+
npm npm package (e.g. express, lodash@4.17.21)
|
|
11
|
+
github GitHub repository (e.g. owner/repo)
|
|
12
|
+
skill Local AI skill directory or SKILL.md path
|
|
13
|
+
local Any local directory to scan
|
|
14
|
+
|
|
15
|
+
Exit codes:
|
|
16
|
+
0 Verification passed (decision is not BLOCK)
|
|
17
|
+
1 Runtime error or install denied/failed
|
|
18
|
+
2 Policy BLOCK — do not install
|
|
19
|
+
`;
|
|
20
|
+
const VERIFY_EXAMPLES = `
|
|
21
|
+
Examples:
|
|
22
|
+
sentinel verify npm express
|
|
23
|
+
sentinel verify npm lodash@4.17.21
|
|
24
|
+
sentinel verify github expressjs/express
|
|
25
|
+
sentinel verify skill ./my-skill
|
|
26
|
+
sentinel verify local ./my-project
|
|
27
|
+
sentinel verify npm express --json
|
|
28
|
+
sentinel verify npm express --markdown
|
|
29
|
+
sentinel verify npm express --policy ./policy.json
|
|
30
|
+
`;
|
|
31
|
+
const INSTALL_EXAMPLES = `
|
|
32
|
+
Examples:
|
|
33
|
+
sentinel install npm express
|
|
34
|
+
sentinel install github owner/repo
|
|
35
|
+
sentinel install skill ./my-skill
|
|
36
|
+
sentinel install npm express --yes
|
|
37
|
+
sentinel install npm express --json
|
|
38
|
+
sentinel install npm express --policy ./policy.json
|
|
39
|
+
|
|
40
|
+
Approval:
|
|
41
|
+
Runs verification first, then prompts [y/N] unless auto-approved.
|
|
42
|
+
--yes skips the prompt for non-BLOCK decisions (WARN, REQUIRE_APPROVAL, APPROVE).
|
|
43
|
+
BLOCK decisions cannot be overridden.
|
|
44
|
+
`;
|
|
45
|
+
program
|
|
46
|
+
.name('sentinel')
|
|
47
|
+
.description('Universal Security Verification Framework for AI Agent Installations')
|
|
48
|
+
.version('0.1.0')
|
|
49
|
+
.addHelpText('after', `
|
|
50
|
+
Commands:
|
|
51
|
+
verify Analyze a target without installing (read-only)
|
|
52
|
+
install Verify, prompt for approval, then install
|
|
53
|
+
|
|
54
|
+
Quick start:
|
|
55
|
+
sentinel verify npm express
|
|
56
|
+
sentinel verify github owner/repo
|
|
57
|
+
sentinel install skill ./my-skill --yes
|
|
58
|
+
|
|
59
|
+
Run "sentinel <command> --help" for command-specific options and examples.
|
|
60
|
+
${TARGET_TYPES_HELP}`);
|
|
61
|
+
program
|
|
62
|
+
.command('verify')
|
|
63
|
+
.description('Verify a package, repository, skill, or other target without installing')
|
|
64
|
+
.argument('<type>', 'Target ecosystem: npm, github, skill, or local')
|
|
65
|
+
.argument('<target>', 'Package name, owner/repo, or filesystem path')
|
|
66
|
+
.option('--json', 'Output the full verification report as JSON (machine-readable)')
|
|
67
|
+
.option('--markdown', 'Output the report as Markdown')
|
|
68
|
+
.option('--policy <file>', 'Path to a JSON policy file (overrides default thresholds and lists)')
|
|
69
|
+
.option('--score-tests', 'Score findings in test/fixture files at full severity (default: down-weighted)')
|
|
70
|
+
.addHelpText('after', `${VERIFY_EXAMPLES}
|
|
71
|
+
Options (default output is a colored terminal report):
|
|
72
|
+
--json Structured JSON with findings, risk, policy, permissions, evidence
|
|
73
|
+
--markdown Markdown table suitable for docs or PR comments
|
|
74
|
+
--policy Custom policy: blockThreshold, warnThreshold, minConfidence,
|
|
75
|
+
trustedPublishers, corporateWhitelist, corporateBlacklist, etc.
|
|
76
|
+
--score-tests Treat dangerous code in test/fixture files at full weight
|
|
77
|
+
(by default such findings are shown but down-weighted)
|
|
78
|
+
|
|
79
|
+
${TARGET_TYPES_HELP}`)
|
|
80
|
+
.action(async (type, target, opts) => {
|
|
81
|
+
try {
|
|
82
|
+
const format = opts.json ? 'json' : opts.markdown ? 'markdown' : 'terminal';
|
|
83
|
+
const policyConfig = await resolvePolicyConfig(opts.policy, opts.scoreTests);
|
|
84
|
+
const sentinel = createDefaultSentinel({ policyConfig, reportFormat: format });
|
|
85
|
+
const spinner = startSpinner(`Verifying ${type}:${target}...`);
|
|
86
|
+
let report;
|
|
87
|
+
try {
|
|
88
|
+
report = await sentinel.verify(type, target);
|
|
89
|
+
}
|
|
90
|
+
finally {
|
|
91
|
+
spinner.stop();
|
|
92
|
+
}
|
|
93
|
+
const output = sentinel.generateReport(report, format);
|
|
94
|
+
console.log(output);
|
|
95
|
+
if (report.policy.decision === 'BLOCK') {
|
|
96
|
+
process.exit(2);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
console.error(kleur.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
101
|
+
process.exit(1);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
program
|
|
105
|
+
.command('install')
|
|
106
|
+
.description('Verify and install a target (requires approval unless auto-approved)')
|
|
107
|
+
.argument('<type>', 'Target ecosystem: npm, github, skill, or local')
|
|
108
|
+
.argument('<target>', 'Package name, owner/repo, or filesystem path')
|
|
109
|
+
.option('--json', 'Output the verification report as JSON instead of terminal format')
|
|
110
|
+
.option('--yes', 'Auto-approve installation after verification (cannot override BLOCK)')
|
|
111
|
+
.option('--policy <file>', 'Path to a JSON policy file (overrides default thresholds and lists)')
|
|
112
|
+
.option('--score-tests', 'Score findings in test/fixture files at full severity (default: down-weighted)')
|
|
113
|
+
.addHelpText('after', `${INSTALL_EXAMPLES}
|
|
114
|
+
Options:
|
|
115
|
+
--json Output report as JSON (terminal format is default)
|
|
116
|
+
--yes Skip the interactive [y/N] approval prompt when policy allows it
|
|
117
|
+
--policy Custom policy file (same fields as verify --policy)
|
|
118
|
+
--score-tests Treat dangerous code in test/fixture files at full weight
|
|
119
|
+
|
|
120
|
+
Install behavior by ecosystem:
|
|
121
|
+
npm npm install <name> --ignore-scripts
|
|
122
|
+
github git clone https://github.com/<owner>/<repo>.git
|
|
123
|
+
skill Verified locally — no file copy (MVP)
|
|
124
|
+
local Verified locally — no installation step (MVP)
|
|
125
|
+
|
|
126
|
+
${TARGET_TYPES_HELP}`)
|
|
127
|
+
.action(async (type, target, opts) => {
|
|
128
|
+
try {
|
|
129
|
+
const format = opts.json ? 'json' : 'terminal';
|
|
130
|
+
const policyConfig = await resolvePolicyConfig(opts.policy, opts.scoreTests);
|
|
131
|
+
const sentinel = createDefaultSentinel({
|
|
132
|
+
policyConfig,
|
|
133
|
+
reportFormat: format,
|
|
134
|
+
autoApprove: opts.yes,
|
|
135
|
+
});
|
|
136
|
+
const spinner = startSpinner(`Verifying ${type}:${target}...`);
|
|
137
|
+
let spinnerStopped = false;
|
|
138
|
+
const stopSpinner = () => {
|
|
139
|
+
if (!spinnerStopped) {
|
|
140
|
+
spinner.stop();
|
|
141
|
+
spinnerStopped = true;
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
let result;
|
|
145
|
+
try {
|
|
146
|
+
result = await sentinel.install(type, target, { onVerified: stopSpinner });
|
|
147
|
+
}
|
|
148
|
+
finally {
|
|
149
|
+
stopSpinner();
|
|
150
|
+
}
|
|
151
|
+
const output = sentinel.generateReport(result.report, format);
|
|
152
|
+
console.log(output);
|
|
153
|
+
if (!result.success) {
|
|
154
|
+
console.error(kleur.red(`\n${result.message}`));
|
|
155
|
+
process.exit(result.report.policy.decision === 'BLOCK' ? 2 : 1);
|
|
156
|
+
}
|
|
157
|
+
console.log(kleur.green(`\n${result.message}`));
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
console.error(kleur.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
161
|
+
process.exit(1);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
async function loadPolicyFile(path) {
|
|
165
|
+
const content = await readFile(path, 'utf-8');
|
|
166
|
+
return JSON.parse(content);
|
|
167
|
+
}
|
|
168
|
+
async function resolvePolicyConfig(policyPath, scoreTests) {
|
|
169
|
+
const fromFile = policyPath ? await loadPolicyFile(policyPath) : undefined;
|
|
170
|
+
if (!scoreTests) {
|
|
171
|
+
return fromFile;
|
|
172
|
+
}
|
|
173
|
+
return { ...fromFile, scoreTestCodeFully: true };
|
|
174
|
+
}
|
|
175
|
+
program.parse();
|
|
176
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAGtD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,MAAM,iBAAiB,GAAG;;;;;;;;;;;CAWzB,CAAC;AAEF,MAAM,eAAe,GAAG;;;;;;;;;;CAUvB,CAAC;AAEF,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;CAaxB,CAAC;AAEF,OAAO;KACJ,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CAAC,sEAAsE,CAAC;KACnF,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,OAAO,EAAE;;;;;;;;;;;EAWtB,iBAAiB,EAAE,CAAC,CAAC;AAEvB,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,yEAAyE,CAAC;KACtF,QAAQ,CAAC,QAAQ,EAAE,gDAAgD,CAAC;KACpE,QAAQ,CAAC,UAAU,EAAE,8CAA8C,CAAC;KACpE,MAAM,CAAC,QAAQ,EAAE,gEAAgE,CAAC;KAClF,MAAM,CAAC,YAAY,EAAE,+BAA+B,CAAC;KACrD,MAAM,CAAC,iBAAiB,EAAE,qEAAqE,CAAC;KAChG,MAAM,CAAC,eAAe,EAAE,gFAAgF,CAAC;KACzG,WAAW,CAAC,OAAO,EAAE,GAAG,eAAe;;;;;;;;;EASxC,iBAAiB,EAAE,CAAC;KACnB,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,MAAc,EAAE,IAAmF,EAAE,EAAE;IAClI,IAAI,CAAC;QACH,MAAM,MAAM,GAAiB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC;QAC1F,MAAM,YAAY,GAAG,MAAM,mBAAmB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QAC7E,MAAM,QAAQ,GAAG,qBAAqB,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC;QAE/E,MAAM,OAAO,GAAG,YAAY,CAAC,aAAa,IAAI,IAAI,MAAM,KAAK,CAAC,CAAC;QAC/D,IAAI,MAAM,CAAC;QACX,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC/C,CAAC;gBAAS,CAAC;YACT,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,CAAC;QACD,MAAM,MAAM,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACvD,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAEpB,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,sEAAsE,CAAC;KACnF,QAAQ,CAAC,QAAQ,EAAE,gDAAgD,CAAC;KACpE,QAAQ,CAAC,UAAU,EAAE,8CAA8C,CAAC;KACpE,MAAM,CAAC,QAAQ,EAAE,mEAAmE,CAAC;KACrF,MAAM,CAAC,OAAO,EAAE,sEAAsE,CAAC;KACvF,MAAM,CAAC,iBAAiB,EAAE,qEAAqE,CAAC;KAChG,MAAM,CAAC,eAAe,EAAE,gFAAgF,CAAC;KACzG,WAAW,CAAC,OAAO,EAAE,GAAG,gBAAgB;;;;;;;;;;;;;EAazC,iBAAiB,EAAE,CAAC;KACnB,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,MAAc,EAAE,IAA8E,EAAE,EAAE;IAC7H,IAAI,CAAC;QACH,MAAM,MAAM,GAAiB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC;QAC7D,MAAM,YAAY,GAAG,MAAM,mBAAmB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QAC7E,MAAM,QAAQ,GAAG,qBAAqB,CAAC;YACrC,YAAY;YACZ,YAAY,EAAE,MAAM;YACpB,WAAW,EAAE,IAAI,CAAC,GAAG;SACtB,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,YAAY,CAAC,aAAa,IAAI,IAAI,MAAM,KAAK,CAAC,CAAC;QAC/D,IAAI,cAAc,GAAG,KAAK,CAAC;QAC3B,MAAM,WAAW,GAAG,GAAS,EAAE;YAC7B,IAAI,CAAC,cAAc,EAAE,CAAC;gBACpB,OAAO,CAAC,IAAI,EAAE,CAAC;gBACf,cAAc,GAAG,IAAI,CAAC;YACxB,CAAC;QACH,CAAC,CAAC;QACF,IAAI,MAAM,CAAC;QACX,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,CAAC;QAC7E,CAAC;gBAAS,CAAC;YACT,WAAW,EAAE,CAAC;QAChB,CAAC;QACD,MAAM,MAAM,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC9D,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAEpB,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YAChD,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAClE,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAClD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,KAAK,UAAU,cAAc,CAAC,IAAY;IACxC,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAA0B,CAAC;AACtD,CAAC;AAED,KAAK,UAAU,mBAAmB,CAChC,UAA8B,EAC9B,UAA+B;IAE/B,MAAM,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3E,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,OAAO,EAAE,GAAG,QAAQ,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC;AACnD,CAAC;AAED,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../src/cli/spinner.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,OAAO;IACtB,IAAI,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAkCD,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAKrD"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import kleur from 'kleur';
|
|
2
|
+
const FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
3
|
+
const FRAME_INTERVAL_MS = 80;
|
|
4
|
+
class TtySpinner {
|
|
5
|
+
message;
|
|
6
|
+
frameIndex = 0;
|
|
7
|
+
timer;
|
|
8
|
+
startedAt = Date.now();
|
|
9
|
+
constructor(message) {
|
|
10
|
+
this.message = message;
|
|
11
|
+
process.stderr.write('\x1B[?25l');
|
|
12
|
+
this.render();
|
|
13
|
+
this.timer = setInterval(() => this.render(), FRAME_INTERVAL_MS);
|
|
14
|
+
if (typeof this.timer.unref === 'function') {
|
|
15
|
+
this.timer.unref();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
render() {
|
|
19
|
+
const frame = FRAMES[this.frameIndex] ?? FRAMES[0];
|
|
20
|
+
this.frameIndex = (this.frameIndex + 1) % FRAMES.length;
|
|
21
|
+
const elapsed = ((Date.now() - this.startedAt) / 1000).toFixed(1);
|
|
22
|
+
process.stderr.write(`\r${kleur.cyan(frame)} ${this.message} ${kleur.dim(`(${elapsed}s)`)}`);
|
|
23
|
+
}
|
|
24
|
+
stop() {
|
|
25
|
+
clearInterval(this.timer);
|
|
26
|
+
process.stderr.write('\r\x1B[K');
|
|
27
|
+
process.stderr.write('\x1B[?25h');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
class NoopSpinner {
|
|
31
|
+
stop() { }
|
|
32
|
+
}
|
|
33
|
+
export function startSpinner(message) {
|
|
34
|
+
if (!process.stderr.isTTY) {
|
|
35
|
+
return new NoopSpinner();
|
|
36
|
+
}
|
|
37
|
+
return new TtySpinner(message);
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=spinner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../src/cli/spinner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAClE,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAM7B,MAAM,UAAU;IAKe;IAJrB,UAAU,GAAG,CAAC,CAAC;IACN,KAAK,CAAiB;IACtB,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAExC,YAA6B,OAAe;QAAf,YAAO,GAAP,OAAO,CAAQ;QAC1C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC;QACjE,IAAI,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;YAC3C,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACrB,CAAC;IACH,CAAC;IAEO,MAAM;QACZ,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,MAAM,CAAC,CAAC,CAAE,CAAC;QACpD,IAAI,CAAC,UAAU,GAAG,CAAC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;QACxD,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAClE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC,CAAC;IAC/F,CAAC;IAED,IAAI;QACF,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACjC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACpC,CAAC;CACF;AAED,MAAM,WAAW;IACf,IAAI,KAAU,CAAC;CAChB;AAED,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAC1B,OAAO,IAAI,WAAW,EAAE,CAAC;IAC3B,CAAC;IACD,OAAO,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/core/permissions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAkB,MAAM,yBAAyB,CAAC;AAW1E,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,CAoBtE"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const PERMISSION_RULE_MAP = [
|
|
2
|
+
{ ruleIds: ['spawn', 'exec', 'child-process', 'os-system', 'subprocess', 'powershell'], type: 'shell', description: 'Shell command execution' },
|
|
3
|
+
{ ruleIds: ['hardcoded-ip', 'discord-webhook', 'telegram-bot', 'ngrok', 'cloudflare-tunnel'], type: 'network-internet', description: 'Internet network access' },
|
|
4
|
+
{ ruleIds: ['private-ip'], type: 'network-localhost', description: 'Localhost/private network access' },
|
|
5
|
+
{ ruleIds: ['aws-key', 'openai-key', 'anthropic-key', 'private-key', 'github-token'], type: 'secrets', description: 'Secret/credential access' },
|
|
6
|
+
{ ruleIds: ['rm-rf'], type: 'filesystem-delete', description: 'Filesystem deletion' },
|
|
7
|
+
{ ruleIds: ['chmod-x', 'registry-edit', 'cron', 'startup-folder'], type: 'filesystem-write', description: 'Filesystem modification' },
|
|
8
|
+
];
|
|
9
|
+
export function buildPermissionGraph(findings) {
|
|
10
|
+
const permissions = [];
|
|
11
|
+
const seen = new Set();
|
|
12
|
+
for (const finding of findings) {
|
|
13
|
+
if (finding.positive || !finding.ruleId)
|
|
14
|
+
continue;
|
|
15
|
+
for (const mapping of PERMISSION_RULE_MAP) {
|
|
16
|
+
if (mapping.ruleIds.includes(finding.ruleId) && !seen.has(mapping.type)) {
|
|
17
|
+
seen.add(mapping.type);
|
|
18
|
+
permissions.push({
|
|
19
|
+
type: mapping.type,
|
|
20
|
+
description: mapping.description,
|
|
21
|
+
source: finding.file ?? finding.ruleId,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return permissions;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=permissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/core/permissions.ts"],"names":[],"mappings":"AAGA,MAAM,mBAAmB,GAA4E;IACnG,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,yBAAyB,EAAE;IAC/I,EAAE,OAAO,EAAE,CAAC,cAAc,EAAE,iBAAiB,EAAE,cAAc,EAAE,OAAO,EAAE,mBAAmB,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,WAAW,EAAE,yBAAyB,EAAE;IAChK,EAAE,OAAO,EAAE,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,WAAW,EAAE,kCAAkC,EAAE;IACvG,EAAE,OAAO,EAAE,CAAC,SAAS,EAAE,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,cAAc,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,0BAA0B,EAAE;IAChJ,EAAE,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,WAAW,EAAE,qBAAqB,EAAE;IACrF,EAAE,OAAO,EAAE,CAAC,SAAS,EAAE,eAAe,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,WAAW,EAAE,yBAAyB,EAAE;CACtI,CAAC;AAEF,MAAM,UAAU,oBAAoB,CAAC,QAAmB;IACtD,MAAM,WAAW,GAAiB,EAAE,CAAC;IACrC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEvC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,OAAO,CAAC,QAAQ,IAAI,CAAC,OAAO,CAAC,MAAM;YAAE,SAAS;QAElD,KAAK,MAAM,OAAO,IAAI,mBAAmB,EAAE,CAAC;YAC1C,IAAI,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBACvB,WAAW,CAAC,IAAI,CAAC;oBACf,IAAI,EAAE,OAAO,CAAC,IAAI;oBAClB,WAAW,EAAE,OAAO,CAAC,WAAW;oBAChC,MAAM,EAAE,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,MAAM;iBACvC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { AcquirerRegistry } from '../acquire/acquirer.js';
|
|
2
|
+
import type { Analyzer } from '../analyzers/analyzer.js';
|
|
3
|
+
import type { ReportFormat, InstallResult, VerificationReport } from '../domain/report.js';
|
|
4
|
+
import type { PolicyConfig } from '../engine/default-policy.js';
|
|
5
|
+
import type { ApprovalPrompt } from '../ports/approval-prompt.js';
|
|
6
|
+
import type { ProcessRunner } from '../ports/process-runner.js';
|
|
7
|
+
export interface SentinelOptions {
|
|
8
|
+
readonly acquirerRegistry: AcquirerRegistry;
|
|
9
|
+
readonly analyzers: Analyzer[];
|
|
10
|
+
readonly policyConfig?: Partial<PolicyConfig>;
|
|
11
|
+
readonly approvalPrompt: ApprovalPrompt;
|
|
12
|
+
readonly processRunner: ProcessRunner;
|
|
13
|
+
readonly reportFormat?: ReportFormat;
|
|
14
|
+
}
|
|
15
|
+
export declare class Sentinel {
|
|
16
|
+
private readonly options;
|
|
17
|
+
private readonly riskCalculator;
|
|
18
|
+
private readonly policyEngine;
|
|
19
|
+
private readonly reportGenerator;
|
|
20
|
+
private readonly policyConfig;
|
|
21
|
+
constructor(options: SentinelOptions);
|
|
22
|
+
verify(ecosystem: string, raw: string): Promise<VerificationReport>;
|
|
23
|
+
private buildUnverifiableReport;
|
|
24
|
+
install(ecosystem: string, raw: string, options?: {
|
|
25
|
+
forceApprove?: boolean;
|
|
26
|
+
onVerified?: () => void;
|
|
27
|
+
}): Promise<InstallResult>;
|
|
28
|
+
generateReport(report: VerificationReport, format?: ReportFormat): string;
|
|
29
|
+
private runInstaller;
|
|
30
|
+
}
|
|
31
|
+
export declare function createSentinel(options: SentinelOptions): Sentinel;
|
|
32
|
+
//# sourceMappingURL=sentinel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sentinel.d.ts","sourceRoot":"","sources":["../../src/core/sentinel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG/D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAIzD,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAgB,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAIzG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAKhE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAGhE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAC5C,QAAQ,CAAC,SAAS,EAAE,QAAQ,EAAE,CAAC;IAC/B,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAC9C,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;CACtC;AAED,qBAAa,QAAQ;IAMP,OAAO,CAAC,QAAQ,CAAC,OAAO;IALpC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAwB;IACvD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAC5C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAyB;IACzD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;gBAEf,OAAO,EAAE,eAAe;IAO/C,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IA8CzE,OAAO,CAAC,uBAAuB;IA6BzB,OAAO,CACX,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,IAAI,CAAA;KAAE,GAC5D,OAAO,CAAC,aAAa,CAAC;IAoCzB,cAAc,CAAC,MAAM,EAAE,kBAAkB,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,MAAM;YAI3D,YAAY;CAmB3B;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,QAAQ,CAEjE"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { cleanupArtifact } from '../acquire/acquirer.js';
|
|
2
|
+
import { runAnalyzers } from '../analyzers/analyzer.js';
|
|
3
|
+
import { isTestPath } from '../analyzers/test-path.js';
|
|
4
|
+
import { buildPermissionGraph } from './permissions.js';
|
|
5
|
+
import { parseTarget } from '../domain/target.js';
|
|
6
|
+
import { DEFAULT_POLICY } from '../engine/default-policy.js';
|
|
7
|
+
import { assessData, hasMeaningfulMetadata, unverifiableAssessment } from '../engine/data-assessment.js';
|
|
8
|
+
import { PolicyEngine } from '../engine/policy-engine.js';
|
|
9
|
+
import { RiskCalculator, TEST_FINDING_WEIGHT } from '../engine/risk-calculator.js';
|
|
10
|
+
import { ReportGenerator } from '../report/report-generator.js';
|
|
11
|
+
export class Sentinel {
|
|
12
|
+
options;
|
|
13
|
+
riskCalculator = new RiskCalculator();
|
|
14
|
+
policyEngine;
|
|
15
|
+
reportGenerator = new ReportGenerator();
|
|
16
|
+
policyConfig;
|
|
17
|
+
constructor(options) {
|
|
18
|
+
this.options = options;
|
|
19
|
+
this.policyConfig = options.policyConfig
|
|
20
|
+
? { ...DEFAULT_POLICY, ...options.policyConfig }
|
|
21
|
+
: DEFAULT_POLICY;
|
|
22
|
+
this.policyEngine = new PolicyEngine(this.policyConfig);
|
|
23
|
+
}
|
|
24
|
+
async verify(ecosystem, raw) {
|
|
25
|
+
const start = Date.now();
|
|
26
|
+
const target = parseTarget(ecosystem, raw);
|
|
27
|
+
const acquirer = this.options.acquirerRegistry.get(target.ecosystem);
|
|
28
|
+
let artifact;
|
|
29
|
+
try {
|
|
30
|
+
artifact = await acquirer.acquire(target);
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
34
|
+
return this.buildUnverifiableReport(target, reason, start);
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
const rawFindings = await runAnalyzers(this.options.analyzers, { artifact, target });
|
|
38
|
+
const findings = tagTestFindings(rawFindings);
|
|
39
|
+
const permissions = buildPermissionGraph(findings.filter((f) => !f.isTest));
|
|
40
|
+
const evidence = {
|
|
41
|
+
hasMetadata: hasMeaningfulMetadata(artifact.metadata),
|
|
42
|
+
fileCount: artifact.files.length,
|
|
43
|
+
};
|
|
44
|
+
const testFindingWeight = this.policyConfig.scoreTestCodeFully ? 1 : TEST_FINDING_WEIGHT;
|
|
45
|
+
const risk = this.riskCalculator.calculate(findings, evidence, { testFindingWeight });
|
|
46
|
+
const dataAssessment = assessData(target, artifact, findings, risk, this.policyConfig);
|
|
47
|
+
const policy = this.policyEngine.evaluate(target, risk, findings, permissions, dataAssessment);
|
|
48
|
+
const criticalCount = findings.filter((f) => f.severity === 'CRITICAL' && !f.positive).length;
|
|
49
|
+
const summary = `${risk.level} risk (${risk.score}/100) - ${criticalCount} critical findings`;
|
|
50
|
+
return {
|
|
51
|
+
target,
|
|
52
|
+
findings,
|
|
53
|
+
risk,
|
|
54
|
+
policy,
|
|
55
|
+
permissions,
|
|
56
|
+
dataAssessment,
|
|
57
|
+
summary,
|
|
58
|
+
recommendedAction: recommendedActionFor(policy.decision),
|
|
59
|
+
scannedAt: new Date().toISOString(),
|
|
60
|
+
durationMs: Date.now() - start,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
finally {
|
|
64
|
+
await cleanupArtifact(artifact);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
buildUnverifiableReport(target, reason, start) {
|
|
68
|
+
const dataAssessment = unverifiableAssessment(`Could not acquire target: ${reason}`);
|
|
69
|
+
const risk = {
|
|
70
|
+
score: 0,
|
|
71
|
+
level: 'LOW',
|
|
72
|
+
confidence: 0,
|
|
73
|
+
positiveSignals: 0,
|
|
74
|
+
negativeSignals: 0,
|
|
75
|
+
};
|
|
76
|
+
const policy = {
|
|
77
|
+
decision: 'REQUIRE_APPROVAL',
|
|
78
|
+
reasons: ['Not enough data was gathered to verify this target automatically', ...dataAssessment.reasons],
|
|
79
|
+
overrides: [],
|
|
80
|
+
};
|
|
81
|
+
return {
|
|
82
|
+
target,
|
|
83
|
+
findings: [],
|
|
84
|
+
risk,
|
|
85
|
+
policy,
|
|
86
|
+
permissions: [],
|
|
87
|
+
dataAssessment,
|
|
88
|
+
summary: 'Could not gather data - manual review required',
|
|
89
|
+
recommendedAction: recommendedActionFor(policy.decision),
|
|
90
|
+
scannedAt: new Date().toISOString(),
|
|
91
|
+
durationMs: Date.now() - start,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
async install(ecosystem, raw, options) {
|
|
95
|
+
const report = await this.verify(ecosystem, raw);
|
|
96
|
+
options?.onVerified?.();
|
|
97
|
+
if (report.policy.decision === 'BLOCK') {
|
|
98
|
+
return {
|
|
99
|
+
success: false,
|
|
100
|
+
message: 'Installation blocked by policy',
|
|
101
|
+
report,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
const approved = options?.forceApprove
|
|
105
|
+
? true
|
|
106
|
+
: await this.options.approvalPrompt.requestApproval(report);
|
|
107
|
+
if (!approved) {
|
|
108
|
+
return {
|
|
109
|
+
success: false,
|
|
110
|
+
message: 'Installation denied by user',
|
|
111
|
+
report,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
const target = report.target;
|
|
115
|
+
const installResult = await this.runInstaller(target);
|
|
116
|
+
return {
|
|
117
|
+
success: installResult.exitCode === 0,
|
|
118
|
+
message: installResult.exitCode === 0
|
|
119
|
+
? `Successfully installed ${target.ecosystem}:${target.name}`
|
|
120
|
+
: `Installation failed: ${installResult.stderr || installResult.stdout}`,
|
|
121
|
+
report,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
generateReport(report, format) {
|
|
125
|
+
return this.reportGenerator.generate(report, format ?? this.options.reportFormat ?? 'terminal');
|
|
126
|
+
}
|
|
127
|
+
async runInstaller(target) {
|
|
128
|
+
const { processRunner } = this.options;
|
|
129
|
+
switch (target.ecosystem) {
|
|
130
|
+
case 'npm':
|
|
131
|
+
return processRunner.run('npm', ['install', target.name, '--ignore-scripts'], {
|
|
132
|
+
env: { npm_config_ignore_scripts: 'true' },
|
|
133
|
+
});
|
|
134
|
+
case 'github': {
|
|
135
|
+
const [owner, repo] = target.name.split('/');
|
|
136
|
+
return processRunner.run('git', ['clone', `https://github.com/${owner}/${repo}.git`]);
|
|
137
|
+
}
|
|
138
|
+
case 'skill':
|
|
139
|
+
case 'local':
|
|
140
|
+
return { exitCode: 0, stdout: 'Local skill/directory verified - no installation needed', stderr: '' };
|
|
141
|
+
default:
|
|
142
|
+
return { exitCode: 1, stdout: '', stderr: `No installer for ecosystem: ${target.ecosystem}` };
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
export function createSentinel(options) {
|
|
147
|
+
return new Sentinel(options);
|
|
148
|
+
}
|
|
149
|
+
function tagTestFindings(findings) {
|
|
150
|
+
return findings.map((finding) => finding.file && isTestPath(finding.file) ? { ...finding, isTest: true } : finding);
|
|
151
|
+
}
|
|
152
|
+
function recommendedActionFor(decision) {
|
|
153
|
+
switch (decision) {
|
|
154
|
+
case 'BLOCK':
|
|
155
|
+
return 'DO NOT INSTALL';
|
|
156
|
+
case 'REQUIRE_APPROVAL':
|
|
157
|
+
return 'REVIEW AND APPROVE BEFORE INSTALLING';
|
|
158
|
+
case 'WARN':
|
|
159
|
+
return 'PROCEED WITH CAUTION';
|
|
160
|
+
default:
|
|
161
|
+
return 'SAFE TO INSTALL';
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=sentinel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sentinel.js","sourceRoot":"","sources":["../../src/core/sentinel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export interface FileEntry {
|
|
2
|
+
readonly path: string;
|
|
3
|
+
readonly content: string;
|
|
4
|
+
readonly size: number;
|
|
5
|
+
}
|
|
6
|
+
export interface PackageMetadata {
|
|
7
|
+
readonly name?: string;
|
|
8
|
+
readonly version?: string;
|
|
9
|
+
readonly author?: string;
|
|
10
|
+
readonly maintainers?: string[];
|
|
11
|
+
readonly repository?: string;
|
|
12
|
+
readonly homepage?: string;
|
|
13
|
+
readonly license?: string;
|
|
14
|
+
readonly publishDate?: string;
|
|
15
|
+
readonly firstPublishDate?: string;
|
|
16
|
+
readonly downloadCount?: number;
|
|
17
|
+
readonly keywords?: string[];
|
|
18
|
+
readonly verifiedPublisher?: boolean;
|
|
19
|
+
readonly signedRelease?: boolean;
|
|
20
|
+
readonly scripts?: Record<string, string>;
|
|
21
|
+
readonly dependencies?: Record<string, string>;
|
|
22
|
+
readonly devDependencies?: Record<string, string>;
|
|
23
|
+
readonly optionalDependencies?: Record<string, string>;
|
|
24
|
+
readonly sourceUrl?: string;
|
|
25
|
+
readonly description?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface Artifact {
|
|
28
|
+
readonly target: import('./target.js').Target;
|
|
29
|
+
readonly rootPath: string;
|
|
30
|
+
readonly files: FileEntry[];
|
|
31
|
+
readonly metadata: PackageMetadata;
|
|
32
|
+
readonly manifest?: Record<string, unknown>;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=artifact.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifact.d.ts","sourceRoot":"","sources":["../../src/domain/artifact.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IACrC,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/C,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClD,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,MAAM,EAAE,OAAO,aAAa,EAAE,MAAM,CAAC;IAC9C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC7C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifact.js","sourceRoot":"","sources":["../../src/domain/artifact.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const SEVERITIES: readonly ["CRITICAL", "HIGH", "MEDIUM", "LOW", "INFO"];
|
|
2
|
+
export type Severity = (typeof SEVERITIES)[number];
|
|
3
|
+
export declare const CATEGORIES: readonly ["metadata", "source", "repository", "static-code", "dependency", "install-script", "ai-prompt", "permission", "network", "secret", "binary", "reputation", "behavioral"];
|
|
4
|
+
export type Category = (typeof CATEGORIES)[number];
|
|
5
|
+
export declare const SEVERITY_WEIGHTS: Record<Severity, number>;
|
|
6
|
+
export interface Finding {
|
|
7
|
+
readonly id: string;
|
|
8
|
+
readonly category: Category;
|
|
9
|
+
readonly severity: Severity;
|
|
10
|
+
readonly title: string;
|
|
11
|
+
readonly description: string;
|
|
12
|
+
readonly evidence?: string;
|
|
13
|
+
readonly file?: string;
|
|
14
|
+
readonly line?: number;
|
|
15
|
+
readonly ruleId?: string;
|
|
16
|
+
readonly positive?: boolean;
|
|
17
|
+
readonly isTest?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export declare function createFinding(partial: Omit<Finding, 'id'> & {
|
|
20
|
+
id?: string;
|
|
21
|
+
}): Finding;
|
|
22
|
+
//# sourceMappingURL=finding.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"finding.d.ts","sourceRoot":"","sources":["../../src/domain/finding.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,wDAAyD,CAAC;AACjF,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnD,eAAO,MAAM,UAAU,oLAcb,CAAC;AACX,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnD,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAMrD,CAAC;AAEF,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7C,OAAO,CAKT"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export const SEVERITIES = ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW', 'INFO'];
|
|
2
|
+
export const CATEGORIES = [
|
|
3
|
+
'metadata',
|
|
4
|
+
'source',
|
|
5
|
+
'repository',
|
|
6
|
+
'static-code',
|
|
7
|
+
'dependency',
|
|
8
|
+
'install-script',
|
|
9
|
+
'ai-prompt',
|
|
10
|
+
'permission',
|
|
11
|
+
'network',
|
|
12
|
+
'secret',
|
|
13
|
+
'binary',
|
|
14
|
+
'reputation',
|
|
15
|
+
'behavioral',
|
|
16
|
+
];
|
|
17
|
+
export const SEVERITY_WEIGHTS = {
|
|
18
|
+
CRITICAL: 50,
|
|
19
|
+
HIGH: 20,
|
|
20
|
+
MEDIUM: 10,
|
|
21
|
+
LOW: 2,
|
|
22
|
+
INFO: 0,
|
|
23
|
+
};
|
|
24
|
+
export function createFinding(partial) {
|
|
25
|
+
return {
|
|
26
|
+
id: partial.id ?? `${partial.category}-${partial.ruleId ?? partial.title}`.replace(/\s+/g, '-').toLowerCase(),
|
|
27
|
+
...partial,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=finding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"finding.js","sourceRoot":"","sources":["../../src/domain/finding.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAU,CAAC;AAGjF,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,UAAU;IACV,QAAQ;IACR,YAAY;IACZ,aAAa;IACb,YAAY;IACZ,gBAAgB;IAChB,WAAW;IACX,YAAY;IACZ,SAAS;IACT,QAAQ;IACR,QAAQ;IACR,YAAY;IACZ,YAAY;CACJ,CAAC;AAGX,MAAM,CAAC,MAAM,gBAAgB,GAA6B;IACxD,QAAQ,EAAE,EAAE;IACZ,IAAI,EAAE,EAAE;IACR,MAAM,EAAE,EAAE;IACV,GAAG,EAAE,CAAC;IACN,IAAI,EAAE,CAAC;CACR,CAAC;AAgBF,MAAM,UAAU,aAAa,CAC3B,OAA8C;IAE9C,OAAO;QACL,EAAE,EAAE,OAAO,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE;QAC7G,GAAG,OAAO;KACX,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/domain/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC"}
|