acidtest 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/LICENSE +21 -0
- package/README.md +104 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +170 -0
- package/dist/index.js.map +1 -0
- package/dist/layers/code.d.ts +10 -0
- package/dist/layers/code.d.ts.map +1 -0
- package/dist/layers/code.js +196 -0
- package/dist/layers/code.js.map +1 -0
- package/dist/layers/crossref.d.ts +10 -0
- package/dist/layers/crossref.d.ts.map +1 -0
- package/dist/layers/crossref.js +143 -0
- package/dist/layers/crossref.js.map +1 -0
- package/dist/layers/injection.d.ts +10 -0
- package/dist/layers/injection.d.ts.map +1 -0
- package/dist/layers/injection.js +88 -0
- package/dist/layers/injection.js.map +1 -0
- package/dist/layers/permissions.d.ts +10 -0
- package/dist/layers/permissions.d.ts.map +1 -0
- package/dist/layers/permissions.js +120 -0
- package/dist/layers/permissions.js.map +1 -0
- package/dist/pattern-loader.d.ts +14 -0
- package/dist/pattern-loader.d.ts.map +1 -0
- package/dist/pattern-loader.js +50 -0
- package/dist/pattern-loader.js.map +1 -0
- package/dist/patterns/credential-patterns.json +77 -0
- package/dist/patterns/dangerous-imports.json +113 -0
- package/dist/patterns/exfiltration-sinks.json +77 -0
- package/dist/patterns/obfuscation.json +65 -0
- package/dist/patterns/prompt-injection.json +125 -0
- package/dist/patterns/sensitive-paths.json +89 -0
- package/dist/reporter.d.ts +14 -0
- package/dist/reporter.d.ts.map +1 -0
- package/dist/reporter.js +175 -0
- package/dist/reporter.js.map +1 -0
- package/dist/scanner.d.ts +15 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +176 -0
- package/dist/scanner.js.map +1 -0
- package/dist/scoring.d.ts +23 -0
- package/dist/scoring.d.ts.map +1 -0
- package/dist/scoring.js +85 -0
- package/dist/scoring.js.map +1 -0
- package/dist/types.d.ts +112 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +46 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Currently
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# AcidTest
|
|
2
|
+
|
|
3
|
+
Security scanner for AI agent skills. Scan before you install.
|
|
4
|
+
|
|
5
|
+
## The Problem
|
|
6
|
+
|
|
7
|
+
The AgentSkills ecosystem has 66,000+ skills. Recent audits found:
|
|
8
|
+
- **26%** contain at least one vulnerability
|
|
9
|
+
- **230+** confirmed malicious skills uploaded to ClawHub in one week
|
|
10
|
+
- **341** skills flagged in the ClawHavoc campaign
|
|
11
|
+
|
|
12
|
+
## Quick Start
|
|
13
|
+
```bash
|
|
14
|
+
npx acidtest scan ./my-skill
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
No API keys. No configuration. No Python.
|
|
18
|
+
|
|
19
|
+
## Example Output
|
|
20
|
+
```
|
|
21
|
+
AcidTest v0.1.0
|
|
22
|
+
|
|
23
|
+
Scanning: proactive-agent
|
|
24
|
+
Source: test-skills/proactive-agent-1-2-4-1
|
|
25
|
+
|
|
26
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
27
|
+
|
|
28
|
+
TRUST SCORE: 72/100 ███████░░░ WARN
|
|
29
|
+
|
|
30
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
31
|
+
|
|
32
|
+
FINDINGS
|
|
33
|
+
|
|
34
|
+
✖ CRITICAL instruction-override
|
|
35
|
+
SKILL.md:170
|
|
36
|
+
Attempts to override agent instructions
|
|
37
|
+
3 matches found
|
|
38
|
+
|
|
39
|
+
○ LOW No declared permissions
|
|
40
|
+
SKILL.md
|
|
41
|
+
Skill declares no permissions (bins, env, or allowed-tools)
|
|
42
|
+
Legitimate skills typically declare at least one permission
|
|
43
|
+
|
|
44
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
45
|
+
|
|
46
|
+
RECOMMENDATION: Do not install. Prompt injection attempt detected.
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## What It Detects
|
|
50
|
+
|
|
51
|
+
- Prompt injection attempts
|
|
52
|
+
- Undeclared network calls
|
|
53
|
+
- Credential harvesting
|
|
54
|
+
- Permission mismatches
|
|
55
|
+
- Data exfiltration patterns
|
|
56
|
+
- Obfuscated payloads
|
|
57
|
+
|
|
58
|
+
## How It Works
|
|
59
|
+
|
|
60
|
+
AcidTest runs four analysis layers: permission audit, prompt injection scan, code analysis (via TypeScript AST), and cross-reference checks that catch when code behavior doesn't match declared permissions.
|
|
61
|
+
|
|
62
|
+
For technical details, see [BUILD-SPEC.md](./BUILD-SPEC.md).
|
|
63
|
+
|
|
64
|
+
## Install
|
|
65
|
+
```bash
|
|
66
|
+
npm install -g acidtest
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Or use without installing:
|
|
70
|
+
```bash
|
|
71
|
+
npx acidtest scan ./path-to-skill
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Usage
|
|
75
|
+
```bash
|
|
76
|
+
# Scan a skill directory
|
|
77
|
+
acidtest scan ./my-skill
|
|
78
|
+
|
|
79
|
+
# Scan a SKILL.md file directly
|
|
80
|
+
acidtest scan ./my-skill/SKILL.md
|
|
81
|
+
|
|
82
|
+
# Scan all skills in a directory
|
|
83
|
+
acidtest scan-all ./skills
|
|
84
|
+
|
|
85
|
+
# JSON output
|
|
86
|
+
acidtest scan ./my-skill --json
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Scoring
|
|
90
|
+
|
|
91
|
+
Starts at 100, deducts by severity (CRITICAL: -25, HIGH: -15, MEDIUM: -8, LOW: -3). Score 80+ is PASS, 50-79 is WARN, 20-49 is FAIL, below 20 is DANGER.
|
|
92
|
+
|
|
93
|
+
## Contributing
|
|
94
|
+
|
|
95
|
+
Detection patterns are JSON files in `src/patterns/`. Add new patterns and submit a PR.
|
|
96
|
+
|
|
97
|
+
## License
|
|
98
|
+
|
|
99
|
+
MIT
|
|
100
|
+
|
|
101
|
+
## Links
|
|
102
|
+
|
|
103
|
+
- Issues: https://github.com/currentlycurrently/acidtest/issues
|
|
104
|
+
- Website: https://acidtest.dev
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;GAGG"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* AcidTest CLI entry point
|
|
4
|
+
* Parses arguments and routes to appropriate commands
|
|
5
|
+
*/
|
|
6
|
+
import { scanSkill, scanAllSkills } from './scanner.js';
|
|
7
|
+
import { reportToTerminal, reportAsJSON } from './reporter.js';
|
|
8
|
+
const VERSION = '0.1.0';
|
|
9
|
+
/**
|
|
10
|
+
* Main CLI function
|
|
11
|
+
*/
|
|
12
|
+
async function main() {
|
|
13
|
+
const args = process.argv.slice(2);
|
|
14
|
+
// Handle --version flag
|
|
15
|
+
if (args.includes('--version') || args.includes('-v')) {
|
|
16
|
+
console.log(`acidtest v${VERSION}`);
|
|
17
|
+
process.exit(0);
|
|
18
|
+
}
|
|
19
|
+
// Handle --help flag
|
|
20
|
+
if (args.includes('--help') || args.includes('-h') || args.length === 0) {
|
|
21
|
+
printHelp();
|
|
22
|
+
process.exit(0);
|
|
23
|
+
}
|
|
24
|
+
// Parse command
|
|
25
|
+
const command = args[0];
|
|
26
|
+
if (command === 'scan') {
|
|
27
|
+
await handleScan(args.slice(1));
|
|
28
|
+
}
|
|
29
|
+
else if (command === 'scan-all') {
|
|
30
|
+
await handleScanAll(args.slice(1));
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
console.error(`Unknown command: ${command}`);
|
|
34
|
+
console.error('Run "acidtest --help" for usage information.');
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Handle 'scan' command
|
|
40
|
+
*/
|
|
41
|
+
async function handleScan(args) {
|
|
42
|
+
// Parse flags
|
|
43
|
+
const jsonOutput = args.includes('--json');
|
|
44
|
+
const paths = args.filter(arg => !arg.startsWith('--'));
|
|
45
|
+
if (paths.length === 0) {
|
|
46
|
+
console.error('Error: No skill path provided');
|
|
47
|
+
console.error('Usage: acidtest scan <path-to-skill> [--json]');
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
const skillPath = paths[0];
|
|
51
|
+
try {
|
|
52
|
+
const result = await scanSkill(skillPath);
|
|
53
|
+
if (jsonOutput) {
|
|
54
|
+
reportAsJSON(result);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
reportToTerminal(result);
|
|
58
|
+
}
|
|
59
|
+
// Exit with non-zero code for FAIL or DANGER
|
|
60
|
+
if (result.status === 'FAIL' || result.status === 'DANGER') {
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
console.error('Error scanning skill:', error.message);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Handle 'scan-all' command
|
|
71
|
+
*/
|
|
72
|
+
async function handleScanAll(args) {
|
|
73
|
+
// Parse flags
|
|
74
|
+
const jsonOutput = args.includes('--json');
|
|
75
|
+
const paths = args.filter(arg => !arg.startsWith('--'));
|
|
76
|
+
if (paths.length === 0) {
|
|
77
|
+
console.error('Error: No directory path provided');
|
|
78
|
+
console.error('Usage: acidtest scan-all <directory> [--json]');
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
const directory = paths[0];
|
|
82
|
+
try {
|
|
83
|
+
const results = await scanAllSkills(directory);
|
|
84
|
+
if (results.length === 0) {
|
|
85
|
+
console.log('No skills found in directory');
|
|
86
|
+
process.exit(0);
|
|
87
|
+
}
|
|
88
|
+
if (jsonOutput) {
|
|
89
|
+
console.log(JSON.stringify(results, null, 2));
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
// Print summary for each skill
|
|
93
|
+
for (let i = 0; i < results.length; i++) {
|
|
94
|
+
const result = results[i];
|
|
95
|
+
reportToTerminal(result);
|
|
96
|
+
// Add separator between skills (except for last one)
|
|
97
|
+
if (i < results.length - 1) {
|
|
98
|
+
console.log('\n' + '='.repeat(60) + '\n');
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Print summary statistics
|
|
102
|
+
console.log('\n' + '='.repeat(60));
|
|
103
|
+
console.log(`\nScanned ${results.length} skill(s):\n`);
|
|
104
|
+
const pass = results.filter(r => r.status === 'PASS').length;
|
|
105
|
+
const warn = results.filter(r => r.status === 'WARN').length;
|
|
106
|
+
const fail = results.filter(r => r.status === 'FAIL').length;
|
|
107
|
+
const danger = results.filter(r => r.status === 'DANGER').length;
|
|
108
|
+
if (pass > 0)
|
|
109
|
+
console.log(` PASS: ${pass}`);
|
|
110
|
+
if (warn > 0)
|
|
111
|
+
console.log(` WARN: ${warn}`);
|
|
112
|
+
if (fail > 0)
|
|
113
|
+
console.log(` FAIL: ${fail}`);
|
|
114
|
+
if (danger > 0)
|
|
115
|
+
console.log(` DANGER: ${danger}`);
|
|
116
|
+
console.log();
|
|
117
|
+
}
|
|
118
|
+
// Exit with non-zero if any skill failed
|
|
119
|
+
const hasFailures = results.some(r => r.status === 'FAIL' || r.status === 'DANGER');
|
|
120
|
+
if (hasFailures) {
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
console.error('Error scanning directory:', error.message);
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Print help text
|
|
131
|
+
*/
|
|
132
|
+
function printHelp() {
|
|
133
|
+
console.log(`
|
|
134
|
+
AcidTest v${VERSION}
|
|
135
|
+
Security scanner for AI agent skills
|
|
136
|
+
|
|
137
|
+
USAGE:
|
|
138
|
+
acidtest scan <path-to-skill> [--json]
|
|
139
|
+
acidtest scan-all <directory> [--json]
|
|
140
|
+
acidtest --version
|
|
141
|
+
acidtest --help
|
|
142
|
+
|
|
143
|
+
COMMANDS:
|
|
144
|
+
scan Scan a single skill directory or SKILL.md file
|
|
145
|
+
scan-all Recursively scan all skills in a directory
|
|
146
|
+
|
|
147
|
+
OPTIONS:
|
|
148
|
+
--json Output results as JSON
|
|
149
|
+
--version Print version number
|
|
150
|
+
--help Show this help message
|
|
151
|
+
|
|
152
|
+
EXAMPLES:
|
|
153
|
+
# Scan a single skill
|
|
154
|
+
acidtest scan ./my-skill
|
|
155
|
+
|
|
156
|
+
# Scan with JSON output
|
|
157
|
+
acidtest scan ./my-skill --json
|
|
158
|
+
|
|
159
|
+
# Scan all skills in a directory
|
|
160
|
+
acidtest scan-all ./skills-directory
|
|
161
|
+
|
|
162
|
+
For more information, visit: https://acidtest.dev
|
|
163
|
+
`);
|
|
164
|
+
}
|
|
165
|
+
// Run CLI
|
|
166
|
+
main().catch(error => {
|
|
167
|
+
console.error('Unexpected error:', error);
|
|
168
|
+
process.exit(1);
|
|
169
|
+
});
|
|
170
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer 3: Code Analysis
|
|
3
|
+
* Performs AST analysis on JavaScript/TypeScript handler files
|
|
4
|
+
*/
|
|
5
|
+
import type { Skill, LayerResult } from '../types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Scan code files for security issues
|
|
8
|
+
*/
|
|
9
|
+
export declare function scanCode(skill: Skill): Promise<LayerResult>;
|
|
10
|
+
//# sourceMappingURL=code.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code.d.ts","sourceRoot":"","sources":["../../src/layers/code.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAW,WAAW,EAAY,MAAM,aAAa,CAAC;AAGzE;;GAEG;AACH,wBAAsB,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC,CA0CjE"}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer 3: Code Analysis
|
|
3
|
+
* Performs AST analysis on JavaScript/TypeScript handler files
|
|
4
|
+
*/
|
|
5
|
+
import ts from 'typescript';
|
|
6
|
+
import { loadPatterns } from '../pattern-loader.js';
|
|
7
|
+
/**
|
|
8
|
+
* Scan code files for security issues
|
|
9
|
+
*/
|
|
10
|
+
export async function scanCode(skill) {
|
|
11
|
+
const findings = [];
|
|
12
|
+
// If no code files, nothing to scan
|
|
13
|
+
if (skill.codeFiles.length === 0) {
|
|
14
|
+
return {
|
|
15
|
+
layer: 'code',
|
|
16
|
+
findings
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
// Load code-related patterns
|
|
20
|
+
const dangerousImports = await loadPatterns('dangerous-imports');
|
|
21
|
+
const pathPatterns = await loadPatterns('sensitive-paths');
|
|
22
|
+
const exfiltrationPatterns = await loadPatterns('exfiltration-sinks');
|
|
23
|
+
const obfuscationPatterns = await loadPatterns('obfuscation');
|
|
24
|
+
const credentialPatterns = await loadPatterns('credential-patterns');
|
|
25
|
+
// Combine all code-layer patterns
|
|
26
|
+
const allPatterns = [
|
|
27
|
+
...dangerousImports,
|
|
28
|
+
...pathPatterns,
|
|
29
|
+
...exfiltrationPatterns,
|
|
30
|
+
...obfuscationPatterns,
|
|
31
|
+
...credentialPatterns
|
|
32
|
+
].filter(p => p.layer === 'code');
|
|
33
|
+
// Scan each code file
|
|
34
|
+
for (const codeFile of skill.codeFiles) {
|
|
35
|
+
// Regex-based pattern scanning
|
|
36
|
+
const regexFindings = scanCodeWithRegex(codeFile, allPatterns);
|
|
37
|
+
findings.push(...regexFindings);
|
|
38
|
+
// AST-based analysis
|
|
39
|
+
const astFindings = scanCodeWithAST(codeFile);
|
|
40
|
+
findings.push(...astFindings);
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
layer: 'code',
|
|
44
|
+
findings
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Scan code file using regex patterns
|
|
49
|
+
*/
|
|
50
|
+
function scanCodeWithRegex(codeFile, patterns) {
|
|
51
|
+
const findings = [];
|
|
52
|
+
const content = codeFile.content;
|
|
53
|
+
const relativePath = codeFile.path;
|
|
54
|
+
for (const pattern of patterns) {
|
|
55
|
+
const regex = new RegExp(pattern.match.value, pattern.match.flags || '');
|
|
56
|
+
const matches = content.match(regex);
|
|
57
|
+
if (matches && matches.length > 0) {
|
|
58
|
+
// Find line number for first match
|
|
59
|
+
const lineNumber = findLineNumber(content, matches[0]);
|
|
60
|
+
findings.push({
|
|
61
|
+
severity: pattern.severity,
|
|
62
|
+
category: pattern.category || 'code-issue',
|
|
63
|
+
title: pattern.name,
|
|
64
|
+
file: relativePath,
|
|
65
|
+
line: lineNumber,
|
|
66
|
+
detail: pattern.description || `Pattern match: ${pattern.name}`,
|
|
67
|
+
evidence: `Found ${matches.length} occurrence(s)`,
|
|
68
|
+
patternId: pattern.id
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return findings;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Scan code file using TypeScript AST
|
|
76
|
+
*/
|
|
77
|
+
function scanCodeWithAST(codeFile) {
|
|
78
|
+
const findings = [];
|
|
79
|
+
const relativePath = codeFile.path;
|
|
80
|
+
try {
|
|
81
|
+
// Parse TypeScript/JavaScript
|
|
82
|
+
const sourceFile = ts.createSourceFile(codeFile.path, codeFile.content, ts.ScriptTarget.Latest, true);
|
|
83
|
+
// Extract all URLs from string literals
|
|
84
|
+
const urls = extractURLs(sourceFile);
|
|
85
|
+
if (urls.length > 0) {
|
|
86
|
+
findings.push({
|
|
87
|
+
severity: 'INFO',
|
|
88
|
+
category: 'network-urls',
|
|
89
|
+
title: 'URL literals found in code',
|
|
90
|
+
file: relativePath,
|
|
91
|
+
detail: `Found ${urls.length} URL(s) in code`,
|
|
92
|
+
evidence: urls.slice(0, 5).join(', ') + (urls.length > 5 ? '...' : '')
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
// Check for suspicious patterns
|
|
96
|
+
const suspiciousFindings = detectSuspiciousPatterns(sourceFile, relativePath);
|
|
97
|
+
findings.push(...suspiciousFindings);
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
// If parsing fails, the code might be malformed or obfuscated
|
|
101
|
+
findings.push({
|
|
102
|
+
severity: 'MEDIUM',
|
|
103
|
+
category: 'parse-error',
|
|
104
|
+
title: 'Failed to parse code file',
|
|
105
|
+
file: relativePath,
|
|
106
|
+
detail: 'Could not parse file as valid JavaScript/TypeScript',
|
|
107
|
+
evidence: 'May indicate obfuscated or malformed code'
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
return findings;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Extract URL strings from source file
|
|
114
|
+
*/
|
|
115
|
+
function extractURLs(sourceFile) {
|
|
116
|
+
const urls = [];
|
|
117
|
+
const urlPattern = /^https?:\/\/[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/;
|
|
118
|
+
function visit(node) {
|
|
119
|
+
if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) {
|
|
120
|
+
const text = node.text;
|
|
121
|
+
if (urlPattern.test(text)) {
|
|
122
|
+
urls.push(text);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
ts.forEachChild(node, visit);
|
|
126
|
+
}
|
|
127
|
+
visit(sourceFile);
|
|
128
|
+
return urls;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Detect suspicious patterns via AST traversal
|
|
132
|
+
*/
|
|
133
|
+
function detectSuspiciousPatterns(sourceFile, filePath) {
|
|
134
|
+
const findings = [];
|
|
135
|
+
const dynamicRequires = [];
|
|
136
|
+
const evals = [];
|
|
137
|
+
function visit(node) {
|
|
138
|
+
// Check for eval() calls
|
|
139
|
+
if (ts.isCallExpression(node)) {
|
|
140
|
+
const expression = node.expression;
|
|
141
|
+
if (ts.isIdentifier(expression) && expression.text === 'eval') {
|
|
142
|
+
const lineNumber = sourceFile.getLineAndCharacterOfPosition(node.getStart()).line + 1;
|
|
143
|
+
evals.push(lineNumber);
|
|
144
|
+
}
|
|
145
|
+
// Check for require() with non-literal arguments
|
|
146
|
+
if (ts.isIdentifier(expression) && expression.text === 'require') {
|
|
147
|
+
if (node.arguments.length > 0) {
|
|
148
|
+
const arg = node.arguments[0];
|
|
149
|
+
if (!ts.isStringLiteral(arg) && !ts.isNoSubstitutionTemplateLiteral(arg)) {
|
|
150
|
+
const lineNumber = sourceFile.getLineAndCharacterOfPosition(node.getStart()).line + 1;
|
|
151
|
+
dynamicRequires.push(lineNumber);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
ts.forEachChild(node, visit);
|
|
157
|
+
}
|
|
158
|
+
visit(sourceFile);
|
|
159
|
+
// Add findings for dynamic requires
|
|
160
|
+
if (dynamicRequires.length > 0) {
|
|
161
|
+
findings.push({
|
|
162
|
+
severity: 'HIGH',
|
|
163
|
+
category: 'dynamic-require',
|
|
164
|
+
title: 'Dynamic require() detected',
|
|
165
|
+
file: filePath,
|
|
166
|
+
line: dynamicRequires[0],
|
|
167
|
+
detail: `Found ${dynamicRequires.length} dynamic require() call(s)`,
|
|
168
|
+
evidence: 'Dynamic imports can load arbitrary modules'
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
// Add findings for eval usage
|
|
172
|
+
if (evals.length > 0) {
|
|
173
|
+
findings.push({
|
|
174
|
+
severity: 'CRITICAL',
|
|
175
|
+
category: 'eval-usage',
|
|
176
|
+
title: 'eval() usage detected',
|
|
177
|
+
file: filePath,
|
|
178
|
+
line: evals[0],
|
|
179
|
+
detail: `Found ${evals.length} eval() call(s)`,
|
|
180
|
+
evidence: 'eval() can execute arbitrary code'
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
return findings;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Find line number for a match in text
|
|
187
|
+
*/
|
|
188
|
+
function findLineNumber(text, match) {
|
|
189
|
+
const index = text.indexOf(match);
|
|
190
|
+
if (index === -1)
|
|
191
|
+
return undefined;
|
|
192
|
+
const beforeMatch = text.substring(0, index);
|
|
193
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
194
|
+
return lineNumber;
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code.js","sourceRoot":"","sources":["../../src/layers/code.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer 4: Cross-Reference Analysis
|
|
3
|
+
* Compares findings across layers to detect permission mismatches and deception
|
|
4
|
+
*/
|
|
5
|
+
import type { Skill, Finding, LayerResult } from '../types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Cross-reference findings from previous layers
|
|
8
|
+
*/
|
|
9
|
+
export declare function scanCrossReference(skill: Skill, previousFindings: Finding[]): Promise<LayerResult>;
|
|
10
|
+
//# sourceMappingURL=crossref.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crossref.d.ts","sourceRoot":"","sources":["../../src/layers/crossref.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/D;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,KAAK,EACZ,gBAAgB,EAAE,OAAO,EAAE,GAC1B,OAAO,CAAC,WAAW,CAAC,CAwKtB"}
|