acidtest 0.5.2 → 0.7.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/.github/workflows/acidtest-example.yml +4 -4
- package/.github/workflows/acidtest-template.yml +1 -1
- package/README.md +70 -5
- package/dist/config.d.ts +19 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +69 -0
- package/dist/config.js.map +1 -0
- package/dist/config.test.d.ts +5 -0
- package/dist/config.test.d.ts.map +1 -0
- package/dist/config.test.js +69 -0
- package/dist/config.test.js.map +1 -0
- package/dist/index.js +45 -8
- package/dist/index.js.map +1 -1
- package/dist/layers/code.js +116 -6
- package/dist/layers/code.js.map +1 -1
- package/dist/layers/code.test.d.ts +5 -0
- package/dist/layers/code.test.d.ts.map +1 -0
- package/dist/layers/code.test.js +214 -0
- package/dist/layers/code.test.js.map +1 -0
- package/dist/layers/injection.d.ts.map +1 -1
- package/dist/layers/injection.js +2 -1
- package/dist/layers/injection.js.map +1 -1
- package/dist/layers/permissions.d.ts.map +1 -1
- package/dist/layers/permissions.js +2 -1
- package/dist/layers/permissions.js.map +1 -1
- package/dist/patterns/credential-patterns.json +10 -1
- package/dist/patterns/dangerous-imports.json +40 -4
- package/dist/remediation.test.d.ts +5 -0
- package/dist/remediation.test.d.ts.map +1 -0
- package/dist/remediation.test.js +74 -0
- package/dist/remediation.test.js.map +1 -0
- package/dist/reporter.d.ts +4 -1
- package/dist/reporter.d.ts.map +1 -1
- package/dist/reporter.js +83 -3
- package/dist/reporter.js.map +1 -1
- package/dist/scanner.d.ts +1 -1
- package/dist/scanner.d.ts.map +1 -1
- package/dist/scanner.js +31 -3
- package/dist/scanner.js.map +1 -1
- package/dist/scanner.test.d.ts +5 -0
- package/dist/scanner.test.d.ts.map +1 -0
- package/dist/scanner.test.js +77 -0
- package/dist/scanner.test.js.map +1 -0
- package/dist/scoring.test.d.ts +5 -0
- package/dist/scoring.test.d.ts.map +1 -0
- package/dist/scoring.test.js +301 -0
- package/dist/scoring.test.js.map +1 -0
- package/dist/types.d.ts +34 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/watch.d.ts +14 -0
- package/dist/watch.d.ts.map +1 -0
- package/dist/watch.js +135 -0
- package/dist/watch.js.map +1 -0
- package/dist/watch.test.d.ts +5 -0
- package/dist/watch.test.d.ts.map +1 -0
- package/dist/watch.test.js +53 -0
- package/dist/watch.test.js.map +1 -0
- package/package.json +13 -4
|
@@ -27,7 +27,7 @@ jobs:
|
|
|
27
27
|
if: hashFiles('src/scanner.ts') != ''
|
|
28
28
|
uses: actions/setup-node@v4
|
|
29
29
|
with:
|
|
30
|
-
node-version: '
|
|
30
|
+
node-version: '20'
|
|
31
31
|
|
|
32
32
|
- name: Run AcidTest
|
|
33
33
|
run: |
|
|
@@ -51,7 +51,7 @@ jobs:
|
|
|
51
51
|
if: hashFiles('src/scanner.ts') != ''
|
|
52
52
|
uses: actions/setup-node@v4
|
|
53
53
|
with:
|
|
54
|
-
node-version: '
|
|
54
|
+
node-version: '20'
|
|
55
55
|
|
|
56
56
|
- name: Run AcidTest
|
|
57
57
|
id: acidtest
|
|
@@ -112,7 +112,7 @@ jobs:
|
|
|
112
112
|
if: hashFiles('src/scanner.ts') != ''
|
|
113
113
|
uses: actions/setup-node@v4
|
|
114
114
|
with:
|
|
115
|
-
node-version: '
|
|
115
|
+
node-version: '20'
|
|
116
116
|
|
|
117
117
|
- name: Run AcidTest on all skills
|
|
118
118
|
run: |
|
|
@@ -163,7 +163,7 @@ jobs:
|
|
|
163
163
|
if: hashFiles('src/scanner.ts') != ''
|
|
164
164
|
uses: actions/setup-node@v4
|
|
165
165
|
with:
|
|
166
|
-
node-version: '
|
|
166
|
+
node-version: '20'
|
|
167
167
|
|
|
168
168
|
- name: Run AcidTest
|
|
169
169
|
id: scan
|
package/README.md
CHANGED
|
@@ -4,11 +4,21 @@ Security scanner for AI agent skills and MCP servers. Scan before you install.
|
|
|
4
4
|
|
|
5
5
|
## The Problem
|
|
6
6
|
|
|
7
|
-
The AI agent ecosystem is growing rapidly
|
|
8
|
-
|
|
9
|
-
- **
|
|
10
|
-
- **
|
|
11
|
-
- **
|
|
7
|
+
The AI agent ecosystem is growing rapidly, but security lags behind adoption:
|
|
8
|
+
|
|
9
|
+
- **No centralized vetting**: Unlike mobile app stores, there's no security review before skills are published
|
|
10
|
+
- **Broad permissions**: Skills can request file system access, environment variables, and network calls
|
|
11
|
+
- **Supply chain risks**: Dependencies and third-party code run with full skill permissions
|
|
12
|
+
- **Prompt injection**: Malicious skills can manipulate AI behavior through carefully crafted prompts
|
|
13
|
+
- **Credential harvesting**: Skills requesting API keys and tokens without proper justification
|
|
14
|
+
|
|
15
|
+
Recent ecosystem incidents highlight these risks:
|
|
16
|
+
- Mass uploads of malicious skills to public marketplaces
|
|
17
|
+
- Skills with undeclared network calls exfiltrating data
|
|
18
|
+
- Obfuscated code hiding malicious behavior
|
|
19
|
+
- Permission escalation through dynamic imports
|
|
20
|
+
|
|
21
|
+
**AcidTest provides security scanning before installation**, helping you identify risks before they reach your system.
|
|
12
22
|
|
|
13
23
|
## Quick Start
|
|
14
24
|
```bash
|
|
@@ -114,6 +124,16 @@ acidtest scan ./server/mcp.json # Direct manifest path
|
|
|
114
124
|
# Scan all skills/servers in a directory
|
|
115
125
|
acidtest scan-all ./directory
|
|
116
126
|
|
|
127
|
+
# Watch mode - re-scan on file changes
|
|
128
|
+
acidtest scan ./my-skill --watch
|
|
129
|
+
acidtest scan ./my-skill -w # Short form
|
|
130
|
+
|
|
131
|
+
# Show remediation suggestions
|
|
132
|
+
acidtest scan ./my-skill --fix
|
|
133
|
+
|
|
134
|
+
# Combine flags
|
|
135
|
+
acidtest scan ./my-skill --watch --fix
|
|
136
|
+
|
|
117
137
|
# JSON output for programmatic use
|
|
118
138
|
acidtest scan ./my-skill --json
|
|
119
139
|
|
|
@@ -121,6 +141,51 @@ acidtest scan ./my-skill --json
|
|
|
121
141
|
acidtest serve
|
|
122
142
|
```
|
|
123
143
|
|
|
144
|
+
### CLI Options
|
|
145
|
+
|
|
146
|
+
- `--watch`, `-w` - Watch for file changes and automatically re-scan
|
|
147
|
+
- Keyboard controls: `q` to quit, `r` to force re-scan, `c` to clear terminal
|
|
148
|
+
- Use `--no-clear` to preserve terminal history between scans
|
|
149
|
+
- `--fix` - Show actionable remediation suggestions for each finding
|
|
150
|
+
- `--json` - Output results as JSON for programmatic use
|
|
151
|
+
- `--no-clear` - Don't clear terminal between scans (watch mode only)
|
|
152
|
+
|
|
153
|
+
### Configuration File
|
|
154
|
+
|
|
155
|
+
Create a `.acidtest.json` file in your skill directory to customize scanning behavior:
|
|
156
|
+
|
|
157
|
+
```json
|
|
158
|
+
{
|
|
159
|
+
"ignore": {
|
|
160
|
+
"patterns": ["di-008"],
|
|
161
|
+
"categories": ["obfuscation"],
|
|
162
|
+
"files": ["vendor/**", "*.min.js"]
|
|
163
|
+
},
|
|
164
|
+
"thresholds": {
|
|
165
|
+
"minScore": 80,
|
|
166
|
+
"failOn": ["CRITICAL", "HIGH"]
|
|
167
|
+
},
|
|
168
|
+
"output": {
|
|
169
|
+
"format": "detailed",
|
|
170
|
+
"showRemediation": true,
|
|
171
|
+
"colors": true
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**Configuration Options:**
|
|
177
|
+
|
|
178
|
+
- `ignore.patterns` - Array of pattern IDs to suppress (e.g., `["di-001", "cp-006"]`)
|
|
179
|
+
- `ignore.categories` - Array of categories to suppress (e.g., `["obfuscation"]`)
|
|
180
|
+
- `ignore.files` - Array of glob patterns for files to skip scanning
|
|
181
|
+
- `thresholds.minScore` - Minimum passing score (0-100). Exit with error if score is below this
|
|
182
|
+
- `thresholds.failOn` - Array of severities that cause scan to fail (e.g., `["CRITICAL", "HIGH"]`)
|
|
183
|
+
- `output.format` - Output format: `"detailed"`, `"compact"`, or `"json"`
|
|
184
|
+
- `output.showRemediation` - Show remediation suggestions (boolean)
|
|
185
|
+
- `output.colors` - Enable/disable colored output (boolean)
|
|
186
|
+
|
|
187
|
+
CLI flags override config file settings.
|
|
188
|
+
|
|
124
189
|
### Use as MCP Server
|
|
125
190
|
|
|
126
191
|
AcidTest can run as an MCP (Model Context Protocol) server, allowing AI agents like Claude to scan skills and MCP servers before installation.
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration file loader
|
|
3
|
+
* Loads and validates .acidtest.json config files
|
|
4
|
+
*/
|
|
5
|
+
import type { AcidTestConfig } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Load AcidTest configuration from directory
|
|
8
|
+
* Looks for .acidtest.json in the skill directory
|
|
9
|
+
*/
|
|
10
|
+
export declare function loadConfig(directory: string): AcidTestConfig;
|
|
11
|
+
/**
|
|
12
|
+
* Get default configuration
|
|
13
|
+
*/
|
|
14
|
+
export declare function getDefaultConfig(): AcidTestConfig;
|
|
15
|
+
/**
|
|
16
|
+
* Merge user config with defaults
|
|
17
|
+
*/
|
|
18
|
+
export declare function mergeConfig(userConfig: AcidTestConfig): AcidTestConfig;
|
|
19
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,CAe5D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,cAAc,CAiBjD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,cAAc,GAAG,cAAc,CAmBtE"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration file loader
|
|
3
|
+
* Loads and validates .acidtest.json config files
|
|
4
|
+
*/
|
|
5
|
+
import { readFileSync, existsSync } from 'fs';
|
|
6
|
+
import { join } from 'path';
|
|
7
|
+
/**
|
|
8
|
+
* Load AcidTest configuration from directory
|
|
9
|
+
* Looks for .acidtest.json in the skill directory
|
|
10
|
+
*/
|
|
11
|
+
export function loadConfig(directory) {
|
|
12
|
+
const configPath = join(directory, '.acidtest.json');
|
|
13
|
+
if (!existsSync(configPath)) {
|
|
14
|
+
return {}; // No config, use defaults
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
const content = readFileSync(configPath, 'utf-8');
|
|
18
|
+
const config = JSON.parse(content);
|
|
19
|
+
return config;
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
console.warn(`Warning: Invalid .acidtest.json: ${error.message}`);
|
|
23
|
+
return {};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get default configuration
|
|
28
|
+
*/
|
|
29
|
+
export function getDefaultConfig() {
|
|
30
|
+
return {
|
|
31
|
+
ignore: {
|
|
32
|
+
patterns: [],
|
|
33
|
+
categories: [],
|
|
34
|
+
files: []
|
|
35
|
+
},
|
|
36
|
+
thresholds: {
|
|
37
|
+
minScore: 0,
|
|
38
|
+
failOn: []
|
|
39
|
+
},
|
|
40
|
+
output: {
|
|
41
|
+
format: 'detailed',
|
|
42
|
+
showRemediation: false,
|
|
43
|
+
colors: true
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Merge user config with defaults
|
|
49
|
+
*/
|
|
50
|
+
export function mergeConfig(userConfig) {
|
|
51
|
+
const defaults = getDefaultConfig();
|
|
52
|
+
return {
|
|
53
|
+
ignore: {
|
|
54
|
+
patterns: userConfig.ignore?.patterns ?? defaults.ignore.patterns,
|
|
55
|
+
categories: userConfig.ignore?.categories ?? defaults.ignore.categories,
|
|
56
|
+
files: userConfig.ignore?.files ?? defaults.ignore.files
|
|
57
|
+
},
|
|
58
|
+
thresholds: {
|
|
59
|
+
minScore: userConfig.thresholds?.minScore ?? defaults.thresholds.minScore,
|
|
60
|
+
failOn: userConfig.thresholds?.failOn ?? defaults.thresholds.failOn
|
|
61
|
+
},
|
|
62
|
+
output: {
|
|
63
|
+
format: userConfig.output?.format ?? defaults.output.format,
|
|
64
|
+
showRemediation: userConfig.output?.showRemediation ?? defaults.output.showRemediation,
|
|
65
|
+
colors: userConfig.output?.colors ?? defaults.output.colors
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,SAAiB;IAC1C,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAErD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,CAAC,CAAC,0BAA0B;IACvC,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAClD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAmB,CAAC;QACrD,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,oCAAqC,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7E,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO;QACL,MAAM,EAAE;YACN,QAAQ,EAAE,EAAE;YACZ,UAAU,EAAE,EAAE;YACd,KAAK,EAAE,EAAE;SACV;QACD,UAAU,EAAE;YACV,QAAQ,EAAE,CAAC;YACX,MAAM,EAAE,EAAE;SACX;QACD,MAAM,EAAE;YACN,MAAM,EAAE,UAAU;YAClB,eAAe,EAAE,KAAK;YACtB,MAAM,EAAE,IAAI;SACb;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,UAA0B;IACpD,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAC;IAEpC,OAAO;QACL,MAAM,EAAE;YACN,QAAQ,EAAE,UAAU,CAAC,MAAM,EAAE,QAAQ,IAAI,QAAQ,CAAC,MAAO,CAAC,QAAQ;YAClE,UAAU,EAAE,UAAU,CAAC,MAAM,EAAE,UAAU,IAAI,QAAQ,CAAC,MAAO,CAAC,UAAU;YACxE,KAAK,EAAE,UAAU,CAAC,MAAM,EAAE,KAAK,IAAI,QAAQ,CAAC,MAAO,CAAC,KAAK;SAC1D;QACD,UAAU,EAAE;YACV,QAAQ,EAAE,UAAU,CAAC,UAAU,EAAE,QAAQ,IAAI,QAAQ,CAAC,UAAW,CAAC,QAAQ;YAC1E,MAAM,EAAE,UAAU,CAAC,UAAU,EAAE,MAAM,IAAI,QAAQ,CAAC,UAAW,CAAC,MAAM;SACrE;QACD,MAAM,EAAE;YACN,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,MAAM,IAAI,QAAQ,CAAC,MAAO,CAAC,MAAM;YAC5D,eAAe,EAAE,UAAU,CAAC,MAAM,EAAE,eAAe,IAAI,QAAQ,CAAC,MAAO,CAAC,eAAe;YACvF,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,MAAM,IAAI,QAAQ,CAAC,MAAO,CAAC,MAAM;SAC7D;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.test.d.ts","sourceRoot":"","sources":["../src/config.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for config loading
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
5
|
+
import { mkdirSync, writeFileSync, rmSync } from 'fs';
|
|
6
|
+
import { join } from 'path';
|
|
7
|
+
import { loadConfig, mergeConfig, getDefaultConfig } from './config.js';
|
|
8
|
+
describe('Config Loading', () => {
|
|
9
|
+
const testDir = join(process.cwd(), 'test-config-temp');
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
mkdirSync(testDir, { recursive: true });
|
|
12
|
+
});
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
rmSync(testDir, { recursive: true, force: true });
|
|
15
|
+
});
|
|
16
|
+
it('should return empty config when .acidtest.json does not exist', () => {
|
|
17
|
+
const config = loadConfig(testDir);
|
|
18
|
+
expect(config).toEqual({});
|
|
19
|
+
});
|
|
20
|
+
it('should load valid .acidtest.json config', () => {
|
|
21
|
+
const configData = {
|
|
22
|
+
ignore: {
|
|
23
|
+
patterns: ['di-001', 'di-002'],
|
|
24
|
+
categories: ['obfuscation']
|
|
25
|
+
},
|
|
26
|
+
thresholds: {
|
|
27
|
+
minScore: 80,
|
|
28
|
+
failOn: ['CRITICAL', 'HIGH']
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
writeFileSync(join(testDir, '.acidtest.json'), JSON.stringify(configData, null, 2));
|
|
32
|
+
const config = loadConfig(testDir);
|
|
33
|
+
expect(config).toEqual(configData);
|
|
34
|
+
});
|
|
35
|
+
it('should return empty config on invalid JSON', () => {
|
|
36
|
+
writeFileSync(join(testDir, '.acidtest.json'), 'invalid json {');
|
|
37
|
+
const config = loadConfig(testDir);
|
|
38
|
+
expect(config).toEqual({});
|
|
39
|
+
});
|
|
40
|
+
it('should merge user config with defaults', () => {
|
|
41
|
+
const userConfig = {
|
|
42
|
+
ignore: {
|
|
43
|
+
patterns: ['di-001']
|
|
44
|
+
},
|
|
45
|
+
thresholds: {
|
|
46
|
+
minScore: 90
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
const merged = mergeConfig(userConfig);
|
|
50
|
+
const defaults = getDefaultConfig();
|
|
51
|
+
expect(merged.ignore?.patterns).toEqual(['di-001']);
|
|
52
|
+
expect(merged.ignore?.categories).toEqual(defaults.ignore.categories);
|
|
53
|
+
expect(merged.thresholds?.minScore).toBe(90);
|
|
54
|
+
expect(merged.thresholds?.failOn).toEqual(defaults.thresholds.failOn);
|
|
55
|
+
expect(merged.output?.format).toBe(defaults.output.format);
|
|
56
|
+
});
|
|
57
|
+
it('should handle partial config', () => {
|
|
58
|
+
const userConfig = {
|
|
59
|
+
thresholds: {
|
|
60
|
+
failOn: ['CRITICAL']
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
const merged = mergeConfig(userConfig);
|
|
64
|
+
const defaults = getDefaultConfig();
|
|
65
|
+
expect(merged.ignore?.patterns).toEqual(defaults.ignore.patterns);
|
|
66
|
+
expect(merged.thresholds?.failOn).toEqual(['CRITICAL']);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
//# sourceMappingURL=config.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.test.js","sourceRoot":"","sources":["../src/config.test.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -5,10 +5,11 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { scanSkill, scanAllSkills } from "./scanner.js";
|
|
7
7
|
import { reportToTerminal, reportAsJSON } from "./reporter.js";
|
|
8
|
+
import { loadConfig, mergeConfig } from "./config.js";
|
|
8
9
|
import { join, dirname } from "path";
|
|
9
10
|
import { fileURLToPath } from "url";
|
|
10
11
|
import { spawn } from "child_process";
|
|
11
|
-
const VERSION = "0.
|
|
12
|
+
const VERSION = "0.7.0";
|
|
12
13
|
/**
|
|
13
14
|
* Main CLI function
|
|
14
15
|
*/
|
|
@@ -50,23 +51,50 @@ async function main() {
|
|
|
50
51
|
async function handleScan(args) {
|
|
51
52
|
// Parse flags
|
|
52
53
|
const jsonOutput = args.includes("--json");
|
|
53
|
-
const
|
|
54
|
+
const watchMode = args.includes("--watch") || args.includes("-w");
|
|
55
|
+
const noClear = args.includes("--no-clear");
|
|
56
|
+
const showFix = args.includes("--fix");
|
|
57
|
+
const paths = args.filter((arg) => !arg.startsWith("--") && arg !== "-w");
|
|
54
58
|
if (paths.length === 0) {
|
|
55
59
|
console.error("Error: No skill path provided");
|
|
56
|
-
console.error("Usage: acidtest scan <path-to-skill> [--json]");
|
|
60
|
+
console.error("Usage: acidtest scan <path-to-skill> [--json] [--watch]");
|
|
57
61
|
process.exit(1);
|
|
58
62
|
}
|
|
59
63
|
const skillPath = paths[0];
|
|
64
|
+
// Handle watch mode
|
|
65
|
+
if (watchMode) {
|
|
66
|
+
const { watchMode: startWatchMode } = await import('./watch.js');
|
|
67
|
+
await startWatchMode(skillPath, { noClear, jsonOutput, showRemediation: showFix });
|
|
68
|
+
return; // Watch mode handles its own exit
|
|
69
|
+
}
|
|
60
70
|
try {
|
|
61
|
-
|
|
71
|
+
// Load config from skill directory
|
|
72
|
+
const userConfig = loadConfig(skillPath);
|
|
73
|
+
const config = mergeConfig(userConfig);
|
|
74
|
+
// Show progress spinner for CLI scans (not for JSON output)
|
|
75
|
+
const result = await scanSkill(skillPath, !jsonOutput);
|
|
62
76
|
if (jsonOutput) {
|
|
63
77
|
reportAsJSON(result);
|
|
64
78
|
}
|
|
65
79
|
else {
|
|
66
|
-
|
|
80
|
+
// CLI flags override config
|
|
81
|
+
const showRemediation = showFix || (config.output?.showRemediation ?? false);
|
|
82
|
+
reportToTerminal(result, { showRemediation });
|
|
83
|
+
}
|
|
84
|
+
// Apply threshold checks from config
|
|
85
|
+
let shouldFail = result.status === "FAIL" || result.status === "DANGER";
|
|
86
|
+
// Check minScore threshold
|
|
87
|
+
if (config.thresholds?.minScore && result.score < config.thresholds.minScore) {
|
|
88
|
+
shouldFail = true;
|
|
67
89
|
}
|
|
68
|
-
//
|
|
69
|
-
if (
|
|
90
|
+
// Check failOn severity threshold
|
|
91
|
+
if (config.thresholds?.failOn && config.thresholds.failOn.length > 0) {
|
|
92
|
+
const hasFailSeverity = result.findings.some(f => config.thresholds.failOn.includes(f.severity));
|
|
93
|
+
if (hasFailSeverity) {
|
|
94
|
+
shouldFail = true;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (shouldFail) {
|
|
70
98
|
process.exit(1);
|
|
71
99
|
}
|
|
72
100
|
}
|
|
@@ -259,7 +287,7 @@ AcidTest v${VERSION}
|
|
|
259
287
|
Security scanner for AI agent skills and MCP servers
|
|
260
288
|
|
|
261
289
|
USAGE:
|
|
262
|
-
acidtest scan <path> [--json]
|
|
290
|
+
acidtest scan <path> [--json] [--watch] [--fix] [--no-clear]
|
|
263
291
|
acidtest scan-all <directory> [--json]
|
|
264
292
|
acidtest demo
|
|
265
293
|
acidtest serve
|
|
@@ -274,6 +302,9 @@ COMMANDS:
|
|
|
274
302
|
|
|
275
303
|
OPTIONS:
|
|
276
304
|
--json Output results as JSON
|
|
305
|
+
--watch, -w Watch for file changes and re-scan automatically
|
|
306
|
+
--fix Show actionable remediation suggestions for findings
|
|
307
|
+
--no-clear Don't clear terminal between scans (watch mode only)
|
|
277
308
|
--version Print version number
|
|
278
309
|
--help Show this help message
|
|
279
310
|
|
|
@@ -290,6 +321,12 @@ EXAMPLES:
|
|
|
290
321
|
# Scan with JSON output
|
|
291
322
|
acidtest scan ./my-skill --json
|
|
292
323
|
|
|
324
|
+
# Show remediation suggestions for findings
|
|
325
|
+
acidtest scan ./my-skill --fix
|
|
326
|
+
|
|
327
|
+
# Watch for changes and re-scan automatically
|
|
328
|
+
acidtest scan ./my-skill --watch
|
|
329
|
+
|
|
293
330
|
# Scan all skills/servers in a directory
|
|
294
331
|
acidtest scan-all ./directory
|
|
295
332
|
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE/D,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAEtC,MAAM,OAAO,GAAG,OAAO,CAAC;AAExB;;GAEG;AACH,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEnC,wBAAwB;IACxB,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACtD,OAAO,CAAC,GAAG,CAAC,aAAa,OAAO,EAAE,CAAC,CAAC;QACpC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,qBAAqB;IACrB,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxE,SAAS,EAAE,CAAC;QACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,gBAAgB;IAChB,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAExB,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACvB,MAAM,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC;SAAM,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;QAClC,MAAM,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC;SAAM,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QAC9B,MAAM,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC;SAAM,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;QAC/B,MAAM,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACnC,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;QAC7C,OAAO,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,UAAU,CAAC,IAAc;IACtC,cAAc;IACd,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IAE1D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;QAC/C,OAAO,CAAC,KAAK,CAAC,+CAA+C,CAAC,CAAC;QAC/D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAE3B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,SAAS,CAAC,CAAC;QAE1C,IAAI,UAAU,EAAE,CAAC;YACf,YAAY,CAAC,MAAM,CAAC,CAAC;QACvB,CAAC;aAAM,CAAC;YACN,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAC3B,CAAC;QAED,6CAA6C;QAC7C,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC3D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,UAAU,EAAE,CAAC;YACf,4CAA4C;YAC5C,MAAM,WAAW,GAAgB;gBAC/B,aAAa,EAAE,OAAO;gBACtB,IAAI,EAAE,UAAU;gBAChB,OAAO,EAAE,OAAO;gBAChB,MAAM,EAAE,OAAO;gBACf,KAAK,EAAG,KAAe,CAAC,OAAO;aAChC,CAAC;YACF,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACpD,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,uBAAuB,EAAG,KAAe,CAAC,OAAO,CAAC,CAAC;QACnE,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,aAAa,CAAC,IAAc;IACzC,cAAc;IACd,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IAE1D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACnD,OAAO,CAAC,KAAK,CAAC,+CAA+C,CAAC,CAAC;QAC/D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAE3B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,SAAS,CAAC,CAAC;QAE/C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;YAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,UAAU,EAAE,CAAC;YACf,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAChD,CAAC;aAAM,CAAC;YACN,+BAA+B;YAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACxC,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;gBAC1B,gBAAgB,CAAC,MAAM,CAAC,CAAC;gBAEzB,qDAAqD;gBACrD,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC3B,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;gBAC5C,CAAC;YACH,CAAC;YAED,2BAA2B;YAC3B,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;YACnC,OAAO,CAAC,GAAG,CAAC,aAAa,OAAO,CAAC,MAAM,cAAc,CAAC,CAAC;YAEvD,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,MAAM,CAAC;YAC/D,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,MAAM,CAAC;YAC/D,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,MAAM,CAAC;YAC/D,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,MAAM,CAAC;YAEnE,IAAI,IAAI,GAAG,CAAC;gBAAE,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC;YAC/C,IAAI,IAAI,GAAG,CAAC;gBAAE,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC;YAC/C,IAAI,IAAI,GAAG,CAAC;gBAAE,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC;YAC/C,IAAI,MAAM,GAAG,CAAC;gBAAE,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,EAAE,CAAC,CAAC;YAEnD,OAAO,CAAC,GAAG,EAAE,CAAC;QAChB,CAAC;QAED,yCAAyC;QACzC,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAC9B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC,MAAM,KAAK,QAAQ,CACpD,CAAC;QAEF,IAAI,WAAW,EAAE,CAAC;YAChB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,UAAU,EAAE,CAAC;YACf,4CAA4C;YAC5C,MAAM,WAAW,GAAgB;gBAC/B,aAAa,EAAE,OAAO;gBACtB,IAAI,EAAE,UAAU;gBAChB,OAAO,EAAE,OAAO;gBAChB,MAAM,EAAE,OAAO;gBACf,KAAK,EAAG,KAAe,CAAC,OAAO;aAChC,CAAC;YACF,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACpD,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAG,KAAe,CAAC,OAAO,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,UAAU,CAAC,IAAc;IACtC,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;IAEnE,gDAAgD;IAChD,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACtC,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,eAAe,CAAC,CAAC;IAE3D,MAAM,QAAQ,GAAG;QACf,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,EAAE;QACzD,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,EAAE;QACzD,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,EAAE;QACzD,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,gBAAgB,CAAC,EAAE;KAC9D,CAAC;IAEF,MAAM,OAAO,GAAG,EAAE,CAAC;IAEnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QAE5B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC7C,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;YAEhD,OAAO,CAAC,GAAG,CAAC,IAAK,OAAO,CAAC,IAAK,WAAW,CAAC,CAAC;YAC3C,gBAAgB,CAAC,MAAM,CAAC,CAAC;YAEzB,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC5B,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CACV,2BAA2B,OAAO,CAAC,IAAI,WAAW,EACjD,KAAe,CAAC,OAAO,CACzB,CAAC;QACJ,CAAC;IACH,CAAC;IAED,gBAAgB;IAChB,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IACnC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAC/B,OAAO,CAAC,GAAG,CACT,wEAAwE,CACzE,CAAC;IAEF,KAAK,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;QAC1C,MAAM,WAAW,GACf,MAAM,CAAC,MAAM,KAAK,MAAM;YACtB,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,MAAM;gBACxB,CAAC,CAAC,QAAQ;gBACV,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,MAAM;oBACxB,CAAC,CAAC,KAAK;oBACP,CAAC,CAAC,KAAK,CAAC;QAEhB,OAAO,CAAC,GAAG,CACT,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,KAAK,WAAW,oBAAoB,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAC9F,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,GAAG,CACT,iEAAiE,CAClE,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;AACrE,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAAC,MAAc;IAC1C,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,MAAM;YACT,OAAO,+CAA+C,CAAC;QACzD,KAAK,MAAM;YACT,OAAO,4CAA4C,CAAC;QACtD,KAAK,MAAM;YACT,OAAO,8CAA8C,CAAC;QACxD,KAAK,QAAQ;YACX,OAAO,+CAA+C,CAAC;QACzD;YACE,OAAO,gBAAgB,CAAC;IAC5B,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,WAAW,CAAC,IAAc;IACvC,oDAAoD;IACpD,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACtC,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;IAEvD,0CAA0C;IAC1C,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,aAAa,CAAC,EAAE;QAC/C,KAAK,EAAE,SAAS,EAAE,+CAA+C;KAClE,CAAC,CAAC;IAEH,6BAA6B;IAC7B,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QAC5B,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,gBAAgB;IAChB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;QAC9B,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QAC5D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,SAAS,SAAS;IAChB,OAAO,CAAC,GAAG,CAAC;YACF,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0ClB,CAAC,CAAC;AACH,CAAC;AAED,UAAU;AACV,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAC;IAC1C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/layers/code.js
CHANGED
|
@@ -65,7 +65,8 @@ function scanCodeWithRegex(codeFile, patterns) {
|
|
|
65
65
|
line: lineNumber,
|
|
66
66
|
detail: pattern.description || `Pattern match: ${pattern.name}`,
|
|
67
67
|
evidence: `Found ${matches.length} occurrence(s)`,
|
|
68
|
-
patternId: pattern.id
|
|
68
|
+
patternId: pattern.id,
|
|
69
|
+
...(pattern.remediation && { remediation: pattern.remediation })
|
|
69
70
|
});
|
|
70
71
|
}
|
|
71
72
|
}
|
|
@@ -137,6 +138,9 @@ function detectSuspiciousPatterns(sourceFile, filePath) {
|
|
|
137
138
|
const findings = [];
|
|
138
139
|
const dynamicRequires = [];
|
|
139
140
|
const evals = [];
|
|
141
|
+
const functionConstructors = [];
|
|
142
|
+
const propertyAccessBypasses = [];
|
|
143
|
+
const stringConcatenations = [];
|
|
140
144
|
function visit(node) {
|
|
141
145
|
// Check for eval() calls
|
|
142
146
|
if (ts.isCallExpression(node)) {
|
|
@@ -145,14 +149,42 @@ function detectSuspiciousPatterns(sourceFile, filePath) {
|
|
|
145
149
|
const lineNumber = sourceFile.getLineAndCharacterOfPosition(node.getStart()).line + 1;
|
|
146
150
|
evals.push(lineNumber);
|
|
147
151
|
}
|
|
148
|
-
// Check for require() with non-literal arguments
|
|
152
|
+
// Check for require() with non-literal arguments (catches dynamic require, template literals, variables)
|
|
149
153
|
if (ts.isIdentifier(expression) && expression.text === 'require') {
|
|
150
154
|
if (node.arguments.length > 0) {
|
|
151
155
|
const arg = node.arguments[0];
|
|
156
|
+
// Catches: require(variable), require(obj.prop), require(`template${expr}`)
|
|
152
157
|
if (!ts.isStringLiteral(arg) && !ts.isNoSubstitutionTemplateLiteral(arg)) {
|
|
153
158
|
const lineNumber = sourceFile.getLineAndCharacterOfPosition(node.getStart()).line + 1;
|
|
154
159
|
dynamicRequires.push(lineNumber);
|
|
155
160
|
}
|
|
161
|
+
// Check for string concatenation: require('child_' + 'process')
|
|
162
|
+
if (ts.isBinaryExpression(arg) && arg.operatorToken.kind === ts.SyntaxKind.PlusToken) {
|
|
163
|
+
const lineNumber = sourceFile.getLineAndCharacterOfPosition(node.getStart()).line + 1;
|
|
164
|
+
stringConcatenations.push(lineNumber);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// Check for Function constructor: new Function(...)
|
|
170
|
+
if (ts.isNewExpression(node)) {
|
|
171
|
+
const expression = node.expression;
|
|
172
|
+
if (ts.isIdentifier(expression) && expression.text === 'Function') {
|
|
173
|
+
const lineNumber = sourceFile.getLineAndCharacterOfPosition(node.getStart()).line + 1;
|
|
174
|
+
functionConstructors.push(lineNumber);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// Check for bracket notation property access on sensitive objects
|
|
178
|
+
// Catches: global['child_process'], process['env'], require['cache']
|
|
179
|
+
if (ts.isElementAccessExpression(node)) {
|
|
180
|
+
const expression = node.expression;
|
|
181
|
+
if (ts.isIdentifier(expression)) {
|
|
182
|
+
const objName = expression.text;
|
|
183
|
+
// Check if accessing sensitive global objects
|
|
184
|
+
const sensitiveObjects = ['global', 'process', 'require', 'module', 'exports'];
|
|
185
|
+
if (sensitiveObjects.includes(objName)) {
|
|
186
|
+
const lineNumber = sourceFile.getLineAndCharacterOfPosition(node.getStart()).line + 1;
|
|
187
|
+
propertyAccessBypasses.push(lineNumber);
|
|
156
188
|
}
|
|
157
189
|
}
|
|
158
190
|
}
|
|
@@ -168,7 +200,8 @@ function detectSuspiciousPatterns(sourceFile, filePath) {
|
|
|
168
200
|
file: filePath,
|
|
169
201
|
line: dynamicRequires[0],
|
|
170
202
|
detail: `Found ${dynamicRequires.length} dynamic require() call(s)`,
|
|
171
|
-
evidence: 'Dynamic imports can load arbitrary modules'
|
|
203
|
+
evidence: 'Dynamic imports can load arbitrary modules',
|
|
204
|
+
patternId: 'ast-dynamic-require'
|
|
172
205
|
});
|
|
173
206
|
}
|
|
174
207
|
// Add findings for eval usage
|
|
@@ -180,7 +213,47 @@ function detectSuspiciousPatterns(sourceFile, filePath) {
|
|
|
180
213
|
file: filePath,
|
|
181
214
|
line: evals[0],
|
|
182
215
|
detail: `Found ${evals.length} eval() call(s)`,
|
|
183
|
-
evidence: 'eval() can execute arbitrary code'
|
|
216
|
+
evidence: 'eval() can execute arbitrary code',
|
|
217
|
+
patternId: 'ast-eval'
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
// Add findings for Function constructor
|
|
221
|
+
if (functionConstructors.length > 0) {
|
|
222
|
+
findings.push({
|
|
223
|
+
severity: 'CRITICAL',
|
|
224
|
+
category: 'function-constructor',
|
|
225
|
+
title: 'Function constructor detected',
|
|
226
|
+
file: filePath,
|
|
227
|
+
line: functionConstructors[0],
|
|
228
|
+
detail: `Found ${functionConstructors.length} Function constructor call(s)`,
|
|
229
|
+
evidence: 'Function constructor can execute arbitrary code like eval()',
|
|
230
|
+
patternId: 'ast-function-constructor'
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
// Add findings for property access bypasses
|
|
234
|
+
if (propertyAccessBypasses.length > 0) {
|
|
235
|
+
findings.push({
|
|
236
|
+
severity: 'MEDIUM',
|
|
237
|
+
category: 'property-access-bypass',
|
|
238
|
+
title: 'Bracket notation on sensitive objects',
|
|
239
|
+
file: filePath,
|
|
240
|
+
line: propertyAccessBypasses[0],
|
|
241
|
+
detail: `Found ${propertyAccessBypasses.length} bracket notation access(es) on sensitive objects`,
|
|
242
|
+
evidence: 'Bracket notation can bypass static analysis: global["child_process"]',
|
|
243
|
+
patternId: 'ast-bracket-access'
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
// Add findings for string concatenation in require
|
|
247
|
+
if (stringConcatenations.length > 0) {
|
|
248
|
+
findings.push({
|
|
249
|
+
severity: 'HIGH',
|
|
250
|
+
category: 'string-concatenation',
|
|
251
|
+
title: 'String concatenation in require()',
|
|
252
|
+
file: filePath,
|
|
253
|
+
line: stringConcatenations[0],
|
|
254
|
+
detail: `Found ${stringConcatenations.length} concatenated string(s) in require()`,
|
|
255
|
+
evidence: 'String concatenation can hide malicious imports: require("child_" + "process")',
|
|
256
|
+
patternId: 'ast-string-concat'
|
|
184
257
|
});
|
|
185
258
|
}
|
|
186
259
|
return findings;
|
|
@@ -206,6 +279,38 @@ function calculateEntropy(str) {
|
|
|
206
279
|
}
|
|
207
280
|
return entropy;
|
|
208
281
|
}
|
|
282
|
+
/**
|
|
283
|
+
* Check if string matches common legitimate high-entropy patterns
|
|
284
|
+
*/
|
|
285
|
+
function isLegitimateHighEntropyString(text) {
|
|
286
|
+
// JWT tokens (header.payload.signature format, starts with eyJ)
|
|
287
|
+
if (/^eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(text)) {
|
|
288
|
+
return true;
|
|
289
|
+
}
|
|
290
|
+
// UUID/GUID (8-4-4-4-12 format)
|
|
291
|
+
if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(text)) {
|
|
292
|
+
return true;
|
|
293
|
+
}
|
|
294
|
+
// Hex hashes (SHA256: 64 chars, SHA1: 40 chars, MD5: 32 chars)
|
|
295
|
+
if (/^[0-9a-f]{32}$|^[0-9a-f]{40}$|^[0-9a-f]{64}$/i.test(text)) {
|
|
296
|
+
return true;
|
|
297
|
+
}
|
|
298
|
+
// Base64 strings (common in configs, keys)
|
|
299
|
+
// Must have padding OR be very long (>100 chars suggests real encoded data)
|
|
300
|
+
// Short base64-looking strings without padding are suspicious
|
|
301
|
+
if (/^[A-Za-z0-9+/]+=+$/.test(text) && text.length % 4 === 0) {
|
|
302
|
+
return true; // Has proper padding
|
|
303
|
+
}
|
|
304
|
+
if (/^[A-Za-z0-9+/]+$/.test(text) && text.length > 100) {
|
|
305
|
+
return true; // Very long, likely real encoded data
|
|
306
|
+
}
|
|
307
|
+
// API keys with common prefixes (Stripe, GitHub, etc.)
|
|
308
|
+
if (/^(sk_|pk_|gh[ps]_|AKIA|ya29\.|glpat-|xox[abp]-)[A-Za-z0-9_-]+$/i.test(text)) {
|
|
309
|
+
// These ARE suspicious, so return false to flag them
|
|
310
|
+
return false;
|
|
311
|
+
}
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
209
314
|
/**
|
|
210
315
|
* Detect high-entropy strings that may indicate obfuscation
|
|
211
316
|
*/
|
|
@@ -218,16 +323,21 @@ function detectHighEntropyStrings(sourceFile, filePath) {
|
|
|
218
323
|
// Check string literals and template literals
|
|
219
324
|
if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) {
|
|
220
325
|
const text = node.text;
|
|
221
|
-
// Skip short strings
|
|
326
|
+
// Skip short strings
|
|
222
327
|
if (text.length < MIN_LENGTH) {
|
|
223
328
|
ts.forEachChild(node, visit);
|
|
224
329
|
return;
|
|
225
330
|
}
|
|
226
|
-
// Skip URLs
|
|
331
|
+
// Skip URLs (already detected elsewhere)
|
|
227
332
|
if (/^https?:\/\//.test(text)) {
|
|
228
333
|
ts.forEachChild(node, visit);
|
|
229
334
|
return;
|
|
230
335
|
}
|
|
336
|
+
// Skip legitimate high-entropy strings (JWTs, UUIDs, hashes)
|
|
337
|
+
if (isLegitimateHighEntropyString(text)) {
|
|
338
|
+
ts.forEachChild(node, visit);
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
231
341
|
const entropy = calculateEntropy(text);
|
|
232
342
|
if (entropy > ENTROPY_THRESHOLD) {
|
|
233
343
|
const lineNumber = sourceFile.getLineAndCharacterOfPosition(node.getStart()).line + 1;
|