@orionscanner/cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +248 -0
- package/assets/logo.png +0 -0
- package/bin/orion.js +48 -0
- package/docs/API_REFERENCE.md +211 -0
- package/docs/ARCHITECTURE.md +183 -0
- package/docs/CHANGELOG.md +112 -0
- package/docs/CONTRIBUTING.md +157 -0
- package/docs/ENGINE_CATALOG.md +87 -0
- package/docs/GETTING_STARTED.md +226 -0
- package/package.json +48 -0
- package/pyproject.toml +16 -0
- package/src/orion/__init__.py +0 -0
- package/src/orion/__pycache__/__init__.cpython-313.pyc +0 -0
- package/src/orion/engine/__init__.py +17 -0
- package/src/orion/engine/__pycache__/__init__.cpython-313.pyc +0 -0
- package/src/orion/engine/__pycache__/config.cpython-313.pyc +0 -0
- package/src/orion/engine/__pycache__/core.cpython-313.pyc +0 -0
- package/src/orion/engine/__pycache__/ir.cpython-313.pyc +0 -0
- package/src/orion/engine/__pycache__/languages.cpython-313.pyc +0 -0
- package/src/orion/engine/__pycache__/registry.cpython-313.pyc +0 -0
- package/src/orion/engine/__pycache__/results.cpython-313.pyc +0 -0
- package/src/orion/engine/__pycache__/runner.cpython-313.pyc +0 -0
- package/src/orion/engine/api_security/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/api_security/engine.py +125 -0
- package/src/orion/engine/architecture/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/architecture/engine.py +463 -0
- package/src/orion/engine/authorization/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/authorization/engine.py +337 -0
- package/src/orion/engine/callgraph/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/callgraph/engine.py +236 -0
- package/src/orion/engine/cfg/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/cfg/engine.py +509 -0
- package/src/orion/engine/chaos/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/chaos/engine.py +268 -0
- package/src/orion/engine/chaos_config/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/chaos_config/engine.py +322 -0
- package/src/orion/engine/complexity/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/complexity/engine.py +144 -0
- package/src/orion/engine/compliance/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/compliance/engine.py +325 -0
- package/src/orion/engine/config.py +41 -0
- package/src/orion/engine/config_engine/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/config_engine/engine.py +364 -0
- package/src/orion/engine/config_validation/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/config_validation/engine.py +313 -0
- package/src/orion/engine/container/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/container/engine.py +546 -0
- package/src/orion/engine/contract_probe/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/contract_probe/engine.py +316 -0
- package/src/orion/engine/core.py +75 -0
- package/src/orion/engine/crypto_guard/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/crypto_guard/engine.py +134 -0
- package/src/orion/engine/data_residency/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/data_residency/engine.py +238 -0
- package/src/orion/engine/dataflow/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/dataflow/engine.py +398 -0
- package/src/orion/engine/dead_import/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/dead_import/engine.py +293 -0
- package/src/orion/engine/deps/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/deps/engine.py +244 -0
- package/src/orion/engine/dispatcher.py +350 -0
- package/src/orion/engine/docs/AUDIT_PROMPT.md +1248 -0
- package/src/orion/engine/duplication/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/duplication/engine.py +120 -0
- package/src/orion/engine/error_handling/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/error_handling/engine.py +256 -0
- package/src/orion/engine/fp_learn/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/fp_learn/engine.py +248 -0
- package/src/orion/engine/hunter/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/hunter/engine.py +324 -0
- package/src/orion/engine/iac_security/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/iac_security/engine.py +218 -0
- package/src/orion/engine/ir.py +22 -0
- package/src/orion/engine/languages.py +454 -0
- package/src/orion/engine/license/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/license/engine.py +172 -0
- package/src/orion/engine/lint/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/lint/engine.py +558 -0
- package/src/orion/engine/llm_security/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/llm_security/engine.py +125 -0
- package/src/orion/engine/logging_c/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/logging_c/engine.py +164 -0
- package/src/orion/engine/noise/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/noise/engine.py +140 -0
- package/src/orion/engine/orphan/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/orphan/engine.py +244 -0
- package/src/orion/engine/perf_guard/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/perf_guard/engine.py +345 -0
- package/src/orion/engine/prompt_security/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/prompt_security/detectors/__init__.py +4 -0
- package/src/orion/engine/prompt_security/engine.py +170 -0
- package/src/orion/engine/provenance/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/provenance/engine.py +242 -0
- package/src/orion/engine/registry.py +55 -0
- package/src/orion/engine/regression/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/regression/engine.py +213 -0
- package/src/orion/engine/results.py +21 -0
- package/src/orion/engine/runner.py +1310 -0
- package/src/orion/engine/sandbox_escape/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/sandbox_escape/engine.py +284 -0
- package/src/orion/engine/sast/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/sast/engine.py +217 -0
- package/src/orion/engine/sast/patterns/__init__.py +513 -0
- package/src/orion/engine/sast/patterns/__pycache__/__init__.cpython-313.pyc +0 -0
- package/src/orion/engine/secrets/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/secrets/engine.py +77 -0
- package/src/orion/engine/secrets/patterns/__init__.py +74 -0
- package/src/orion/engine/secrets/patterns/__pycache__/__init__.cpython-313.pyc +0 -0
- package/src/orion/engine/sensitive_data/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/sensitive_data/engine.py +143 -0
- package/src/orion/engine/state/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/state/engine.py +218 -0
- package/src/orion/engine/supply_chain_sbom/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/supply_chain_sbom/engine.py +290 -0
- package/src/orion/engine/symbol/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/symbol/engine.py +463 -0
- package/src/orion/engine/taint/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/taint/engine.py +464 -0
- package/src/orion/engine/test_coverage/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/test_coverage/engine.py +445 -0
- package/src/orion/engine/threat_model/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/threat_model/engine.py +126 -0
- package/src/orion/engine/wiring_trace/__pycache__/engine.cpython-313.pyc +0 -0
- package/src/orion/engine/wiring_trace/engine.py +200 -0
- package/src/orion_engine.egg-info/PKG-INFO +7 -0
- package/src/orion_engine.egg-info/SOURCES.txt +65 -0
- package/src/orion_engine.egg-info/dependency_links.txt +1 -0
- package/src/orion_engine.egg-info/entry_points.txt +2 -0
- package/src/orion_engine.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# Orion Engine Architecture
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Orion Engine is a **polyglot code audit platform** with 38 native analysis engines, built as a single MIT-licensed Python package. No external tool dependencies (Semgrep, TruffleHog, Safety, Bandit, etc.).
|
|
6
|
+
|
|
7
|
+
## Core Design Principles
|
|
8
|
+
|
|
9
|
+
| Principle | Implementation |
|
|
10
|
+
|-----------|----------------|
|
|
11
|
+
| **Total Coverage** | 38 engines covering security, quality, architecture, supply chain, compliance |
|
|
12
|
+
| **Hardened** | No silent failures, secret zeroization, resource limits, per-engine timeouts |
|
|
13
|
+
| **Atomic** | Per-engine isolation - one failure doesn't cascade |
|
|
14
|
+
| **Native** | Pure Python, zero subprocess calls, zero external tool dependencies |
|
|
15
|
+
| **Orchestrated** | Single `OrionEngine().run()` entry point for all 38 engines |
|
|
16
|
+
| **Scalable** | Async/await, connection pooling, stateless engines, polyglot dispatch |
|
|
17
|
+
|
|
18
|
+
## Architecture Overview
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
��─────────────────────────────────────────────────────────────��
|
|
22
|
+
│ OrionEngine │
|
|
23
|
+
│ (Orchestrator - single run() entry point) │
|
|
24
|
+
��──────────────────────────��──────────────────────────────────��
|
|
25
|
+
│
|
|
26
|
+
��─────────────────��─────────────────��
|
|
27
|
+
�� �� ��
|
|
28
|
+
��────────────────�� ��────────────────�� ��────────────────��
|
|
29
|
+
│ Polyglot │ │ Engine │ │ Registry │
|
|
30
|
+
│ Dispatcher │ │ Registry │ │ (38 engines) │
|
|
31
|
+
��──────��─────────�� └────────────────�� └────────────────��
|
|
32
|
+
│
|
|
33
|
+
��
|
|
34
|
+
��─────────────────────────────────────────────────────────────��
|
|
35
|
+
│ Language Detection │
|
|
36
|
+
│ .py → Python .js/.ts → JS/TS .html → HTML │
|
|
37
|
+
│ .java → Java .go → Go .rs → Rust │
|
|
38
|
+
│ Dockerfile docker-compose .yaml/.json/.toml │
|
|
39
|
+
��──────────────────────────��────────────────────────────────────��
|
|
40
|
+
│
|
|
41
|
+
��─────────────────��─────────────────��
|
|
42
|
+
�� �� ��
|
|
43
|
+
��────────────────�� ��────────────────�� ��────────────────��
|
|
44
|
+
│ Python AST │ Universal Regex │ Language-Specific│
|
|
45
|
+
│ Analyzers │ (Fallback) │ Analyzers │
|
|
46
|
+
��────────────────�� └────────────────�� └────────────────��
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Core Components
|
|
50
|
+
|
|
51
|
+
### 1. OrionEngine (Orchestrator)
|
|
52
|
+
- Single entry point: `OrionEngine().run(irs, config)`
|
|
53
|
+
- Manages 38 engines concurrently with timeouts
|
|
54
|
+
- Aggregates findings, handles errors silently
|
|
55
|
+
|
|
56
|
+
### 2. Polyglot Dispatcher
|
|
57
|
+
- Detects language from file extension/filename
|
|
58
|
+
- Routes to language-specific analyzer or universal fallback
|
|
59
|
+
- Supports 20+ languages out of the box
|
|
60
|
+
|
|
61
|
+
### 3. Engine Registry
|
|
62
|
+
- Auto-discovers 38 engines on first use
|
|
63
|
+
- Maps engine name → engine class
|
|
64
|
+
- Provides health checks and resource limits
|
|
65
|
+
|
|
66
|
+
### 4. IR (Intermediate Representation)
|
|
67
|
+
- Content-addressed (SHA-256)
|
|
68
|
+
- Carries: content, path, language, project_root, metadata
|
|
69
|
+
- Immutable, serializable
|
|
70
|
+
|
|
71
|
+
## 38 Engines by Category
|
|
72
|
+
|
|
73
|
+
### Security (7)
|
|
74
|
+
| Engine | Purpose | Languages |
|
|
75
|
+
|--------|---------|-----------|
|
|
76
|
+
| `sast` | SQLi, XSS, CMDi, SSRF, path traversal, secrets, weak crypto | Python (AST), JS/TS (regex), Universal |
|
|
77
|
+
| `secrets` | API keys, tokens, passwords (regex + entropy) | All text files |
|
|
78
|
+
| `deps` | Vulnerable deps (requirements.txt, package.json, Cargo.toml, etc.) | Python, JS/TS, Go, Rust, Java, PHP, Ruby |
|
|
79
|
+
| `taint` | User input → dangerous sink tracking | Python (AST), JS/TS (planned) |
|
|
80
|
+
| `authorization` | Missing auth on routes | Python (Flask/FastAPI/Django), JS/TS (Express) |
|
|
81
|
+
| `sandbox_escape` | `__import__('os')`, `eval(compile())`, etc. | Python |
|
|
82
|
+
| `prompt_security` | Prompt injection detection | All text files |
|
|
83
|
+
|
|
84
|
+
### AST/IR Analysis (8)
|
|
85
|
+
`callgraph`, `cfg`, `symbol`, `dataflow`, `orphan`, `dead_import`, `wiring_trace`, `state`
|
|
86
|
+
|
|
87
|
+
### Quality (7)
|
|
88
|
+
`complexity`, `duplication`, `error_handling`, `logging_c`, `license`, `lint`, `test_coverage`
|
|
89
|
+
|
|
90
|
+
### Config/Infra (7)
|
|
91
|
+
`config_engine`, `config_validation`, `contract_probe`, `perf_guard`, `data_residency`, `regression`, `container`
|
|
92
|
+
|
|
93
|
+
### Meta/Supply Chain (9)
|
|
94
|
+
`chaos`, `chaos_config`, `noise`, `hunter`, `supply_chain_sbom`, `compliance`, `provenance`, `fp_learn`, `architecture`
|
|
95
|
+
|
|
96
|
+
## Data Flow
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
User Code → Files → IR List → OrionEngine.run()
|
|
100
|
+
│
|
|
101
|
+
��
|
|
102
|
+
��──────────────────────��
|
|
103
|
+
│ For each IR: │
|
|
104
|
+
│ 1. Detect language │
|
|
105
|
+
│ 2. Route to analyzer │
|
|
106
|
+
│ 3. Collect findings │
|
|
107
|
+
└──────────────────────��
|
|
108
|
+
│
|
|
109
|
+
��
|
|
110
|
+
��──────────────────────��
|
|
111
|
+
│ Aggregate & Dedupe │
|
|
112
|
+
│ Score & Grade │
|
|
113
|
+
│ Generate Reports │
|
|
114
|
+
└──────────────────────��
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Configuration
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
config = EngineConfig(
|
|
121
|
+
toggles={
|
|
122
|
+
"exclude": ["tests/", "vendor/", "*.min.js"],
|
|
123
|
+
"only_engines": ["sast", "secrets", "deps"],
|
|
124
|
+
"severity_threshold": "medium",
|
|
125
|
+
},
|
|
126
|
+
resource_limits=ResourceLimits(
|
|
127
|
+
max_cpu_seconds=120,
|
|
128
|
+
max_memory_mb=1024,
|
|
129
|
+
max_files=50000
|
|
130
|
+
),
|
|
131
|
+
network_policy=NetworkPolicy(allow_outbound=False)
|
|
132
|
+
)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Reports
|
|
136
|
+
|
|
137
|
+
Three formats generated in `ORION SCANNER REPORTS/`:
|
|
138
|
+
- **HTML** - Dark theme, sidebar nav, expandable findings, score/grade
|
|
139
|
+
- **JSON** - Machine-readable, CI/CD integration
|
|
140
|
+
- **TXT** - Human-readable summary
|
|
141
|
+
|
|
142
|
+
## Extending Engines
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
class MyEngine:
|
|
146
|
+
name = "my_engine"
|
|
147
|
+
version = "1.0.0"
|
|
148
|
+
|
|
149
|
+
async def check_availability(self) -> bool: return True
|
|
150
|
+
|
|
151
|
+
def resource_limits(self):
|
|
152
|
+
return ResourceLimits(max_cpu_seconds=30, max_memory_mb=256)
|
|
153
|
+
|
|
154
|
+
async def run(self, ir: OrionIR, config: EngineConfig) -> EngineResult:
|
|
155
|
+
# Language-aware analysis
|
|
156
|
+
language = ir.metadata.get("language")
|
|
157
|
+
# ... analysis logic
|
|
158
|
+
return EngineResult(engine=self.name, findings=[...], ok=True)
|
|
159
|
+
|
|
160
|
+
# Register
|
|
161
|
+
EngineRegistry().register("my_engine", MyEngine)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Polyglot Support Matrix
|
|
165
|
+
|
|
166
|
+
| Language | SAST | Secrets | Deps | Taint | Callgraph | Config |
|
|
167
|
+
|----------|------|---------|------|-------|-----------|--------|
|
|
168
|
+
| Python | �� AST | �� | �� | �� AST | �� | �� |
|
|
169
|
+
| JavaScript | �� Regex | �� | �� | ��� Planned | ��� | �� |
|
|
170
|
+
| TypeScript | �� Regex | �� | �� | ��� Planned | ��� | �� |
|
|
171
|
+
| Java | ��� Regex | �� | �� | ��� | ��� | �� |
|
|
172
|
+
| Go | ��� Regex | �� | �� | ��� | ��� | �� |
|
|
173
|
+
| Rust | ��� Regex | �� | �� | ��� | ��� | �� |
|
|
174
|
+
| PHP | ��� Regex | �� | �� | ��� | ��� | �� |
|
|
175
|
+
| Ruby | ��� Regex | �� | �� | ��� | ��� | �� |
|
|
176
|
+
| C/C++ | ��� Regex | �� | ��� | ��� | ��� | �� |
|
|
177
|
+
| C# | ��� Regex | �� | �� | ��� | ��� | �� |
|
|
178
|
+
| Go/Rust/JS/TS | Universal | �� | �� | Universal | ��� | �� |
|
|
179
|
+
| HTML/CSS | ��� Regex | �� | ��� | Universal | ��� | ��� |
|
|
180
|
+
| Dockerfile | ��� Regex | �� | �� | Universal | ��� | �� |
|
|
181
|
+
| YAML/JSON/TOML | ��� | �� | �� | ��� | ��� | �� |
|
|
182
|
+
|
|
183
|
+
��� = Full support | ��� = Regex/Universal fallback | ��� = Not applicable
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to Orion Engine.
|
|
4
|
+
|
|
5
|
+
## [0.1.0] - 2026-08-14
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- **38 Native Engines** — SAST, Secrets, Deps, Taint, Callgraph, CFG, Symbol, Dataflow, Authorization, Orphan, Prompt Security, Contract Probe, Wiring Trace, State, License, Complexity, Duplication, Dead Import, Error Handling, Logging, Config Engine, Chaos, Chaos Config, Regression, Perf Guard, Data Residency, Noise, Supply Chain SBOM, Hunter, Lint, Architecture, Test Coverage, Container, Compliance, Provenance, FP Learn, Sandbox Escape, Config Validation
|
|
9
|
+
- **Polyglot Support** — 20+ languages via automatic detection and universal regex fallback
|
|
10
|
+
- **Polyglot Dispatcher** — Routes files to language-specific analyzers or universal regex
|
|
11
|
+
- **Language Infrastructure** — 20+ languages, capabilities registry, extension mapping
|
|
12
|
+
- **Professional HTML Reports** — Dark theme, sidebar nav, expandable findings, score/grade (A-F), responsive design
|
|
13
|
+
- **Interactive CLI** — Menu system (9 options), multi-colored spinner, auto clear-screen
|
|
14
|
+
- **Three Report Formats** — HTML (dark theme), JSON (CI/CD), TXT (human-readable)
|
|
15
|
+
- **False Positive Learning** — Reads `.orion-feedback.json`, reduces confidence on matches
|
|
16
|
+
- **Compliance Mapping** — GDPR, PCI-DSS, SOC2, HIPAA
|
|
17
|
+
- **SBOM Generation** — CycloneDX format with purl, hashes, licenses
|
|
18
|
+
- **Provenance Attestation** — SLSA-like: git commit, file hashes, builder identity
|
|
19
|
+
- **FP Learning** — Reads feedback, reduces confidence on similar patterns
|
|
20
|
+
- **Config Validation** — Self-validates OrionEngine config
|
|
21
|
+
|
|
22
|
+
### Core Platform
|
|
23
|
+
- `OrionEngine` — Single orchestrator, async, 38 engines concurrent
|
|
24
|
+
- `EngineConfig` — Toggles, resource limits, network policy
|
|
25
|
+
- `ResourceLimits` — CPU, memory, file size, file count limits
|
|
26
|
+
- `NetworkPolicy` — Outbound control with allowlist
|
|
27
|
+
- `OrionIR` — Content-addressed (SHA-256), immutable
|
|
28
|
+
- `EngineResult` / `Finding` — Structured results with evidence
|
|
29
|
+
- `EngineRegistry` — Auto-discovery of 38 engines
|
|
30
|
+
|
|
31
|
+
### Language Support (20+)
|
|
32
|
+
Python, JavaScript, TypeScript, Java, Go, Rust, PHP, Ruby, C/C++, C#, HTML, CSS, YAML, JSON, TOML, XML, Dockerfile, Shell, PowerShell, Markdown
|
|
33
|
+
|
|
34
|
+
### Security Engines
|
|
35
|
+
- **sast** — SQLi, XSS, CMDi, SSRF, path traversal, hardcoded creds, weak crypto, deserialization
|
|
36
|
+
- **secrets** — API keys, tokens, passwords (regex + entropy), test pattern filtering
|
|
37
|
+
- **deps** — Vulnerable deps (requirements.txt, package.json, Cargo.toml, go.mod, pom.xml, composer.json, Gemfile, Pipfile, poetry.lock, yarn.lock, pnpm-lock.yaml)
|
|
38
|
+
- **taint** — User input → dangerous sinks (SQL, shell, code exec, template, deserialization)
|
|
39
|
+
- **authorization** — Missing auth on Flask/FastAPI/Django/Express/Spring/Gin/Laravel/Rails/ASP.NET routes
|
|
40
|
+
- **sandbox_escape** — `__import__('os')`, `eval(compile())`, `ctypes`, `__subclasses__()`, `Function` constructor, `Runtime.exec`, `Process.Start`
|
|
41
|
+
- **prompt_security** — Prompt injection, jailbreak, base64 payloads, special tokens
|
|
42
|
+
|
|
43
|
+
### AST/IR Analysis Engines
|
|
44
|
+
- **callgraph** — Function calls, recursion, undefined functions, deep chains
|
|
45
|
+
- **cfg** — Control flow: unreachable code, infinite loops, missing returns, cyclomatic complexity
|
|
46
|
+
- **symbol** — Symbol table: shadowed builtins, undefined names, unused imports, late-binding closures
|
|
47
|
+
- **dataflow** — Variable def/use: use-before-def, dead stores, mutable defaults, global mutations
|
|
48
|
+
- **orphan** — Zero incoming imports (excludes entry points)
|
|
49
|
+
- **dead_import** — Unused imports across scopes
|
|
50
|
+
- **wiring_trace** — Config → usage tracing
|
|
51
|
+
- **state** — Mutable globals, class attrs, function defaults, `global`/`nonlocal`
|
|
52
|
+
|
|
53
|
+
### Quality Engines
|
|
54
|
+
- **complexity** — Cyclomatic & cognitive complexity (>10/20/50)
|
|
55
|
+
- **duplication** — Sliding window token normalization, SHA256 clustering
|
|
56
|
+
- **error_handling** — Bare except, swallowed errors, lost causes, assert in prod, sys.exit in libs
|
|
57
|
+
- **logging_c** — print() in prod, PII in logs, missing getLogger, DEBUG in prod, no structured logging
|
|
58
|
+
- **license** — SPDX headers, GPL/AGPL detection, root LICENSE, dep conflicts
|
|
59
|
+
- **lint** — Unused vars, undefined names, import order, line length, docstrings, wildcards, ==None, bare except
|
|
60
|
+
- **test_coverage** — Untested public functions, test-only-mocks, no assertions, long tests, missing conftest
|
|
61
|
+
|
|
62
|
+
### Config/Infra Engines
|
|
63
|
+
- **config_engine** — Required keys, types, placeholders, secrets, duplicates, URLs, emails
|
|
64
|
+
- **chaos** — No retry/circuit-breaker/timeout/idempotency, global locks, direct instantiation
|
|
65
|
+
- **chaos_config** — Empty/null/negative/huge values, invalid enums, circular refs, long strings
|
|
66
|
+
- **regression** — Monkey patching, dynamic imports, sys.modules mutation, builtins/env mutation
|
|
67
|
+
- **perf_guard** — N+1 queries, O(n²) loops, string concat, large in-memory, missing pagination, sync I/O in async
|
|
68
|
+
- **data_residency** — PII: emails, phones, SSN, credit cards (Luhn), IPs, UUIDs, API keys
|
|
69
|
+
- **container** — Dockerfile, docker-compose, K8s YAML, Helm: root, latest tag, secrets, privileged, host namespaces, healthcheck, limits
|
|
70
|
+
|
|
71
|
+
### Meta/Supply Chain Engines
|
|
72
|
+
- **noise** — Low confidence + recent changes + high churn, duplicates, generated files
|
|
73
|
+
- **hunter** — Cross-engine correlation: SQLi+auth=CRITICAL, XSS+CSP=HIGH, secret+public=CRITICAL
|
|
74
|
+
- **supply_chain_sbom** — CycloneDX: purl, hashes, licenses, external refs
|
|
75
|
+
- **compliance** — GDPR (Art 25/32/33), PCI-DSS (Req 3/4/6/8), SOC2 (CC6.1/6.7/7.2), HIPAA (164.312)
|
|
76
|
+
- **provenance** — Git commit/tag/branch, SHA256 file hashes, builder identity, dep hashes
|
|
77
|
+
- **fp_learn** — Reads `.orion-feedback.json`, reduces confidence by 0.3 on feature match
|
|
78
|
+
- **config_validation** — Validates paths, globs, limits, network policy, parallelism, timeout
|
|
79
|
+
- **architecture** — Cyclic imports, layer violations (domain→app→infra→pres), god classes/modules, feature envy
|
|
80
|
+
|
|
81
|
+
### Reports
|
|
82
|
+
- **HTML** — Dark theme, fixed sidebar, expandable findings, score/grade (A-F), responsive, print-ready
|
|
83
|
+
- **JSON** — Machine-readable, CI/CD ready
|
|
84
|
+
- **TXT** — Human-readable summary
|
|
85
|
+
|
|
86
|
+
### CLI
|
|
87
|
+
- `orion` — Interactive menu (9 options)
|
|
88
|
+
- `orion .` — Full audit
|
|
89
|
+
- `orion . --security` — Security engines only
|
|
90
|
+
- `orion . --quality` — Quality engines only
|
|
91
|
+
- `orion . --arch` — Architecture engines only
|
|
92
|
+
- `orion path` — Scan file or directory
|
|
93
|
+
- `orion . --config-json '{}'` — Custom config
|
|
94
|
+
|
|
95
|
+
### Removed
|
|
96
|
+
- All GPL/AGPL dependencies (Semgrep, TruffleHog, Safety, Bandit)
|
|
97
|
+
- External tool subprocess calls
|
|
98
|
+
- Old adapter/check/intelligence/reporting architecture
|
|
99
|
+
- Benchmarks, fixtures, test suites (legacy)
|
|
100
|
+
- Docker, npm, GUI, serve, sandbox modules
|
|
101
|
+
|
|
102
|
+
## Upgrade Guide
|
|
103
|
+
|
|
104
|
+
### From 0.x (Legacy)
|
|
105
|
+
- Complete rewrite — no migration path
|
|
106
|
+
- Install fresh: `pip install -e .`
|
|
107
|
+
- Config format changed — use new `EngineConfig`
|
|
108
|
+
- API changed — use `OrionEngine().run(irs, config)`
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
**Orion Engine v0.1.0** — 38 native MIT engines, polyglot, zero external deps, professional reports.
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
## Development Setup
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
git clone https://github.com/chandrahotha/OrionEngine
|
|
7
|
+
cd OrionEngine
|
|
8
|
+
pip install -e .[dev]
|
|
9
|
+
pre-commit install
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Code Style
|
|
13
|
+
|
|
14
|
+
- **Python 3.10+** — type hints required
|
|
15
|
+
- **Black** — formatting (`black src/`)
|
|
16
|
+
- **Ruff** — linting (`ruff check src/`)
|
|
17
|
+
- **MyPy** — type checking (`mypy src/`)
|
|
18
|
+
- **Async first** — all engines async
|
|
19
|
+
|
|
20
|
+
## Adding a New Engine
|
|
21
|
+
|
|
22
|
+
1. Create directory: `src/orion/engine/my_engine/`
|
|
23
|
+
2. Create `engine.py`:
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
from orion.engine.languages import detect_language, Language, get_capabilities
|
|
27
|
+
from orion.engine.dispatcher import UniversalRegexAnalyzer, PolyglotEngine
|
|
28
|
+
from orion.engine.config import EngineConfig, ResourceLimits
|
|
29
|
+
from orion.engine.ir import OrionIR
|
|
30
|
+
from orion.engine.results import EngineResult, Finding
|
|
31
|
+
|
|
32
|
+
class Engine:
|
|
33
|
+
name = "my_engine"
|
|
34
|
+
version = "1.0.0"
|
|
35
|
+
|
|
36
|
+
def __init__(self):
|
|
37
|
+
self.universal = UniversalRegexAnalyzer(
|
|
38
|
+
categories=["secrets", "sql_injection", "xss", "command_injection"]
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
async def check_availability(self) -> bool:
|
|
42
|
+
return True
|
|
43
|
+
|
|
44
|
+
def resource_limits(self) -> ResourceLimits:
|
|
45
|
+
return ResourceLimits(max_cpu_seconds=60, max_memory_mb=512)
|
|
46
|
+
|
|
47
|
+
async def run(self, ir: OrionIR, config: EngineConfig) -> EngineResult:
|
|
48
|
+
language = ir.metadata.get("language")
|
|
49
|
+
if isinstance(language, str):
|
|
50
|
+
try:
|
|
51
|
+
language = Language(language.lower())
|
|
52
|
+
except ValueError:
|
|
53
|
+
from orion.engine.languages import detect_language
|
|
54
|
+
language = detect_language(ir.metadata.get("path", ""))
|
|
55
|
+
|
|
56
|
+
if language == Language.PYTHON:
|
|
57
|
+
return await self._run_python(ir, config)
|
|
58
|
+
|
|
59
|
+
return self.universal.run(ir, config)
|
|
60
|
+
|
|
61
|
+
async def _run_python(self, ir: OrionIR, config: EngineConfig) -> EngineResult:
|
|
62
|
+
# Python-specific AST analysis
|
|
63
|
+
findings = []
|
|
64
|
+
# ... your analysis
|
|
65
|
+
return EngineResult(engine=self.name, findings=findings, ok=True)
|
|
66
|
+
|
|
67
|
+
# Backward compatibility
|
|
68
|
+
Engine = Engine
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
3. Register in `src/orion/engine/registry.py` (auto-discovery works automatically)
|
|
72
|
+
|
|
73
|
+
## Testing
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# Run all tests
|
|
77
|
+
pytest tests/
|
|
78
|
+
|
|
79
|
+
# Run specific engine tests
|
|
80
|
+
pytest tests/test_sast.py -v
|
|
81
|
+
|
|
82
|
+
# Type check
|
|
83
|
+
mypy src/
|
|
84
|
+
|
|
85
|
+
# Lint
|
|
86
|
+
ruff check src/
|
|
87
|
+
|
|
88
|
+
# Format
|
|
89
|
+
black src/
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Engine Guidelines
|
|
93
|
+
|
|
94
|
+
1. **No silent failures** — wrap in try/except, return errors in `EngineResult.errors`
|
|
95
|
+
2. **Confidence scoring** — every finding needs `metadata["confidence"]` (0.0-1.0)
|
|
96
|
+
3. **Evidence** — include `snippet`, `cwe`, `cvss`, `line`, `file` in metadata
|
|
97
|
+
4. **Language support** — use `detect_language()`, `get_capabilities()`, `UniversalRegexAnalyzer`
|
|
98
|
+
5. **Resource limits** — respect `config.get_limits().max_cpu_seconds`
|
|
99
|
+
5. **No silent failures** — engine errors go to `EngineResult.errors`, not stdout
|
|
100
|
+
6. **Async** — `run()` must be async, use `asyncio.wait_for` for timeouts
|
|
101
|
+
|
|
102
|
+
## Polyglot Support
|
|
103
|
+
|
|
104
|
+
Add language support to your engine:
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
async def run(self, ir: OrionIR, config: EngineConfig) -> EngineResult:
|
|
108
|
+
language = ir.metadata.get("language")
|
|
109
|
+
if isinstance(language, str):
|
|
110
|
+
try:
|
|
111
|
+
language = Language(language.lower())
|
|
112
|
+
except ValueError:
|
|
113
|
+
from orion.engine.languages import detect_language
|
|
114
|
+
language = detect_language(ir.metadata.get("path", ""))
|
|
115
|
+
|
|
116
|
+
caps = get_capabilities(language)
|
|
117
|
+
|
|
118
|
+
if language == Language.PYTHON:
|
|
119
|
+
return await self._run_python_ast(ir, config)
|
|
120
|
+
elif language in (Language.JAVASCRIPT, Language.TYPESCRIPT):
|
|
121
|
+
return await self._run_js_regex(ir, config)
|
|
122
|
+
elif language in (Language.JAVA, Language.GO, Language.RUST, Language.PHP, Language.RUBY):
|
|
123
|
+
return await self._run_universal(ir, config)
|
|
124
|
+
|
|
125
|
+
return self.universal.run(ir, config)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Adding Language Support
|
|
129
|
+
|
|
130
|
+
1. Add to `Language` enum in `languages.py`
|
|
131
|
+
2. Add extension mapping in `EXTENSION_MAP`
|
|
132
|
+
3. Add `LanguageCapabilities` in `LANGUAGE_CAPABILITIES`
|
|
133
|
+
4. Add patterns to `UNIVERSAL_PATTERNS` in `dispatcher.py`
|
|
134
|
+
5. Test with sample files
|
|
135
|
+
|
|
136
|
+
## Reporting Bugs
|
|
137
|
+
|
|
138
|
+
Use GitHub Issues with:
|
|
139
|
+
- Orion version (`orion --version` or check `pyproject.toml`)
|
|
140
|
+
- Python version
|
|
141
|
+
- OS
|
|
142
|
+
- Minimal reproduction code
|
|
143
|
+
- Expected vs actual behavior
|
|
144
|
+
- Engine(s) involved
|
|
145
|
+
|
|
146
|
+
## Pull Request Process
|
|
147
|
+
|
|
148
|
+
1. Fork & create feature branch
|
|
149
|
+
2. Write tests for new functionality
|
|
150
|
+
3. Ensure all tests pass
|
|
151
|
+
4. Run `black`, `ruff`, `mypy`
|
|
152
|
+
5. Update docs if needed
|
|
153
|
+
6. Submit PR with clear description
|
|
154
|
+
|
|
155
|
+
## License
|
|
156
|
+
|
|
157
|
+
MIT — all contributions must be MIT-compatible.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Engine Catalog — 38 Native Engines
|
|
2
|
+
|
|
3
|
+
All engines are **native, MIT-licensed, zero external dependencies**. Each engine routes to the appropriate language analyzer automatically via the Polyglot Dispatcher.
|
|
4
|
+
|
|
5
|
+
## Security Engines (7)
|
|
6
|
+
|
|
7
|
+
| Engine | Description | Primary Languages | Detection Method |
|
|
8
|
+
|--------|-------------|-------------------|------------------|
|
|
9
|
+
| **sast** | Static Application Security Testing — SQLi, XSS, CMDi, SSRF, path traversal, hardcoded creds, weak crypto, deserialization | Python (AST), JS/TS (regex), Universal regex fallback | AST + Regex |
|
|
10
|
+
| **secrets** | API keys, tokens, passwords, private keys — regex + Shannon entropy, test pattern filtering | All text files | Regex + Entropy |
|
|
11
|
+
| **deps** | Vulnerable dependencies — requirements.txt, package.json, Cargo.toml, go.mod, pom.xml, composer.json, Gemfile, Pipfile, poetry.lock, yarn.lock, pnpm-lock.yaml | Python, JS/TS, Go, Rust, Java, PHP, Ruby, .NET | Manifest parsing + CVE DB |
|
|
12
|
+
| **taint** | Taint tracking: user input → dangerous sinks (SQL, shell, code exec, template, deserialization) | Python (AST), JS/TS (planned), Universal fallback | AST + Regex |
|
|
13
|
+
| **authorization** | Missing auth on routes — Flask, FastAPI, Django, Express, Fastify, Spring, Gin, Laravel, Rails, ASP.NET | Python, JS/TS, Java, Go, PHP, Ruby, C# | AST + Regex |
|
|
14
|
+
| **sandbox_escape** | `__import__('os')`, `eval(compile())`, `ctypes`, `__subclasses__()`, `Function` constructor, `Runtime.exec`, `Process.Start` | Python, JS/TS, Java, PHP, Ruby, C# | Regex |
|
|
15
|
+
| **prompt_security** | Prompt injection, jailbreak patterns, base64 payloads, special tokens | All text files | Regex + Heuristics |
|
|
16
|
+
|
|
17
|
+
## AST/IR Analysis Engines (8)
|
|
18
|
+
|
|
19
|
+
| Engine | Description | Languages |
|
|
20
|
+
|--------|-------------|-----------|
|
|
21
|
+
| **callgraph** | Function call graph, recursive calls, undefined functions, deep chains | Python (AST), JS/TS, Java, Go, Rust, PHP, Ruby, C# (regex) |
|
|
22
|
+
| **cfg** | Control flow graph per function — unreachable code, infinite loops, missing returns, cyclomatic complexity | Python (AST), Universal fallback |
|
|
23
|
+
| **symbol** | Symbol table — shadowed builtins, undefined names, unused imports, late-binding closures | Python (AST), Universal fallback |
|
|
24
|
+
| **dataflow** | Variable def/use — use-before-def, dead stores, mutable defaults, global mutations | Python (AST), Universal fallback |
|
|
25
|
+
| **orphan** | Files with zero incoming imports — excludes `__init__.py`, tests, scripts, entry points | Python (AST), JS/TS, Java, Go, Rust, PHP, Ruby (regex) |
|
|
26
|
+
| **dead_import** | Unused imports — tracks Name/Attribute usage across scopes | Python (AST), JS/TS, Java, Go, Rust, PHP, Ruby (regex) |
|
|
27
|
+
| **wiring_trace** | Config wiring — traces from .env/config.yaml/settings.py to usage sites | Python, JS/TS, Java, Go, Rust, PHP, Ruby (config files) |
|
|
28
|
+
| **state** | Mutable state — globals, class attrs, function defaults, `global`/`nonlocal` | Python (AST), Universal fallback |
|
|
29
|
+
|
|
30
|
+
## Quality Engines (7)
|
|
31
|
+
|
|
32
|
+
| Engine | Description | Languages |
|
|
33
|
+
|--------|-------------|-----------|
|
|
34
|
+
| **complexity** | Cyclomatic & cognitive complexity — functions >10/20/50 | Python (AST), Universal regex fallback |
|
|
35
|
+
| **duplication** | Code duplication — sliding window (5 lines), token normalization, SHA256 clustering | Python, JS/TS, Java, Go, Rust, C/C++, C# |
|
|
36
|
+
| **error_handling** | Bare `except:`, `except Exception: pass`, lost causes, `assert` in prod, `sys.exit()` in libs | Python (AST), Universal fallback |
|
|
37
|
+
| **logging_c** | `print()` in prod, PII in logs, missing `getLogger(__name__)`, DEBUG in prod, missing structured logging | Python (AST), Universal fallback |
|
|
38
|
+
| **license** | SPDX headers, GPL/AGPL detection, root LICENSE file, dep license conflicts | All source files |
|
|
39
|
+
| **lint** | Unused vars, undefined names, import order, line length >100, missing docstrings, wildcard imports, `== None`, bare except | Python (AST), Universal fallback |
|
|
40
|
+
| **test_coverage** | Untested public functions, test-only-mocks, no-assertions, long tests, missing conftest.py | Python (AST), Universal fallback |
|
|
41
|
+
|
|
42
|
+
## Config/Infra Engines (7)
|
|
43
|
+
|
|
44
|
+
| Engine | Description | Languages |
|
|
45
|
+
|--------|-------------|-----------|
|
|
46
|
+
| **config_engine** | Config validation — required keys, types, placeholders, secrets in non-.env, duplicates, URLs, emails | YAML, JSON, TOML, .env, .ini, .properties, Python |
|
|
47
|
+
| **chaos** | Chaos resilience — no retry/circuit-breaker/timeout/idempotency, global locks, direct instantiation | Python (AST), Universal fallback |
|
|
48
|
+
| **chaos_config** | Config edge cases — empty/null/negative/huge values, invalid enums, circular refs, long strings | YAML, JSON, TOML, .env, .ini, .properties, Python |
|
|
49
|
+
| **regression** | Monkey patching, dynamic imports, `sys.modules` mutation, `builtins`/`os.environ` mutation, signal/atexit handlers | Python (AST), Universal fallback |
|
|
50
|
+
| **perf_guard** | N+1 queries, O(n²) loops, `list.append` in hot loops, string `+=`, large in-memory loads, missing pagination, sync I/O in async | Python (AST), Universal fallback |
|
|
51
|
+
| **data_residency** | Hardcoded PII — emails, phones, SSN, credit cards (Luhn), IPs, UUIDs, API keys | All text files (regex) |
|
|
52
|
+
| **container** | Dockerfile, docker-compose, K8s YAML, Helm — root user, latest tag, secrets in ENV, privileged, host namespaces, missing healthcheck/read-only/limits | Dockerfile, docker-compose, K8s YAML, Helm values |
|
|
53
|
+
|
|
54
|
+
## Meta/Supply Chain Engines (9)
|
|
55
|
+
|
|
56
|
+
| Engine | Description | Languages |
|
|
57
|
+
|--------|-------------|-----------|
|
|
58
|
+
| **noise** | Suppresses low-confidence + recent changes + high churn, duplicates, generated files | All findings |
|
|
59
|
+
| **hunter** | Cross-engine correlation — SQLi + missing auth = CRITICAL, XSS + missing CSP = HIGH, secret + public repo = CRITICAL | All findings |
|
|
60
|
+
| **supply_chain_sbom** | CycloneDX SBOM — components with purl, hashes, licenses, external references | All dep files |
|
|
61
|
+
| **compliance** | Maps findings to GDPR (Art 25/32/33), PCI-DSS (Req 3/4/6/8), SOC2 (CC6.1/6.7/7.2), HIPAA (164.312) | All findings |
|
|
62
|
+
| **provenance** | SLSA-like — git commit/tag/branch, SHA256 file hashes, builder identity (CI env), dep hashes | Git, all source files |
|
|
63
|
+
| **fp_learn** | Reads `.orion-feedback.json`, extracts features, reduces confidence by 0.3 on match | All findings |
|
|
64
|
+
| **config_validation** | Validates OrionEngine config — paths, globs, limits, network policy, parallelism, timeout | Config object |
|
|
65
|
+
| **architecture** | Cyclic imports, layer violations (domain→app→infra→pres), god classes/modules, feature envy, data classes with behavior | Python (AST), JS/TS, Java, Go, Rust, PHP, Ruby (regex) |
|
|
66
|
+
| **config_validation** | Validates EngineConfig — paths exist, globs valid, limits positive, network policy consistent | Config object |
|
|
67
|
+
|
|
68
|
+
## Language Support Matrix
|
|
69
|
+
|
|
70
|
+
| Language | SAST | Secrets | Deps | Taint | Callgraph | Config | Container |
|
|
71
|
+
|----------|------|---------|------|-------|-----------|--------|-----------|
|
|
72
|
+
| Python | ���� AST | ���� | ���� | ���� AST | ���� AST | ���� | ���� |
|
|
73
|
+
| JavaScript | ���� Regex | ���� | ���� | ���� Regex | ���� Regex | ���� | ���� |
|
|
74
|
+
| TypeScript | ���� Regex | ���� | ���� | ���� Regex | ���� Regex | ���� | ���� |
|
|
75
|
+
| Java | ���� Regex | ���� | ���� | ���� Regex | ���� Regex | ���� | ���� |
|
|
76
|
+
| Go | ���� Regex | ���� | ���� | ���� Regex | ���� Regex | ���� | ���� |
|
|
77
|
+
| Rust | ���� Regex | ���� | ���� | ���� Regex | ���� Regex | ���� | ���� |
|
|
78
|
+
| PHP | ���� Regex | ���� | ���� | ���� Regex | ���� Regex | ���� | ���� |
|
|
79
|
+
| Ruby | ���� Regex | ���� | ���� | ���� Regex | ���� Regex | ���� | ���� |
|
|
80
|
+
| C/C++ | ���� Regex | ���� | ���� | ���� Regex | ���� Regex | ���� | ���� |
|
|
81
|
+
| C# | ���� Regex | ���� | ���� | ���� Regex | ���� Regex | ���� | ���� |
|
|
82
|
+
| HTML | ���� Regex | ���� | ���� | ���� Regex | ���� Regex | ���� | ���� |
|
|
83
|
+
| CSS | ���� | ���� | ���� | ���� | ���� | ���� | ���� |
|
|
84
|
+
| YAML/JSON/TOML | ���� | ���� | ���� | ���� | ���� | ���� | ���� |
|
|
85
|
+
| Dockerfile | ���� Regex | ���� | ���� | ���� Regex | ���� Regex | ���� | ���� |
|
|
86
|
+
|
|
87
|
+
�� = Full AST support | ���� = Regex/Universal fallback | ���� = Not applicable
|