circle-ir-ai 1.3.1 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +117 -12
- package/README.md +125 -247
- package/dist/agents/mastra/agents.d.ts +12 -12
- package/dist/agents/mastra/instance.d.ts +12 -12
- package/dist/cli/args.d.ts +1 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +11 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/index.js +17 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/dead-code/detector.d.ts.map +1 -1
- package/dist/dead-code/detector.js +1 -0
- package/dist/dead-code/detector.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/llm/language-context.d.ts.map +1 -1
- package/dist/llm/language-context.js +1 -0
- package/dist/llm/language-context.js.map +1 -1
- package/dist/project/analyzer.js +1 -1
- package/dist/project/analyzer.js.map +1 -1
- package/dist/project/two-phase-analyzer.js +1 -1
- package/dist/project/two-phase-analyzer.js.map +1 -1
- package/dist/security-scan/scanner.d.ts.map +1 -1
- package/dist/security-scan/scanner.js +1 -0
- package/dist/security-scan/scanner.js.map +1 -1
- package/package.json +13 -13
package/LICENSE
CHANGED
|
@@ -1,15 +1,120 @@
|
|
|
1
|
-
|
|
1
|
+
PolyForm Noncommercial License 1.0.0
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<https://polyformproject.org/licenses/noncommercial/1.0.0>
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
-
copyright notice and this permission notice appear in all copies.
|
|
5
|
+
Required Notice: Copyright (c) 2025 Cognium Labs
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
7
|
+
Acceptance
|
|
8
|
+
|
|
9
|
+
To obtain any license under these terms, you must agree to them as both
|
|
10
|
+
strict obligations and conditions to all your licenses.
|
|
11
|
+
|
|
12
|
+
Copyright License
|
|
13
|
+
|
|
14
|
+
The licensor grants you a copyright license for the software to do
|
|
15
|
+
everything you might do with the software that would otherwise infringe
|
|
16
|
+
the licensor's copyright in it for any permitted purpose. However, you
|
|
17
|
+
may only distribute the software according to Distribution License and
|
|
18
|
+
make changes or new works based on the software according to Changes and
|
|
19
|
+
New Works License.
|
|
20
|
+
|
|
21
|
+
Distribution License
|
|
22
|
+
|
|
23
|
+
The licensor grants you an additional copyright license to distribute
|
|
24
|
+
copies of the software. Your license to distribute covers distributing
|
|
25
|
+
the software with changes and new works permitted by Changes and New
|
|
26
|
+
Works License.
|
|
27
|
+
|
|
28
|
+
Notices
|
|
29
|
+
|
|
30
|
+
You must ensure that anyone who gets a copy of any part of the software
|
|
31
|
+
from you also gets a copy of these terms or the URL for them above, as
|
|
32
|
+
well as copies of any plain-text lines beginning with Required Notice:
|
|
33
|
+
that the licensor provided with the software. For example:
|
|
34
|
+
|
|
35
|
+
Required Notice: Copyright (c) 2025 Cognium Labs
|
|
36
|
+
|
|
37
|
+
Changes and New Works License
|
|
38
|
+
|
|
39
|
+
The licensor grants you an additional copyright license to make changes
|
|
40
|
+
and new works based on the software for any permitted purpose.
|
|
41
|
+
|
|
42
|
+
Patent License
|
|
43
|
+
|
|
44
|
+
The licensor grants you a patent license for the software that covers
|
|
45
|
+
patent claims the licensor can license, or becomes able to license, that
|
|
46
|
+
you would infringe by using the software.
|
|
47
|
+
|
|
48
|
+
Noncommercial Purposes
|
|
49
|
+
|
|
50
|
+
Any noncommercial purpose is a permitted purpose.
|
|
51
|
+
|
|
52
|
+
Personal Uses
|
|
53
|
+
|
|
54
|
+
Personal use for research, experiment, and testing for the benefit of
|
|
55
|
+
public knowledge, personal study, private entertainment, hobby projects,
|
|
56
|
+
amateur pursuits, or religious observance, without any anticipated
|
|
57
|
+
commercial application, is use for a permitted purpose.
|
|
58
|
+
|
|
59
|
+
Noncommercial Organizations
|
|
60
|
+
|
|
61
|
+
Use by any charitable organization, educational institution, public
|
|
62
|
+
research organization, public safety or health organization,
|
|
63
|
+
environmental protection organization, or government institution is use
|
|
64
|
+
for a permitted purpose regardless of the source of funding or
|
|
65
|
+
obligations resulting from the funding.
|
|
66
|
+
|
|
67
|
+
Fair Use
|
|
68
|
+
|
|
69
|
+
You may have "fair use" rights for the software under the law. These
|
|
70
|
+
terms do not limit them.
|
|
71
|
+
|
|
72
|
+
No Other Rights
|
|
73
|
+
|
|
74
|
+
These terms do not allow you to sublicense or transfer any of your
|
|
75
|
+
licenses to anyone else, or prevent the licensor from granting licenses
|
|
76
|
+
to anyone else. These terms do not imply any other licenses.
|
|
77
|
+
|
|
78
|
+
Patent Defense
|
|
79
|
+
|
|
80
|
+
If you make any written claim that the software infringes or contributes
|
|
81
|
+
to infringement of any patent, your patent license for the software
|
|
82
|
+
granted under these terms ends immediately. If your company makes such a
|
|
83
|
+
claim, your patent license ends immediately for work on behalf of your
|
|
84
|
+
company.
|
|
85
|
+
|
|
86
|
+
Violations
|
|
87
|
+
|
|
88
|
+
The first time you are notified in writing that you have violated any of
|
|
89
|
+
these terms, or done anything with the software not covered by your
|
|
90
|
+
licenses, your licenses can nonetheless continue if you come into full
|
|
91
|
+
compliance with these terms, and take practical steps to correct past
|
|
92
|
+
violations, within 32 days of receiving notice. Otherwise, all your
|
|
93
|
+
licenses end immediately.
|
|
94
|
+
|
|
95
|
+
No Liability
|
|
96
|
+
|
|
97
|
+
As far as the law allows, the software comes as is, without any warranty
|
|
98
|
+
or condition, and the licensor will not be liable to you for any damages
|
|
99
|
+
arising out of these terms or the use or nature of the software, under
|
|
100
|
+
any kind of legal claim.
|
|
101
|
+
|
|
102
|
+
Definitions
|
|
103
|
+
|
|
104
|
+
The licensor is the individual or entity offering these terms, and the
|
|
105
|
+
software is the software the licensor makes available under these terms.
|
|
106
|
+
|
|
107
|
+
You refers to the individual or entity agreeing to these terms.
|
|
108
|
+
|
|
109
|
+
Your company is any legal entity, sole proprietorship, or other kind of
|
|
110
|
+
organization that you work for, plus all organizations that have control
|
|
111
|
+
over, are under the control of, or are under common control with that
|
|
112
|
+
organization. Control means ownership of substantially all the assets of
|
|
113
|
+
an entity, or the power to direct its management and policies by vote,
|
|
114
|
+
contract, or otherwise. Control can be direct or indirect.
|
|
115
|
+
|
|
116
|
+
Your licenses are all the licenses granted to you for the software under
|
|
117
|
+
these terms.
|
|
118
|
+
|
|
119
|
+
Use means anything you do with the software requiring one of your
|
|
120
|
+
licenses.
|
package/README.md
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
# circle-ir-ai
|
|
2
2
|
|
|
3
|
-
LLM-enhanced static analysis built on [circle-ir](https://github.com/
|
|
3
|
+
LLM-enhanced static analysis built on [circle-ir](https://github.com/cogniumhq/circle-ir). Provides CLI tools, AI-powered vulnerability verification, and comprehensive security analysis.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- **Multi-Language Support**: Java, JavaScript/TypeScript, Python, Rust
|
|
8
|
-
- **LLM
|
|
9
|
-
- **Pattern Discovery**: Discover sources/sinks beyond YAML patterns
|
|
8
|
+
- **LLM Discovery**: Discover vulnerabilities beyond static patterns via LLM
|
|
10
9
|
- **Cross-File Analysis**: Track taint across file boundaries
|
|
11
|
-
- **AI Skills Analysis**: Security analysis for AI agent skills (
|
|
10
|
+
- **AI Skills Analysis**: Security analysis for AI agent skills (MCP servers)
|
|
12
11
|
- **Security Scanning**: OWASP Top 10 mapping with trend tracking
|
|
13
12
|
- **Dead Code Detection**: Find unreachable code via call graph analysis
|
|
14
13
|
- **Secret Scanning**: Detect secrets in code and Git history
|
|
15
14
|
- **Health Scoring**: Calculate overall codebase health
|
|
16
|
-
- **Benchmark Suite**: OWASP, Juliet, SecuriBench, CWE-Bench test runners
|
|
17
15
|
|
|
18
16
|
## Installation
|
|
19
17
|
|
|
@@ -21,316 +19,196 @@ LLM-enhanced static analysis built on [circle-ir](https://github.com/cognitim/ci
|
|
|
21
19
|
npm install circle-ir-ai circle-ir
|
|
22
20
|
```
|
|
23
21
|
|
|
24
|
-
##
|
|
25
|
-
|
|
26
|
-
### CLI
|
|
22
|
+
## CLI
|
|
27
23
|
|
|
28
24
|
```bash
|
|
29
|
-
# Analyze a single file
|
|
30
|
-
circle-ir-ai src/App.java
|
|
31
|
-
|
|
32
|
-
#
|
|
33
|
-
circle-ir-ai src
|
|
34
|
-
|
|
35
|
-
#
|
|
36
|
-
circle-ir-ai ./
|
|
37
|
-
|
|
38
|
-
# Security scan with OWASP Top 10 mapping
|
|
39
|
-
circle-ir-ai scan ./src
|
|
40
|
-
|
|
41
|
-
# Detect dead/unreachable code
|
|
42
|
-
circle-ir-ai dead-code ./src
|
|
43
|
-
|
|
44
|
-
# Scan for secrets
|
|
45
|
-
circle-ir-ai secrets ./src
|
|
46
|
-
|
|
47
|
-
# Calculate codebase health score
|
|
48
|
-
circle-ir-ai health ./src
|
|
49
|
-
|
|
50
|
-
# Run OWASP Benchmark
|
|
51
|
-
circle-ir-ai benchmark ./testcode --expected ./expected.csv
|
|
52
|
-
|
|
53
|
-
# Analyze AI Skills (OpenClaw, MCP servers)
|
|
54
|
-
circle-ir-ai analyze-skill ./my-skill
|
|
55
|
-
circle-ir-ai analyze-skill ./my-skill --format json -o report.json
|
|
25
|
+
circle-ir-ai src/App.java # Analyze a single file
|
|
26
|
+
circle-ir-ai src/App.java --llm # With LLM verification
|
|
27
|
+
circle-ir-ai ./src --threads 20 # Analyze directory (parallelized)
|
|
28
|
+
circle-ir-ai scan ./src # Security scan (OWASP Top 10)
|
|
29
|
+
circle-ir-ai dead-code ./src # Dead code detection
|
|
30
|
+
circle-ir-ai secrets ./src # Secret scanning
|
|
31
|
+
circle-ir-ai health ./src # Codebase health score
|
|
32
|
+
circle-ir-ai analyze-skill ./my-skill # AI skill security analysis
|
|
56
33
|
```
|
|
57
34
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
Analyze AI agent skills for security issues and capability mismatches. Supports OpenClaw skills and MCP servers.
|
|
35
|
+
Options: `--format json|summary|sarif`, `-o <file>`, `--threads <n>`, `--llm`, `-q`
|
|
61
36
|
|
|
62
|
-
|
|
37
|
+
### LLM CLI Flags
|
|
63
38
|
|
|
64
39
|
```bash
|
|
65
|
-
#
|
|
66
|
-
circle-ir-ai
|
|
67
|
-
|
|
68
|
-
#
|
|
69
|
-
circle-ir-ai
|
|
70
|
-
|
|
71
|
-
# With markdown report
|
|
72
|
-
circle-ir-ai analyze-skill ./my-skill --format markdown -o SECURITY.md
|
|
73
|
-
|
|
74
|
-
# Filter by severity and confidence
|
|
75
|
-
circle-ir-ai analyze-skill ./my-skill --min-severity high --min-confidence 0.8
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
**What it analyzes:**
|
|
79
|
-
|
|
80
|
-
- `SKILL.md` - Natural language instructions (extracts declared capabilities)
|
|
81
|
-
- Code files (`.ts`, `.js`, `.py`, `.java`, `.rs`) - Actual implementation
|
|
82
|
-
- `mcp-server.json` - MCP server configuration (if present)
|
|
83
|
-
- Cross-artifact analysis - Detects capability mismatches between documentation and code
|
|
84
|
-
|
|
85
|
-
**Output:**
|
|
86
|
-
|
|
87
|
-
```
|
|
88
|
-
================================================================================
|
|
89
|
-
SKILL ANALYSIS REPORT: github-reader
|
|
90
|
-
================================================================================
|
|
91
|
-
|
|
92
|
-
Skill ID: github-reader-001
|
|
93
|
-
Version: 1.0.0
|
|
94
|
-
Trust Score: 22.0% 🚨
|
|
95
|
-
Findings: 13
|
|
96
|
-
Analysis Time: 21.84s
|
|
97
|
-
|
|
98
|
-
CRITICAL FINDINGS (1)
|
|
99
|
-
────────────────────────────────────────────────────────────────────────────────
|
|
100
|
-
|
|
101
|
-
1. Server-Side Request Forgery (CWE-918) not declared
|
|
102
|
-
Type: capability_mismatch
|
|
103
|
-
Artifact: src/index.ts
|
|
104
|
-
Confidence: 90%
|
|
105
|
-
Description: The code performs outbound HTTP requests via `https.request()`
|
|
106
|
-
but SKILL.md does not list any such sink.
|
|
107
|
-
|
|
108
|
-
RECOMMENDATIONS
|
|
109
|
-
────────────────────────────────────────────────────────────────────────────────
|
|
110
|
-
|
|
111
|
-
1. Update SKILL.md to accurately describe all capabilities
|
|
112
|
-
2. Add input validation and sanitization
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
**Trust Score Interpretation:**
|
|
116
|
-
|
|
117
|
-
- `90-100%` ✅ - High trust, minimal issues
|
|
118
|
-
- `70-89%` ⚠️ - Medium trust, some concerns
|
|
119
|
-
- `50-69%` ❌ - Low trust, significant issues
|
|
120
|
-
- `<50%` 🚨 - Critical issues, do not deploy
|
|
121
|
-
|
|
122
|
-
**Programmatic API:**
|
|
123
|
-
|
|
124
|
-
```typescript
|
|
125
|
-
import { analyzeSkillBundle } from 'circle-ir-ai/skills';
|
|
126
|
-
|
|
127
|
-
const result = await analyzeSkillBundle('./my-skill', {
|
|
128
|
-
enableCrossArtifact: true, // Detect capability mismatches
|
|
129
|
-
enableVerification: true, // LLM verification
|
|
130
|
-
minConfidence: 0.7,
|
|
131
|
-
minSeverity: 'medium',
|
|
132
|
-
onProgress: (status) => console.log(status.message),
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
console.log(`Trust Score: ${result.score}`);
|
|
136
|
-
console.log(`Findings: ${result.findings.length}`);
|
|
137
|
-
console.log(`Recommendations: ${result.recommendations.join('\n')}`);
|
|
40
|
+
circle-ir-ai ./src --llm # Enable LLM enrichment + verification
|
|
41
|
+
circle-ir-ai ./src --llm-enrich # LLM enrichment only
|
|
42
|
+
circle-ir-ai ./src --llm-verify # LLM verification only
|
|
43
|
+
circle-ir-ai ./src --llm --llm-model gpt-4o # Override model
|
|
44
|
+
circle-ir-ai ./src --llm --llm-base-url <url> # Override API base URL
|
|
45
|
+
circle-ir-ai ./src --llm --llm-api-key <key> # Override API key
|
|
138
46
|
```
|
|
139
47
|
|
|
140
|
-
|
|
48
|
+
| Flag | Description | Default |
|
|
49
|
+
|------|-------------|---------|
|
|
50
|
+
| `--llm` | Enable both enrichment and verification | off |
|
|
51
|
+
| `--llm-enrich` | Enable LLM source/sink discovery | off |
|
|
52
|
+
| `--llm-verify` | Enable LLM exploitability verification | off |
|
|
53
|
+
| `--llm-base-url <url>` | LLM API base URL (OpenAI-compatible) | `http://localhost:4000/v1` |
|
|
54
|
+
| `--llm-api-key <key>` | LLM API key | `LLM_API_KEY` env var |
|
|
55
|
+
| `--llm-model <model>` | LLM model name | `cognium/gpt-oss-120b` |
|
|
141
56
|
|
|
142
|
-
|
|
143
|
-
- **Capability Mismatch Detection**: LLM-based semantic comparison between declared and actual behavior
|
|
144
|
-
- **Vulnerability Detection**: Standard taint analysis on code files
|
|
145
|
-
- **Trust Score**: 0.0-1.0 score based on severity-weighted findings
|
|
146
|
-
- **Actionable Recommendations**: Specific guidance for remediation
|
|
57
|
+
CLI flags override environment variables. Any OpenAI-compatible API works (OpenAI, Azure, Ollama, Together, GitHub Models, etc.).
|
|
147
58
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
- ✅ **74% false positive reduction** through test file exclusion, validation utility recognition, and timeout fixes
|
|
151
|
-
- ✅ **Real-world validated** on official MCP servers (fetch: 84% trust, filesystem: accurate findings)
|
|
152
|
-
- ✅ **Fast analysis** (~25s for typical skills)
|
|
153
|
-
- ⚠️ Large SKILL.md files (>10KB) may take longer to extract
|
|
154
|
-
|
|
155
|
-
**Known Limitations:**
|
|
156
|
-
|
|
157
|
-
- Capability mismatch detection quality depends on LLM model used
|
|
158
|
-
- Trust score may be conservative for complex codebases with many filesystem operations
|
|
159
|
-
|
|
160
|
-
### Programmatic API
|
|
59
|
+
## Programmatic API
|
|
161
60
|
|
|
162
61
|
```typescript
|
|
163
|
-
import {
|
|
164
|
-
import {
|
|
62
|
+
import { initAnalyzer } from 'circle-ir';
|
|
63
|
+
import { analyzeFile } from 'circle-ir-ai';
|
|
165
64
|
|
|
166
|
-
// Initialize
|
|
167
65
|
await initAnalyzer();
|
|
168
66
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
imports,
|
|
177
|
-
{
|
|
178
|
-
enableEnrichment: true,
|
|
179
|
-
enableVerification: true,
|
|
180
|
-
}
|
|
181
|
-
);
|
|
182
|
-
|
|
183
|
-
console.log('Verified vulnerabilities:', result.vulnerabilities);
|
|
67
|
+
const result = await analyzeFile('MyClass.java', code, {
|
|
68
|
+
language: 'java',
|
|
69
|
+
enableEnrichment: true,
|
|
70
|
+
enableVerification: true,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
console.log('Findings:', result.findings);
|
|
184
74
|
```
|
|
185
75
|
|
|
186
|
-
###
|
|
76
|
+
### Multi-file analysis
|
|
187
77
|
|
|
188
78
|
```typescript
|
|
189
79
|
import { analyzeProjectTwoPhase } from 'circle-ir-ai';
|
|
190
80
|
|
|
191
|
-
const files = [
|
|
192
|
-
{ path: 'src/Controller.java', content: controllerCode },
|
|
193
|
-
{ path: 'src/Service.java', content: serviceCode },
|
|
194
|
-
];
|
|
195
|
-
|
|
196
81
|
const result = await analyzeProjectTwoPhase(files, 'java', {
|
|
197
82
|
enableEnrichment: true,
|
|
198
83
|
parallelPhase1: true,
|
|
199
84
|
maxConcurrency: 10,
|
|
200
|
-
enablePhase2: true,
|
|
201
85
|
});
|
|
202
86
|
|
|
203
87
|
console.log('Cross-file taint flows:', result.crossFileFlows);
|
|
204
88
|
```
|
|
205
89
|
|
|
206
|
-
### Security
|
|
90
|
+
### Security scanning, dead code, secrets, health
|
|
207
91
|
|
|
208
92
|
```typescript
|
|
209
|
-
import { scanDirectory,
|
|
93
|
+
import { scanDirectory, detectDeadCode, scanForSecrets, calculateHealthScore } from 'circle-ir-ai';
|
|
210
94
|
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
95
|
+
const scan = await scanDirectory('/path/to/project');
|
|
96
|
+
const deadCode = await detectDeadCode({ target: '/path/to/project' });
|
|
97
|
+
const secrets = await scanForSecrets('/path/to/project', { scanHistory: true });
|
|
98
|
+
const health = await calculateHealthScore('/path/to/project');
|
|
214
99
|
```
|
|
215
100
|
|
|
216
|
-
###
|
|
101
|
+
### AI skill analysis
|
|
217
102
|
|
|
218
103
|
```typescript
|
|
219
|
-
import {
|
|
104
|
+
import { analyzeSkillBundle } from 'circle-ir-ai';
|
|
220
105
|
|
|
221
|
-
const result = await
|
|
222
|
-
|
|
223
|
-
|
|
106
|
+
const result = await analyzeSkillBundle('./my-skill', {
|
|
107
|
+
enableCrossArtifact: true,
|
|
108
|
+
enableVerification: true,
|
|
224
109
|
});
|
|
225
110
|
|
|
226
|
-
console.log(
|
|
227
|
-
|
|
111
|
+
console.log(`Trust Score: ${result.score}`);
|
|
112
|
+
console.log(`Findings: ${result.findings.length}`);
|
|
228
113
|
```
|
|
229
114
|
|
|
230
|
-
|
|
115
|
+
## LLM Configuration
|
|
231
116
|
|
|
232
|
-
|
|
233
|
-
import { scanForSecrets, formatSecretReport } from 'circle-ir-ai';
|
|
117
|
+
Configure via environment variables or CLI flags (flags take precedence):
|
|
234
118
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
119
|
+
```bash
|
|
120
|
+
# Environment variables
|
|
121
|
+
export LLM_API_KEY=your-api-key
|
|
122
|
+
export LLM_BASE_URL=http://localhost:4000/v1
|
|
123
|
+
export LLM_ENRICHMENT_MODEL=cognium/gpt-oss-120b # default (FREE)
|
|
240
124
|
|
|
241
|
-
|
|
125
|
+
# Or use CLI flags directly
|
|
126
|
+
circle-ir-ai ./src --llm \
|
|
127
|
+
--llm-base-url https://api.openai.com/v1 \
|
|
128
|
+
--llm-api-key sk-... \
|
|
129
|
+
--llm-model gpt-4o
|
|
242
130
|
```
|
|
243
131
|
|
|
244
|
-
###
|
|
132
|
+
### Provider Examples
|
|
245
133
|
|
|
246
|
-
|
|
247
|
-
|
|
134
|
+
| Provider | `--llm-base-url` | `--llm-model` |
|
|
135
|
+
|----------|-------------------|---------------|
|
|
136
|
+
| Cognium (free) | `http://localhost:4000/v1` | `cognium/gpt-oss-120b` |
|
|
137
|
+
| OpenAI | `https://api.openai.com/v1` | `gpt-4o` |
|
|
138
|
+
| GitHub Models (free) | `https://models.github.ai/inference` | `openai/gpt-5` |
|
|
139
|
+
| Azure OpenAI | `https://YOUR.openai.azure.com/...` | `gpt-4o` |
|
|
140
|
+
| Ollama (local) | `http://localhost:11434/v1` | `llama3` |
|
|
141
|
+
| Together AI | `https://api.together.xyz/v1` | `meta-llama/Llama-3-70b` |
|
|
248
142
|
|
|
249
|
-
|
|
250
|
-
includeSecurity: true,
|
|
251
|
-
includeSecrets: true,
|
|
252
|
-
includeDeadCode: true,
|
|
253
|
-
});
|
|
143
|
+
## CI/CD with GitHub Actions
|
|
254
144
|
|
|
255
|
-
|
|
256
|
-
// Scores: Security 35%, Maintainability 25%, Quality 25%, Performance 15%
|
|
257
|
-
```
|
|
145
|
+
Run LLM-enhanced SAST in CI using [GitHub Models](https://github.com/marketplace?type=models) free tier -- no API keys needed:
|
|
258
146
|
|
|
259
|
-
|
|
147
|
+
```yaml
|
|
148
|
+
name: SAST Scan
|
|
149
|
+
on: [pull_request]
|
|
260
150
|
|
|
261
|
-
|
|
151
|
+
permissions:
|
|
152
|
+
contents: read
|
|
153
|
+
models: read
|
|
262
154
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
155
|
+
jobs:
|
|
156
|
+
scan:
|
|
157
|
+
runs-on: ubuntu-latest
|
|
158
|
+
steps:
|
|
159
|
+
- uses: actions/checkout@v4
|
|
160
|
+
- uses: actions/setup-node@v4
|
|
161
|
+
with:
|
|
162
|
+
node-version: "22"
|
|
267
163
|
|
|
268
|
-
|
|
164
|
+
- run: npm ci && npm run build
|
|
165
|
+
working-directory: circle-ir-ai
|
|
269
166
|
|
|
270
|
-
|
|
271
|
-
|
|
167
|
+
# Required: symlink WASM files for tree-sitter
|
|
168
|
+
- run: ln -s node_modules/circle-ir/dist/wasm wasm
|
|
169
|
+
working-directory: circle-ir-ai
|
|
272
170
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
}
|
|
171
|
+
- name: LLM-enhanced SAST scan
|
|
172
|
+
working-directory: circle-ir-ai
|
|
173
|
+
env:
|
|
174
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
175
|
+
run: |
|
|
176
|
+
node dist/cli/index.js ./src --llm \
|
|
177
|
+
--llm-base-url https://models.github.ai/inference \
|
|
178
|
+
--llm-api-key "$GITHUB_TOKEN" \
|
|
179
|
+
--llm-model openai/gpt-5 \
|
|
180
|
+
--format json -o sast-results.json
|
|
277
181
|
```
|
|
278
182
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
```
|
|
282
|
-
circle-ir-ai <file|dir> [options]
|
|
283
|
-
|
|
284
|
-
Commands:
|
|
285
|
-
<file|dir> Analyze file or directory
|
|
286
|
-
scan <dir> Security scan with OWASP mapping
|
|
287
|
-
dead-code <dir> Detect unreachable code
|
|
288
|
-
secrets <dir> Scan for secrets
|
|
289
|
-
health <dir> Calculate health score
|
|
290
|
-
benchmark <dir> Run benchmark suite
|
|
291
|
-
|
|
292
|
-
Options:
|
|
293
|
-
-f, --format <fmt> Output format: json, summary, sarif
|
|
294
|
-
-o, --output <file> Write output to file
|
|
295
|
-
--llm Enable LLM enrichment and verification
|
|
296
|
-
--llm-enrich Enable LLM enrichment only
|
|
297
|
-
--llm-verify Enable LLM verification only
|
|
298
|
-
--llm-base-url <url> LLM proxy URL
|
|
299
|
-
--llm-api-key <key> LLM API key
|
|
300
|
-
--threads <n> Parallel analysis threads (default: 10)
|
|
301
|
-
-d, --discover-patterns Enable dynamic pattern discovery
|
|
302
|
-
-q, --quiet Suppress progress messages
|
|
303
|
-
-h, --help Show help
|
|
304
|
-
```
|
|
183
|
+
**GitHub Models free tier limits**: `openai/gpt-5` = 50 req/day, `openai/gpt-4o-mini` = 150 req/day. Auth uses the built-in `GITHUB_TOKEN` with `models: read` permission.
|
|
305
184
|
|
|
306
185
|
## Benchmark Results
|
|
307
186
|
|
|
308
|
-
| Benchmark | Score |
|
|
309
|
-
|
|
310
|
-
|
|
|
311
|
-
|
|
|
312
|
-
|
|
|
313
|
-
|
|
|
314
|
-
|
|
|
315
|
-
|
|
|
316
|
-
|
|
317
|
-
|
|
187
|
+
| Benchmark | Score |
|
|
188
|
+
|-----------|-------|
|
|
189
|
+
| OWASP Benchmark (Java, 1415 tests) | +100% |
|
|
190
|
+
| Juliet Test Suite (156 tests) | +100% |
|
|
191
|
+
| SecuriBench Micro | 97.7% TPR, 6.7% FPR |
|
|
192
|
+
| CWE-Bench-Java (120 CVEs) | 42.5% static, 81.7% +LLM Discovery |
|
|
193
|
+
| NodeJS Synthetic (25 tests) | 100% TPR |
|
|
194
|
+
| CWE-Bench-Rust (30 tests) | 77.8% TPR, 0% FPR |
|
|
195
|
+
|
|
196
|
+
CWE-Bench-Java reference: CodeQL 22.5%, IRIS+GPT-4 45.8%.
|
|
318
197
|
|
|
319
198
|
## Supported Languages
|
|
320
199
|
|
|
321
|
-
| Language |
|
|
322
|
-
|
|
323
|
-
|
|
|
324
|
-
|
|
|
325
|
-
|
|
|
326
|
-
|
|
|
327
|
-
| **Rust** | .rs | Actix-web, Rocket, Axum |
|
|
200
|
+
| Language | Frameworks |
|
|
201
|
+
|----------|------------|
|
|
202
|
+
| Java | Spring, JAX-RS, Servlet API |
|
|
203
|
+
| JavaScript/TypeScript | Express, Fastify, Node.js |
|
|
204
|
+
| Python | Flask, Django, FastAPI |
|
|
205
|
+
| Rust | Actix-web, Rocket, Axum |
|
|
328
206
|
|
|
329
207
|
## Related Packages
|
|
330
208
|
|
|
331
|
-
- **[circle-ir](https://github.com/
|
|
332
|
-
- **[circle-pack](https://github.com/cognitim/circle-pack)**: Cloudflare Workers API deployment
|
|
209
|
+
- **[circle-ir](https://github.com/cogniumhq/circle-ir)**: Core SAST library (open source, MIT)
|
|
333
210
|
|
|
334
211
|
## License
|
|
335
212
|
|
|
336
|
-
|
|
213
|
+
PolyForm Noncommercial License 1.0.0 -- free for noncommercial use.
|
|
214
|
+
Commercial use requires a separate license. See [LICENSE](./LICENSE) for details.
|
|
@@ -90,14 +90,14 @@ export declare const verificationAgent: Agent<"verification-agent", {
|
|
|
90
90
|
export declare const crossFileAgent: Agent<"cross-file-agent", {
|
|
91
91
|
crossFileTaint: import("@mastra/core/tools").Tool<{
|
|
92
92
|
sourceCode: string;
|
|
93
|
-
sourceFile: string;
|
|
94
|
-
targetFile: string;
|
|
95
|
-
targetCode: string;
|
|
96
93
|
exportedTaint: {
|
|
97
94
|
symbol: string;
|
|
98
95
|
type: string;
|
|
99
96
|
line: number;
|
|
100
97
|
}[];
|
|
98
|
+
targetFile: string;
|
|
99
|
+
sourceFile: string;
|
|
100
|
+
targetCode: string;
|
|
101
101
|
importedSymbols: string[];
|
|
102
102
|
}, {
|
|
103
103
|
taintFlows: Array<{
|
|
@@ -178,14 +178,14 @@ export declare const orchestratorAgent: Agent<"orchestrator-agent", {
|
|
|
178
178
|
}, unknown, unknown, import("@mastra/core/tools").ToolExecutionContext<unknown, unknown, unknown>, "verify-vulnerability", unknown>;
|
|
179
179
|
crossFileTaint: import("@mastra/core/tools").Tool<{
|
|
180
180
|
sourceCode: string;
|
|
181
|
-
sourceFile: string;
|
|
182
|
-
targetFile: string;
|
|
183
|
-
targetCode: string;
|
|
184
181
|
exportedTaint: {
|
|
185
182
|
symbol: string;
|
|
186
183
|
type: string;
|
|
187
184
|
line: number;
|
|
188
185
|
}[];
|
|
186
|
+
targetFile: string;
|
|
187
|
+
sourceFile: string;
|
|
188
|
+
targetCode: string;
|
|
189
189
|
importedSymbols: string[];
|
|
190
190
|
}, {
|
|
191
191
|
taintFlows: Array<{
|
|
@@ -266,14 +266,14 @@ export declare const agents: {
|
|
|
266
266
|
crossFile: Agent<"cross-file-agent", {
|
|
267
267
|
crossFileTaint: import("@mastra/core/tools").Tool<{
|
|
268
268
|
sourceCode: string;
|
|
269
|
-
sourceFile: string;
|
|
270
|
-
targetFile: string;
|
|
271
|
-
targetCode: string;
|
|
272
269
|
exportedTaint: {
|
|
273
270
|
symbol: string;
|
|
274
271
|
type: string;
|
|
275
272
|
line: number;
|
|
276
273
|
}[];
|
|
274
|
+
targetFile: string;
|
|
275
|
+
sourceFile: string;
|
|
276
|
+
targetCode: string;
|
|
277
277
|
importedSymbols: string[];
|
|
278
278
|
}, {
|
|
279
279
|
taintFlows: Array<{
|
|
@@ -349,14 +349,14 @@ export declare const agents: {
|
|
|
349
349
|
}, unknown, unknown, import("@mastra/core/tools").ToolExecutionContext<unknown, unknown, unknown>, "verify-vulnerability", unknown>;
|
|
350
350
|
crossFileTaint: import("@mastra/core/tools").Tool<{
|
|
351
351
|
sourceCode: string;
|
|
352
|
-
sourceFile: string;
|
|
353
|
-
targetFile: string;
|
|
354
|
-
targetCode: string;
|
|
355
352
|
exportedTaint: {
|
|
356
353
|
symbol: string;
|
|
357
354
|
type: string;
|
|
358
355
|
line: number;
|
|
359
356
|
}[];
|
|
357
|
+
targetFile: string;
|
|
358
|
+
sourceFile: string;
|
|
359
|
+
targetCode: string;
|
|
360
360
|
importedSymbols: string[];
|
|
361
361
|
}, {
|
|
362
362
|
taintFlows: Array<{
|