@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 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ProcessResult, ProcessRunner } from '../ports/process-runner.js';
|
|
2
|
+
export declare class NodeProcessRunner implements ProcessRunner {
|
|
3
|
+
run(command: string, args: string[], options?: {
|
|
4
|
+
cwd?: string;
|
|
5
|
+
env?: Record<string, string>;
|
|
6
|
+
}): Promise<ProcessResult>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=node-process-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-process-runner.d.ts","sourceRoot":"","sources":["../../src/adapters/node-process-runner.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAE/E,qBAAa,iBAAkB,YAAW,aAAa;IAC/C,GAAG,CACP,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,GACvD,OAAO,CAAC,aAAa,CAAC;CAoB1B"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
export class NodeProcessRunner {
|
|
3
|
+
async run(command, args, options) {
|
|
4
|
+
return new Promise((resolve, reject) => {
|
|
5
|
+
const child = spawn(command, args, {
|
|
6
|
+
cwd: options?.cwd,
|
|
7
|
+
env: { ...process.env, ...options?.env },
|
|
8
|
+
shell: false,
|
|
9
|
+
});
|
|
10
|
+
let stdout = '';
|
|
11
|
+
let stderr = '';
|
|
12
|
+
child.stdout?.on('data', (data) => { stdout += data.toString(); });
|
|
13
|
+
child.stderr?.on('data', (data) => { stderr += data.toString(); });
|
|
14
|
+
child.on('error', reject);
|
|
15
|
+
child.on('close', (code) => {
|
|
16
|
+
resolve({ exitCode: code ?? 1, stdout, stderr });
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=node-process-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-process-runner.js","sourceRoot":"","sources":["../../src/adapters/node-process-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAG3C,MAAM,OAAO,iBAAiB;IAC5B,KAAK,CAAC,GAAG,CACP,OAAe,EACf,IAAc,EACd,OAAwD;QAExD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;gBACjC,GAAG,EAAE,OAAO,EAAE,GAAG;gBACjB,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE;gBACxC,KAAK,EAAE,KAAK;aACb,CAAC,CAAC;YAEH,IAAI,MAAM,GAAG,EAAE,CAAC;YAChB,IAAI,MAAM,GAAG,EAAE,CAAC;YAEhB,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE,GAAG,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3E,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE,GAAG,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAE3E,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC1B,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;gBACzB,OAAO,CAAC,EAAE,QAAQ,EAAE,IAAI,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;YACnD,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { NpmPackageInfo, OsvVulnerability, RegistryClient } from '../ports/registry-client.js';
|
|
2
|
+
export declare class NpmRegistryClient implements RegistryClient {
|
|
3
|
+
private readonly registryUrl;
|
|
4
|
+
constructor(registryUrl?: string);
|
|
5
|
+
getNpmPackage(name: string, version?: string): Promise<NpmPackageInfo>;
|
|
6
|
+
checkOsv(packageName: string, version: string, ecosystem: string): Promise<OsvVulnerability[]>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=npm-registry-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"npm-registry-client.d.ts","sourceRoot":"","sources":["../../src/adapters/npm-registry-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AA2BpG,qBAAa,iBAAkB,YAAW,cAAc;IACtD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;gBAEzB,WAAW,SAA+B;IAIhD,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IA8CtE,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;CAmBrG"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export class NpmRegistryClient {
|
|
2
|
+
registryUrl;
|
|
3
|
+
constructor(registryUrl = 'https://registry.npmjs.org') {
|
|
4
|
+
this.registryUrl = registryUrl;
|
|
5
|
+
}
|
|
6
|
+
async getNpmPackage(name, version) {
|
|
7
|
+
const encoded = encodeURIComponent(name).replace('%40', '@');
|
|
8
|
+
const url = `${this.registryUrl}/${encoded}`;
|
|
9
|
+
const response = await fetch(url);
|
|
10
|
+
if (!response.ok) {
|
|
11
|
+
throw new Error(`npm package not found: ${name} (${response.status})`);
|
|
12
|
+
}
|
|
13
|
+
const data = (await response.json());
|
|
14
|
+
const resolvedVersion = version ?? data['dist-tags'].latest;
|
|
15
|
+
const versionInfo = data.versions[resolvedVersion];
|
|
16
|
+
if (!versionInfo) {
|
|
17
|
+
throw new Error(`Version ${resolvedVersion} not found for ${name}`);
|
|
18
|
+
}
|
|
19
|
+
const author = typeof versionInfo.author === 'string'
|
|
20
|
+
? versionInfo.author
|
|
21
|
+
: versionInfo.author?.name;
|
|
22
|
+
const repository = typeof versionInfo.repository === 'string'
|
|
23
|
+
? versionInfo.repository
|
|
24
|
+
: versionInfo.repository?.url?.replace(/^git\+/, '').replace(/\.git$/, '');
|
|
25
|
+
return {
|
|
26
|
+
name: versionInfo.name,
|
|
27
|
+
version: versionInfo.version,
|
|
28
|
+
author,
|
|
29
|
+
maintainers: versionInfo.maintainers?.map((m) => m.name),
|
|
30
|
+
repository,
|
|
31
|
+
homepage: versionInfo.homepage,
|
|
32
|
+
license: versionInfo.license,
|
|
33
|
+
publishDate: data.time?.[resolvedVersion],
|
|
34
|
+
firstPublishDate: data.time?.created,
|
|
35
|
+
keywords: versionInfo.keywords,
|
|
36
|
+
verifiedPublisher: false,
|
|
37
|
+
scripts: versionInfo.scripts,
|
|
38
|
+
dependencies: versionInfo.dependencies,
|
|
39
|
+
devDependencies: versionInfo.devDependencies,
|
|
40
|
+
optionalDependencies: versionInfo.optionalDependencies,
|
|
41
|
+
description: versionInfo.description,
|
|
42
|
+
sourceUrl: repository,
|
|
43
|
+
tarballUrl: versionInfo.dist.tarball,
|
|
44
|
+
signedRelease: !!versionInfo.dist.integrity,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
async checkOsv(packageName, version, ecosystem) {
|
|
48
|
+
const response = await fetch('https://api.osv.dev/v1/query', {
|
|
49
|
+
method: 'POST',
|
|
50
|
+
headers: { 'Content-Type': 'application/json' },
|
|
51
|
+
body: JSON.stringify({
|
|
52
|
+
package: { name: packageName, ecosystem },
|
|
53
|
+
version,
|
|
54
|
+
}),
|
|
55
|
+
});
|
|
56
|
+
if (!response.ok)
|
|
57
|
+
return [];
|
|
58
|
+
const data = (await response.json());
|
|
59
|
+
return (data.vulns ?? []).map((v) => ({
|
|
60
|
+
id: v.id,
|
|
61
|
+
summary: v.summary,
|
|
62
|
+
severity: v.database_specific?.severity,
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=npm-registry-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"npm-registry-client.js","sourceRoot":"","sources":["../../src/adapters/npm-registry-client.ts"],"names":[],"mappings":"AA2BA,MAAM,OAAO,iBAAiB;IACX,WAAW,CAAS;IAErC,YAAY,WAAW,GAAG,4BAA4B;QACpD,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,IAAY,EAAE,OAAgB;QAChD,MAAM,OAAO,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC7D,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,WAAW,IAAI,OAAO,EAAE,CAAC;QAC7C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,0BAA0B,IAAI,KAAK,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;QACzE,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAwB,CAAC;QAC5D,MAAM,eAAe,GAAG,OAAO,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC;QAC5D,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;QACnD,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,WAAW,eAAe,kBAAkB,IAAI,EAAE,CAAC,CAAC;QACtE,CAAC;QAED,MAAM,MAAM,GAAG,OAAO,WAAW,CAAC,MAAM,KAAK,QAAQ;YACnD,CAAC,CAAC,WAAW,CAAC,MAAM;YACpB,CAAC,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC;QAE7B,MAAM,UAAU,GAAG,OAAO,WAAW,CAAC,UAAU,KAAK,QAAQ;YAC3D,CAAC,CAAC,WAAW,CAAC,UAAU;YACxB,CAAC,CAAC,WAAW,CAAC,UAAU,EAAE,GAAG,EAAE,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAE7E,OAAO;YACL,IAAI,EAAE,WAAW,CAAC,IAAI;YACtB,OAAO,EAAE,WAAW,CAAC,OAAO;YAC5B,MAAM;YACN,WAAW,EAAE,WAAW,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;YACxD,UAAU;YACV,QAAQ,EAAE,WAAW,CAAC,QAAQ;YAC9B,OAAO,EAAE,WAAW,CAAC,OAAO;YAC5B,WAAW,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,eAAe,CAAC;YACzC,gBAAgB,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO;YACpC,QAAQ,EAAE,WAAW,CAAC,QAAQ;YAC9B,iBAAiB,EAAE,KAAK;YACxB,OAAO,EAAE,WAAW,CAAC,OAAO;YAC5B,YAAY,EAAE,WAAW,CAAC,YAAY;YACtC,eAAe,EAAE,WAAW,CAAC,eAAe;YAC5C,oBAAoB,EAAE,WAAW,CAAC,oBAAoB;YACtD,WAAW,EAAE,WAAW,CAAC,WAAW;YACpC,SAAS,EAAE,UAAU;YACrB,UAAU,EAAE,WAAW,CAAC,IAAI,CAAC,OAAO;YACpC,aAAa,EAAE,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS;SAC5C,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,WAAmB,EAAE,OAAe,EAAE,SAAiB;QACpE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,8BAA8B,EAAE;YAC3D,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,OAAO,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE;gBACzC,OAAO;aACR,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE;YAAE,OAAO,EAAE,CAAC;QAE5B,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAkG,CAAC;QACtI,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACpC,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,QAAQ,EAAE,CAAC,CAAC,iBAAiB,EAAE,QAAQ;SACxC,CAAC,CAAC,CAAC;IACN,CAAC;CACF"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AnalysisContext, Analyzer } from './analyzer.js';
|
|
2
|
+
export declare class AiPromptAnalyzer implements Analyzer {
|
|
3
|
+
readonly id = "ai-prompt";
|
|
4
|
+
supports(ctx: AnalysisContext): boolean;
|
|
5
|
+
analyze(ctx: AnalysisContext): Promise<import("../domain/finding.js").Finding[]>;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=ai-prompt-analyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-prompt-analyzer.d.ts","sourceRoot":"","sources":["../../src/analyzers/ai-prompt-analyzer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AA8B/D,qBAAa,gBAAiB,YAAW,QAAQ;IAC/C,QAAQ,CAAC,EAAE,eAAe;IAE1B,QAAQ,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO;IAIjC,OAAO,CAAC,GAAG,EAAE,eAAe;CAgEnC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { createFinding } from '../domain/finding.js';
|
|
2
|
+
import { findMatchingLine } from './match-evidence.js';
|
|
3
|
+
import { AI_INJECTION_RULES, INVISIBLE_UNICODE, ZERO_WIDTH_CHARS } from './rules/index.js';
|
|
4
|
+
const PROMPT_EXTENSIONS = ['.md', '.txt', '.yaml', '.yml', '.json'];
|
|
5
|
+
const SKILL_FILE_PATTERN = /(?:^|\/)SKILL\.md$/i;
|
|
6
|
+
const GENERIC_PACKAGE_DOC_PATTERN = /(?:^|\/)(?:README|CHANGELOG|HISTORY|CONTRIBUTING|LICENSE)(?:\.\w+)?$/i;
|
|
7
|
+
const EXPLICIT_PROMPT_FILE_PATTERN = /(?:^|\/)(?:prompt|system-prompt|instructions)(?:\.\w+)?$|\.(?:prompt|skill)\.(?:md|txt|yaml|yml)$/i;
|
|
8
|
+
function isSkillTarget(ecosystem) {
|
|
9
|
+
return ecosystem === 'skill' || ecosystem === 'local';
|
|
10
|
+
}
|
|
11
|
+
function isPromptFile(path, ecosystem) {
|
|
12
|
+
if (SKILL_FILE_PATTERN.test(path) || path.toUpperCase().includes('SKILL')) {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
if (isSkillTarget(ecosystem)) {
|
|
16
|
+
return PROMPT_EXTENSIONS.some((ext) => path.endsWith(ext));
|
|
17
|
+
}
|
|
18
|
+
if (GENERIC_PACKAGE_DOC_PATTERN.test(path)) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
return EXPLICIT_PROMPT_FILE_PATTERN.test(path);
|
|
22
|
+
}
|
|
23
|
+
export class AiPromptAnalyzer {
|
|
24
|
+
id = 'ai-prompt';
|
|
25
|
+
supports(ctx) {
|
|
26
|
+
return ctx.artifact.files.some((f) => isPromptFile(f.path, ctx.target.ecosystem));
|
|
27
|
+
}
|
|
28
|
+
async analyze(ctx) {
|
|
29
|
+
const findings = [];
|
|
30
|
+
const promptFiles = ctx.artifact.files.filter((f) => isPromptFile(f.path, ctx.target.ecosystem));
|
|
31
|
+
for (const file of promptFiles) {
|
|
32
|
+
for (const rule of AI_INJECTION_RULES) {
|
|
33
|
+
rule.pattern.lastIndex = 0;
|
|
34
|
+
if (rule.pattern.test(file.content)) {
|
|
35
|
+
const match = findMatchingLine(file.content, rule.pattern);
|
|
36
|
+
findings.push(createFinding({
|
|
37
|
+
category: 'ai-prompt',
|
|
38
|
+
severity: rule.severity,
|
|
39
|
+
title: rule.title,
|
|
40
|
+
description: rule.description,
|
|
41
|
+
ruleId: rule.id,
|
|
42
|
+
file: file.path,
|
|
43
|
+
line: match?.line,
|
|
44
|
+
evidence: match?.evidence,
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (ZERO_WIDTH_CHARS.test(file.content)) {
|
|
49
|
+
findings.push(createFinding({
|
|
50
|
+
category: 'ai-prompt',
|
|
51
|
+
severity: 'CRITICAL',
|
|
52
|
+
title: 'Zero-width characters',
|
|
53
|
+
description: 'Hidden zero-width Unicode characters detected in prompt content',
|
|
54
|
+
ruleId: 'zero-width',
|
|
55
|
+
file: file.path,
|
|
56
|
+
}));
|
|
57
|
+
}
|
|
58
|
+
if (INVISIBLE_UNICODE.test(file.content)) {
|
|
59
|
+
findings.push(createFinding({
|
|
60
|
+
category: 'ai-prompt',
|
|
61
|
+
severity: 'HIGH',
|
|
62
|
+
title: 'Invisible Unicode characters',
|
|
63
|
+
description: 'Invisible Unicode characters detected in prompt content',
|
|
64
|
+
ruleId: 'invisible-unicode',
|
|
65
|
+
file: file.path,
|
|
66
|
+
}));
|
|
67
|
+
}
|
|
68
|
+
const htmlComments = file.content.match(/<!--[\s\S]*?-->/g);
|
|
69
|
+
if (htmlComments && htmlComments.length > 0) {
|
|
70
|
+
for (const comment of htmlComments) {
|
|
71
|
+
if (comment.length > 50) {
|
|
72
|
+
findings.push(createFinding({
|
|
73
|
+
category: 'ai-prompt',
|
|
74
|
+
severity: 'MEDIUM',
|
|
75
|
+
title: 'Hidden HTML comment',
|
|
76
|
+
description: 'Large HTML comment that may contain hidden instructions',
|
|
77
|
+
ruleId: 'html-comment',
|
|
78
|
+
file: file.path,
|
|
79
|
+
evidence: comment.slice(0, 100),
|
|
80
|
+
}));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return findings;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=ai-prompt-analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-prompt-analyzer.js","sourceRoot":"","sources":["../../src/analyzers/ai-prompt-analyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Artifact } from '../domain/artifact.js';
|
|
2
|
+
import type { Finding } from '../domain/finding.js';
|
|
3
|
+
import type { Target } from '../domain/target.js';
|
|
4
|
+
export interface AnalysisContext {
|
|
5
|
+
readonly artifact: Artifact;
|
|
6
|
+
readonly target: Target;
|
|
7
|
+
}
|
|
8
|
+
export interface Analyzer {
|
|
9
|
+
readonly id: string;
|
|
10
|
+
supports(ctx: AnalysisContext): boolean;
|
|
11
|
+
analyze(ctx: AnalysisContext): Promise<Finding[]>;
|
|
12
|
+
}
|
|
13
|
+
export declare function runAnalyzers(analyzers: Analyzer[], ctx: AnalysisContext): Promise<Finding[]>;
|
|
14
|
+
//# sourceMappingURL=analyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../../src/analyzers/analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC;IACxC,OAAO,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;CACnD;AAED,wBAAsB,YAAY,CAChC,SAAS,EAAE,QAAQ,EAAE,EACrB,GAAG,EAAE,eAAe,GACnB,OAAO,CAAC,OAAO,EAAE,CAAC,CASpB"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export async function runAnalyzers(analyzers, ctx) {
|
|
2
|
+
const findings = [];
|
|
3
|
+
for (const analyzer of analyzers) {
|
|
4
|
+
if (analyzer.supports(ctx)) {
|
|
5
|
+
const result = await analyzer.analyze(ctx);
|
|
6
|
+
findings.push(...result);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
return findings;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../../src/analyzers/analyzer.ts"],"names":[],"mappings":"AAeA,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,SAAqB,EACrB,GAAoB;IAEpB,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC3C,QAAQ,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AnalysisContext, Analyzer } from './analyzer.js';
|
|
2
|
+
import type { RegistryClient } from '../ports/registry-client.js';
|
|
3
|
+
export declare class DependencyAnalyzer implements Analyzer {
|
|
4
|
+
private readonly registry?;
|
|
5
|
+
readonly id = "dependency";
|
|
6
|
+
constructor(registry?: RegistryClient | undefined);
|
|
7
|
+
supports(ctx: AnalysisContext): boolean;
|
|
8
|
+
analyze(ctx: AnalysisContext): Promise<import("../domain/finding.js").Finding[]>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=dependency-analyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dependency-analyzer.d.ts","sourceRoot":"","sources":["../../src/analyzers/dependency-analyzer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAKlE,qBAAa,kBAAmB,YAAW,QAAQ;IAGrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC;IAFtC,QAAQ,CAAC,EAAE,gBAAgB;gBAEE,QAAQ,CAAC,EAAE,cAAc,YAAA;IAEtD,QAAQ,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO;IAIjC,OAAO,CAAC,GAAG,EAAE,eAAe;CAyEnC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { createFinding } from '../domain/finding.js';
|
|
2
|
+
const DEPENDENCY_WARNING_THRESHOLD = 50;
|
|
3
|
+
const DEPENDENCY_CRITICAL_THRESHOLD = 200;
|
|
4
|
+
export class DependencyAnalyzer {
|
|
5
|
+
registry;
|
|
6
|
+
id = 'dependency';
|
|
7
|
+
constructor(registry) {
|
|
8
|
+
this.registry = registry;
|
|
9
|
+
}
|
|
10
|
+
supports(ctx) {
|
|
11
|
+
return !!(ctx.artifact.metadata.dependencies || ctx.artifact.manifest);
|
|
12
|
+
}
|
|
13
|
+
async analyze(ctx) {
|
|
14
|
+
const findings = [];
|
|
15
|
+
const manifestDeps = ctx.artifact.manifest?.dependencies;
|
|
16
|
+
const deps = {
|
|
17
|
+
...(ctx.artifact.metadata.dependencies ?? {}),
|
|
18
|
+
...(manifestDeps ?? {}),
|
|
19
|
+
};
|
|
20
|
+
const depCount = Object.keys(deps).length;
|
|
21
|
+
if (depCount > DEPENDENCY_CRITICAL_THRESHOLD) {
|
|
22
|
+
findings.push(createFinding({
|
|
23
|
+
category: 'dependency',
|
|
24
|
+
severity: 'HIGH',
|
|
25
|
+
title: 'Excessive dependencies',
|
|
26
|
+
description: `Package has ${depCount} dependencies`,
|
|
27
|
+
ruleId: 'excessive-deps',
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
else if (depCount > DEPENDENCY_WARNING_THRESHOLD) {
|
|
31
|
+
findings.push(createFinding({
|
|
32
|
+
category: 'dependency',
|
|
33
|
+
severity: 'MEDIUM',
|
|
34
|
+
title: 'Many dependencies',
|
|
35
|
+
description: `Package has ${depCount} dependencies`,
|
|
36
|
+
ruleId: 'many-deps',
|
|
37
|
+
}));
|
|
38
|
+
}
|
|
39
|
+
for (const [name, version] of Object.entries(deps)) {
|
|
40
|
+
if (version.includes('http://') || version.includes('git+http')) {
|
|
41
|
+
findings.push(createFinding({
|
|
42
|
+
category: 'dependency',
|
|
43
|
+
severity: 'HIGH',
|
|
44
|
+
title: 'Non-HTTPS dependency source',
|
|
45
|
+
description: `Dependency ${name} uses non-HTTPS source: ${version}`,
|
|
46
|
+
ruleId: 'insecure-dep-source',
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
if (version.startsWith('file:') || version.startsWith('../')) {
|
|
50
|
+
findings.push(createFinding({
|
|
51
|
+
category: 'dependency',
|
|
52
|
+
severity: 'MEDIUM',
|
|
53
|
+
title: 'Local file dependency',
|
|
54
|
+
description: `Dependency ${name} references local file: ${version}`,
|
|
55
|
+
ruleId: 'local-dep',
|
|
56
|
+
}));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (this.registry && ctx.artifact.metadata.name && ctx.artifact.metadata.version) {
|
|
60
|
+
try {
|
|
61
|
+
const vulns = await this.registry.checkOsv(ctx.artifact.metadata.name, ctx.artifact.metadata.version, 'npm');
|
|
62
|
+
for (const vuln of vulns) {
|
|
63
|
+
findings.push(createFinding({
|
|
64
|
+
category: 'dependency',
|
|
65
|
+
severity: vuln.severity === 'CRITICAL' ? 'CRITICAL' : 'HIGH',
|
|
66
|
+
title: `Known vulnerability: ${vuln.id}`,
|
|
67
|
+
description: vuln.summary,
|
|
68
|
+
ruleId: 'cve',
|
|
69
|
+
}));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// OSV lookup is best-effort
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return findings;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=dependency-analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dependency-analyzer.js","sourceRoot":"","sources":["../../src/analyzers/dependency-analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAIrD,MAAM,4BAA4B,GAAG,EAAE,CAAC;AACxC,MAAM,6BAA6B,GAAG,GAAG,CAAC;AAE1C,MAAM,OAAO,kBAAkB;IAGA;IAFpB,EAAE,GAAG,YAAY,CAAC;IAE3B,YAA6B,QAAyB;QAAzB,aAAQ,GAAR,QAAQ,CAAiB;IAAG,CAAC;IAE1D,QAAQ,CAAC,GAAoB;QAC3B,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACzE,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,GAAoB;QAChC,MAAM,QAAQ,GAAG,EAAE,CAAC;QACpB,MAAM,YAAY,GAAG,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,YAAkD,CAAC;QAC/F,MAAM,IAAI,GAAG;YACX,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,IAAI,EAAE,CAAC;YAC7C,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC;SACxB,CAAC;QAEF,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;QAE1C,IAAI,QAAQ,GAAG,6BAA6B,EAAE,CAAC;YAC7C,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC;gBAC1B,QAAQ,EAAE,YAAY;gBACtB,QAAQ,EAAE,MAAM;gBAChB,KAAK,EAAE,wBAAwB;gBAC/B,WAAW,EAAE,eAAe,QAAQ,eAAe;gBACnD,MAAM,EAAE,gBAAgB;aACzB,CAAC,CAAC,CAAC;QACN,CAAC;aAAM,IAAI,QAAQ,GAAG,4BAA4B,EAAE,CAAC;YACnD,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC;gBAC1B,QAAQ,EAAE,YAAY;gBACtB,QAAQ,EAAE,QAAQ;gBAClB,KAAK,EAAE,mBAAmB;gBAC1B,WAAW,EAAE,eAAe,QAAQ,eAAe;gBACnD,MAAM,EAAE,WAAW;aACpB,CAAC,CAAC,CAAC;QACN,CAAC;QAED,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACnD,IAAI,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;gBAChE,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC;oBAC1B,QAAQ,EAAE,YAAY;oBACtB,QAAQ,EAAE,MAAM;oBAChB,KAAK,EAAE,6BAA6B;oBACpC,WAAW,EAAE,cAAc,IAAI,2BAA2B,OAAO,EAAE;oBACnE,MAAM,EAAE,qBAAqB;iBAC9B,CAAC,CAAC,CAAC;YACN,CAAC;YAED,IAAI,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC7D,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC;oBAC1B,QAAQ,EAAE,YAAY;oBACtB,QAAQ,EAAE,QAAQ;oBAClB,KAAK,EAAE,uBAAuB;oBAC9B,WAAW,EAAE,cAAc,IAAI,2BAA2B,OAAO,EAAE;oBACnE,MAAM,EAAE,WAAW;iBACpB,CAAC,CAAC,CAAC;YACN,CAAC;QACH,CAAC;QAED,IAAI,IAAI,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YACjF,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,CACxC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAC1B,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAC7B,KAAK,CACN,CAAC;gBACF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBACzB,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC;wBAC1B,QAAQ,EAAE,YAAY;wBACtB,QAAQ,EAAE,IAAI,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM;wBAC5D,KAAK,EAAE,wBAAwB,IAAI,CAAC,EAAE,EAAE;wBACxC,WAAW,EAAE,IAAI,CAAC,OAAO;wBACzB,MAAM,EAAE,KAAK;qBACd,CAAC,CAAC,CAAC;gBACN,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,4BAA4B;YAC9B,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Analyzer } from './analyzer.js';
|
|
2
|
+
import type { RegistryClient } from '../ports/registry-client.js';
|
|
3
|
+
export declare function createDefaultAnalyzers(registry?: RegistryClient): Analyzer[];
|
|
4
|
+
export * from './analyzer.js';
|
|
5
|
+
export * from './metadata-analyzer.js';
|
|
6
|
+
export * from './source-analyzer.js';
|
|
7
|
+
export * from './static-code-analyzer.js';
|
|
8
|
+
export * from './install-script-analyzer.js';
|
|
9
|
+
export * from './ai-prompt-analyzer.js';
|
|
10
|
+
export * from './secret-analyzer.js';
|
|
11
|
+
export * from './dependency-analyzer.js';
|
|
12
|
+
export * from './network-analyzer.js';
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/analyzers/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAS9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElE,wBAAgB,sBAAsB,CAAC,QAAQ,CAAC,EAAE,cAAc,GAAG,QAAQ,EAAE,CAW5E;AAED,cAAc,eAAe,CAAC;AAC9B,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { AiPromptAnalyzer } from './ai-prompt-analyzer.js';
|
|
2
|
+
import { DependencyAnalyzer } from './dependency-analyzer.js';
|
|
3
|
+
import { InstallScriptAnalyzer } from './install-script-analyzer.js';
|
|
4
|
+
import { MetadataAnalyzer } from './metadata-analyzer.js';
|
|
5
|
+
import { NetworkAnalyzer } from './network-analyzer.js';
|
|
6
|
+
import { SecretAnalyzer } from './secret-analyzer.js';
|
|
7
|
+
import { SourceAnalyzer } from './source-analyzer.js';
|
|
8
|
+
import { StaticCodeAnalyzer } from './static-code-analyzer.js';
|
|
9
|
+
export function createDefaultAnalyzers(registry) {
|
|
10
|
+
return [
|
|
11
|
+
new MetadataAnalyzer(),
|
|
12
|
+
new SourceAnalyzer(),
|
|
13
|
+
new StaticCodeAnalyzer(),
|
|
14
|
+
new InstallScriptAnalyzer(),
|
|
15
|
+
new AiPromptAnalyzer(),
|
|
16
|
+
new SecretAnalyzer(),
|
|
17
|
+
new DependencyAnalyzer(registry),
|
|
18
|
+
new NetworkAnalyzer(),
|
|
19
|
+
];
|
|
20
|
+
}
|
|
21
|
+
export * from './analyzer.js';
|
|
22
|
+
export * from './metadata-analyzer.js';
|
|
23
|
+
export * from './source-analyzer.js';
|
|
24
|
+
export * from './static-code-analyzer.js';
|
|
25
|
+
export * from './install-script-analyzer.js';
|
|
26
|
+
export * from './ai-prompt-analyzer.js';
|
|
27
|
+
export * from './secret-analyzer.js';
|
|
28
|
+
export * from './dependency-analyzer.js';
|
|
29
|
+
export * from './network-analyzer.js';
|
|
30
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/analyzers/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAG/D,MAAM,UAAU,sBAAsB,CAAC,QAAyB;IAC9D,OAAO;QACL,IAAI,gBAAgB,EAAE;QACtB,IAAI,cAAc,EAAE;QACpB,IAAI,kBAAkB,EAAE;QACxB,IAAI,qBAAqB,EAAE;QAC3B,IAAI,gBAAgB,EAAE;QACtB,IAAI,cAAc,EAAE;QACpB,IAAI,kBAAkB,CAAC,QAAQ,CAAC;QAChC,IAAI,eAAe,EAAE;KACtB,CAAC;AACJ,CAAC;AAED,cAAc,eAAe,CAAC;AAC9B,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AnalysisContext, Analyzer } from './analyzer.js';
|
|
2
|
+
export declare class InstallScriptAnalyzer implements Analyzer {
|
|
3
|
+
readonly id = "install-script";
|
|
4
|
+
supports(ctx: AnalysisContext): boolean;
|
|
5
|
+
analyze(ctx: AnalysisContext): Promise<import("../domain/finding.js").Finding[]>;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=install-script-analyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-script-analyzer.d.ts","sourceRoot":"","sources":["../../src/analyzers/install-script-analyzer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAgB/D,qBAAa,qBAAsB,YAAW,QAAQ;IACpD,QAAQ,CAAC,EAAE,oBAAoB;IAE/B,QAAQ,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO;IAIjC,OAAO,CAAC,GAAG,EAAE,eAAe;CA+CnC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { createFinding } from '../domain/finding.js';
|
|
2
|
+
const INSTALL_SCRIPT_KEYS = ['postinstall', 'preinstall', 'prepare', 'install', 'prepublish'];
|
|
3
|
+
const DANGEROUS_INSTALL_PATTERNS = [
|
|
4
|
+
{ pattern: /curl\s+[^|]+\|\s*(?:bash|sh)/gi, severity: 'CRITICAL', title: 'curl pipe to shell in install script' },
|
|
5
|
+
{ pattern: /wget\s+[^|]+\|\s*(?:bash|sh)/gi, severity: 'CRITICAL', title: 'wget pipe to shell in install script' },
|
|
6
|
+
{ pattern: /Invoke-WebRequest|Invoke-RestMethod/gi, severity: 'HIGH', title: 'PowerShell web request in install script' },
|
|
7
|
+
{ pattern: /\bsudo\s+/g, severity: 'HIGH', title: 'sudo in install script' },
|
|
8
|
+
{ pattern: /chmod\s+\+x/g, severity: 'MEDIUM', title: 'chmod +x in install script' },
|
|
9
|
+
{ pattern: /rm\s+-rf/g, severity: 'HIGH', title: 'rm -rf in install script' },
|
|
10
|
+
{ pattern: /npx\s+/g, severity: 'MEDIUM', title: 'npx in install script' },
|
|
11
|
+
{ pattern: /npm\s+exec/g, severity: 'MEDIUM', title: 'npm exec in install script' },
|
|
12
|
+
{ pattern: /docker\s+pull/g, severity: 'MEDIUM', title: 'docker pull in install script' },
|
|
13
|
+
{ pattern: /pip\s+install/g, severity: 'MEDIUM', title: 'pip install in install script' },
|
|
14
|
+
];
|
|
15
|
+
export class InstallScriptAnalyzer {
|
|
16
|
+
id = 'install-script';
|
|
17
|
+
supports(ctx) {
|
|
18
|
+
return !!ctx.artifact.metadata.scripts;
|
|
19
|
+
}
|
|
20
|
+
async analyze(ctx) {
|
|
21
|
+
const findings = [];
|
|
22
|
+
const scripts = ctx.artifact.metadata.scripts ?? {};
|
|
23
|
+
for (const key of INSTALL_SCRIPT_KEYS) {
|
|
24
|
+
const script = scripts[key];
|
|
25
|
+
if (!script)
|
|
26
|
+
continue;
|
|
27
|
+
findings.push(createFinding({
|
|
28
|
+
category: 'install-script',
|
|
29
|
+
severity: 'MEDIUM',
|
|
30
|
+
title: `Install script: ${key}`,
|
|
31
|
+
description: `Package defines a ${key} script`,
|
|
32
|
+
ruleId: `script-${key}`,
|
|
33
|
+
evidence: script,
|
|
34
|
+
}));
|
|
35
|
+
for (const check of DANGEROUS_INSTALL_PATTERNS) {
|
|
36
|
+
check.pattern.lastIndex = 0;
|
|
37
|
+
if (check.pattern.test(script)) {
|
|
38
|
+
findings.push(createFinding({
|
|
39
|
+
category: 'install-script',
|
|
40
|
+
severity: check.severity,
|
|
41
|
+
title: check.title,
|
|
42
|
+
description: `Dangerous pattern in ${key} script: ${check.title}`,
|
|
43
|
+
ruleId: `dangerous-${key}`,
|
|
44
|
+
evidence: script,
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
for (const file of ctx.artifact.files) {
|
|
50
|
+
if (file.path.match(/postinstall\.(sh|ps1|js)$/i)) {
|
|
51
|
+
findings.push(createFinding({
|
|
52
|
+
category: 'install-script',
|
|
53
|
+
severity: 'HIGH',
|
|
54
|
+
title: 'Standalone install script file',
|
|
55
|
+
description: `Found install script file: ${file.path}`,
|
|
56
|
+
ruleId: 'standalone-script',
|
|
57
|
+
file: file.path,
|
|
58
|
+
}));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return findings;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=install-script-analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-script-analyzer.js","sourceRoot":"","sources":["../../src/analyzers/install-script-analyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"match-evidence.d.ts","sourceRoot":"","sources":["../../src/analyzers/match-evidence.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAEvC,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAYhD"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const MAX_EVIDENCE_LENGTH = 120;
|
|
2
|
+
export function findMatchingLine(content, pattern) {
|
|
3
|
+
const lines = content.split('\n');
|
|
4
|
+
for (let i = 0; i < lines.length; i++) {
|
|
5
|
+
pattern.lastIndex = 0;
|
|
6
|
+
if (pattern.test(lines[i])) {
|
|
7
|
+
return {
|
|
8
|
+
line: i + 1,
|
|
9
|
+
evidence: lines[i].trim().slice(0, MAX_EVIDENCE_LENGTH),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=match-evidence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"match-evidence.js","sourceRoot":"","sources":["../../src/analyzers/match-evidence.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEvC,MAAM,UAAU,gBAAgB,CAC9B,OAAe,EACf,OAAe;IAEf,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC;QACtB,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC;YAC5B,OAAO;gBACL,IAAI,EAAE,CAAC,GAAG,CAAC;gBACX,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,mBAAmB,CAAC;aACzD,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AnalysisContext, Analyzer } from './analyzer.js';
|
|
2
|
+
export declare class MetadataAnalyzer implements Analyzer {
|
|
3
|
+
readonly id = "metadata";
|
|
4
|
+
supports(): boolean;
|
|
5
|
+
analyze(ctx: AnalysisContext): Promise<import("../domain/finding.js").Finding[]>;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=metadata-analyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata-analyzer.d.ts","sourceRoot":"","sources":["../../src/analyzers/metadata-analyzer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAS/D,qBAAa,gBAAiB,YAAW,QAAQ;IAC/C,QAAQ,CAAC,EAAE,cAAc;IAEzB,QAAQ,IAAI,OAAO;IAIb,OAAO,CAAC,GAAG,EAAE,eAAe;CAmGnC"}
|