@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,1310 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Orion Engine - Enterprise Code Audit & Security Platform.
|
|
3
|
+
|
|
4
|
+
Proprietary In-House Engines for Security Auditing, Architecture & Governance.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
import base64
|
|
9
|
+
import json
|
|
10
|
+
import sys
|
|
11
|
+
import html
|
|
12
|
+
import itertools
|
|
13
|
+
import os
|
|
14
|
+
import re
|
|
15
|
+
import threading
|
|
16
|
+
import time
|
|
17
|
+
from datetime import datetime
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
|
|
20
|
+
from orion.engine import OrionEngine, EngineConfig, ResourceLimits
|
|
21
|
+
from orion.engine.ir import OrionIR
|
|
22
|
+
from orion.engine.languages import detect_language, is_binary_file, Language
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# Ensure UTF-8 stdout on Windows console
|
|
26
|
+
if sys.platform == "win32":
|
|
27
|
+
try:
|
|
28
|
+
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
|
29
|
+
sys.stderr.reconfigure(encoding="utf-8", errors="replace")
|
|
30
|
+
except Exception:
|
|
31
|
+
pass
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def clear_screen():
|
|
35
|
+
"""Clear terminal screen cross-platform safely without shell execution."""
|
|
36
|
+
sys.stdout.write("\033[H\033[2J")
|
|
37
|
+
sys.stdout.flush()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# --- CLI Terminal Professional Styling Tokens ---
|
|
41
|
+
RESET = "\033[0m"
|
|
42
|
+
BOLD = "\033[1m"
|
|
43
|
+
DIM = "\033[2m"
|
|
44
|
+
ITALIC = "\033[3m"
|
|
45
|
+
UNDERLINE = "\033[4m"
|
|
46
|
+
|
|
47
|
+
RED = "\033[91m"
|
|
48
|
+
GREEN = "\033[92m"
|
|
49
|
+
YELLOW = "\033[93m"
|
|
50
|
+
BLUE = "\033[94m"
|
|
51
|
+
MAGENTA = "\033[95m"
|
|
52
|
+
CYAN = "\033[96m"
|
|
53
|
+
WHITE = "\033[97m"
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
BANNER = f"""{CYAN}{BOLD}
|
|
57
|
+
┌───────────────────────────────────────────────────────────────────────────────────┐
|
|
58
|
+
│ ___ ____ _____ ____ _ __ {WHITE}{BOLD}ORION SECURITY SUITE{CYAN} │
|
|
59
|
+
│ / __ \\/ __ \\/ _/ __ \\/ | / / {DIM}Code Intelligence & Governance{CYAN} │
|
|
60
|
+
│ / / / / /_/ // // / / / |/ / {CYAN}─── {WHITE}{BOLD}SEE. ANALYZE. IMPROVE.{RESET}{CYAN} ──────────────── │
|
|
61
|
+
│/ /_/ / _, _// // /_/ / /| / │
|
|
62
|
+
│\\____/_/ |_/___/\\____/_/ |_/ {DIM}SAST & Threat Modeling{CYAN} │
|
|
63
|
+
└───────────────────────────────────────────────────────────────────────────────────┘{RESET}
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
MENU = f"""
|
|
67
|
+
{WHITE}{BOLD}AUDIT WORKSPACE EXECUTION{RESET}
|
|
68
|
+
{CYAN}─────────────────────────────────────────────────────────────────────────────────────{RESET}
|
|
69
|
+
{GREEN}{BOLD}[1]{RESET} {WHITE}{BOLD}Quick Workspace Audit{RESET} {DIM}Fast multi-engine scan on current workspace{RESET}
|
|
70
|
+
{GREEN}{BOLD}[2]{RESET} {WHITE}{BOLD}Full Deep Security Audit{RESET} {DIM}Comprehensive SAST, Secrets, Cloud, AI & Quality sweep{RESET}
|
|
71
|
+
|
|
72
|
+
{WHITE}{BOLD}SPECIALIZED SECURITY & COMPLIANCE SWEEPS{RESET}
|
|
73
|
+
{CYAN}─────────────────────────────────────────────────────────────────────────────────────{RESET}
|
|
74
|
+
{CYAN}{BOLD}[3]{RESET} {WHITE}Application Security & SAST{RESET} {DIM}DeepSAST™, SecretShield™, TaintStream™, AuthMatrix™{RESET}
|
|
75
|
+
{CYAN}{BOLD}[4]{RESET} {WHITE}Cloud, Container & IaC{RESET} {DIM}CloudPulse™, DockerAudit™, PolicyForge™, CloudConfig™{RESET}
|
|
76
|
+
{CYAN}{BOLD}[5]{RESET} {WHITE}AI & LLM Agent Security{RESET} {DIM}PromptArmor™, AgentShield™ (OWASP LLM Top 10){RESET}
|
|
77
|
+
{CYAN}{BOLD}[6]{RESET} {WHITE}Cryptography & Key Vault{RESET} {DIM}CryptoFortress™, SecretShield™ (Weak Ciphers & Keys){RESET}
|
|
78
|
+
{CYAN}{BOLD}[7]{RESET} {WHITE}Code Quality & Standards{RESET} {DIM}CognitivePulse™, CloneMatrix™, CleanSweep™, CodeStandard™{RESET}
|
|
79
|
+
{CYAN}{BOLD}[8]{RESET} {WHITE}Supply Chain & SBOM{RESET} {DIM}SupplyGuard™, VulnPulse™, LicenseAudit™, ReguGuard™{RESET}
|
|
80
|
+
{CYAN}{BOLD}[9]{RESET} {WHITE}Threat Model & Data Privacy{RESET} {DIM}ThreatPulse™ (STRIDE), PrivacyShield™ (PII / PCI-DSS){RESET}
|
|
81
|
+
|
|
82
|
+
{WHITE}{BOLD}REPORTING & SYSTEM STATUS{RESET}
|
|
83
|
+
{CYAN}─────────────────────────────────────────────────────────────────────────────────────{RESET}
|
|
84
|
+
{YELLOW}{BOLD}[R]{RESET} {WHITE}View Latest Report{RESET} {DIM}Open latest executive report with PDF export{RESET}
|
|
85
|
+
{YELLOW}{BOLD}[S]{RESET} {WHITE}Engine Health Matrix{RESET} {DIM}Inspect status and specifications of in-house engines{RESET}
|
|
86
|
+
{RED}{BOLD}[0]{RESET} {WHITE}Exit Orion Suite{RESET} {DIM}Terminate CLI session{RESET}
|
|
87
|
+
{CYAN}─────────────────────────────────────────────────────────────────────────────────────{RESET}
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
ENGINE_MARKETING_METADATA = {
|
|
92
|
+
# 1. Advanced Application Security & SAST
|
|
93
|
+
"sast": {"name": "DeepSAST™", "title": "Core Semantic Vulnerability Analyzer", "cat": "Application Security", "desc": "Next-Gen AST Code & Injection Defense"},
|
|
94
|
+
"taint": {"name": "TaintStream™", "title": "Source-to-Sink Dataflow Tracer", "cat": "Application Security", "desc": "Unsanitized Input & Injection Vector Tracker"},
|
|
95
|
+
"secrets": {"name": "SecretShield™", "title": "Credential & Token Vault", "cat": "Application Security", "desc": "Zero-Entropy Secret & Key Leak Detection"},
|
|
96
|
+
"authorization": {"name": "AuthMatrix™", "title": "Access Control & Privilege Guard", "cat": "Application Security", "desc": "RBAC / ABAC Broken Authorization Defense"},
|
|
97
|
+
"sandbox_escape": {"name": "ContainerBreak™", "title": "Sandbox & Isolation Auditor", "cat": "Application Security", "desc": "Subprocess & Jailbreak Prevention"},
|
|
98
|
+
"hunter": {"name": "ThreatHunter™", "title": "Zero-Day Vulnerability Hunter", "cat": "Application Security", "desc": "Proactive Exploit & Risk Vector Discovery"},
|
|
99
|
+
|
|
100
|
+
# 2. AI, LLM & Emerging Threat Defense
|
|
101
|
+
"prompt_security": {"name": "PromptArmor™", "title": "AI Guardrails & Jailbreak Shield", "cat": "AI & Emerging Threats", "desc": "Indirect Injection & Context Hijack Protection"},
|
|
102
|
+
"llm_security": {"name": "AgentShield™", "title": "OWASP LLM Top 10 Sentinel", "cat": "AI & Emerging Threats", "desc": "Autonomous Agency & Unsafe Execution Defense"},
|
|
103
|
+
"crypto_guard": {"name": "CryptoFortress™", "title": "Quantum-Ready Cipher Auditor", "cat": "AI & Emerging Threats", "desc": "Weak Cryptography & Broken Hash Detector"},
|
|
104
|
+
"api_security": {"name": "APIGuard™", "title": "Microservice & REST Security Sentry", "cat": "AI & Emerging Threats", "desc": "OWASP API Top 10 & BOLA/IDOR Defense"},
|
|
105
|
+
|
|
106
|
+
# 3. Cloud, Infrastructure & Container Governance
|
|
107
|
+
"iac_security": {"name": "CloudPulse™", "title": "Infrastructure-as-Code Sentinel", "cat": "Cloud & Infrastructure", "desc": "Terraform, Kubernetes & CI/CD Hardener"},
|
|
108
|
+
"container": {"name": "DockerAudit™", "title": "Image & Namespace Security Engine", "cat": "Cloud & Infrastructure", "desc": "Privilege Escalation & Manifest Scanner"},
|
|
109
|
+
"config_engine": {"name": "CloudConfig™", "title": "Environment & Secrets Validator", "cat": "Cloud & Infrastructure", "desc": "Production Settings & Env Hygiene"},
|
|
110
|
+
"config_validation": {"name": "PolicyForge™", "title": "Configuration Governance Engine", "cat": "Cloud & Infrastructure", "desc": "Schema & Setting Integrity Assurance"},
|
|
111
|
+
"chaos": {"name": "ChaosEngine™", "title": "Resilience & Fault Prober", "cat": "Cloud & Infrastructure", "desc": "Runtime Failure & Latency Simulation"},
|
|
112
|
+
"chaos_config": {"name": "ConfigChaos™", "title": "Stress & Edge-Case Validator", "cat": "Cloud & Infrastructure", "desc": "Configuration Fault Tolerance Testing"},
|
|
113
|
+
|
|
114
|
+
# 4. Supply Chain, Compliance & Legal Protection
|
|
115
|
+
"supply_chain_sbom": {"name": "SupplyGuard™", "title": "Enterprise SBOM Matrix Generator", "cat": "Supply Chain & Compliance", "desc": "CycloneDX/SPDX Inventory Assurance"},
|
|
116
|
+
"deps": {"name": "VulnPulse™", "title": "Real-Time Dependency CVE Scanner", "cat": "Supply Chain & Compliance", "desc": "Outdated & Compromised Package Detection"},
|
|
117
|
+
"license": {"name": "LicenseAudit™", "title": "Open-Source IP & Legal Compliance", "cat": "Supply Chain & Compliance", "desc": "GPL/Copyleft Risk Mitigation"},
|
|
118
|
+
"provenance": {"name": "ChainOfCustody™", "title": "Artifact Provenance Tracker", "cat": "Supply Chain & Compliance", "desc": "Build Integrity & Tamper Proofing"},
|
|
119
|
+
"compliance": {"name": "ReguGuard™", "title": "Multi-Standard Compliance Auditor", "cat": "Supply Chain & Compliance", "desc": "SOC 2, ISO 27001, HIPAA & PCI-DSS Audit"},
|
|
120
|
+
"data_residency": {"name": "GeoFence™", "title": "Data Sovereignty & Privacy Guard", "cat": "Supply Chain & Compliance", "desc": "GDPR, CCPA & Cross-Border Residency"},
|
|
121
|
+
"threat_model": {"name": "ThreatPulse™", "title": "Automated STRIDE & Boundary Model", "cat": "Supply Chain & Compliance", "desc": "Trust-Boundary Crossing & Entrypoint Risk Mapper"},
|
|
122
|
+
"sensitive_data": {"name": "PrivacyShield™", "title": "PII, GDPR, HIPAA & PCI-DSS Shield", "cat": "Supply Chain & Compliance", "desc": "Credit Card PAN, SSN & Cleartext PII Leak Sentry"},
|
|
123
|
+
|
|
124
|
+
# 5. Architectural Intelligence & Deep Flow Analysis
|
|
125
|
+
"callgraph": {"name": "GraphTrace™", "title": "Inter-Procedural Call Topology", "cat": "Architecture & Dataflow", "desc": "Deep Function Call & Callpath Mapper"},
|
|
126
|
+
"cfg": {"name": "ControlFlow™", "title": "Path Traversal & Reachability Engine", "cat": "Architecture & Dataflow", "desc": "Deadlock & Branch Reachability Analyzer"},
|
|
127
|
+
"dataflow": {"name": "DataFlow™", "title": "Global State & Variable Propagation", "cat": "Architecture & Dataflow", "desc": "Data Mutation & Side-Effect Engine"},
|
|
128
|
+
"symbol": {"name": "SymbolMatrix™", "title": "Cross-Module Symbol Table Engine", "cat": "Architecture & Dataflow", "desc": "Identifier Scope & Type Hierarchy"},
|
|
129
|
+
"architecture": {"name": "ArchPulse™", "title": "Structural Boundary & Layering Auditor", "cat": "Architecture & Dataflow", "desc": "Spaghetti Code & Circular Coupling Detector"},
|
|
130
|
+
"wiring_trace": {"name": "WiringTrace™", "title": "Service Bus & Pipeline Wire Tracer", "cat": "Architecture & Dataflow", "desc": "Component Interconnection Tracker"},
|
|
131
|
+
"state": {"name": "StateGuard™", "title": "Finite State & Race-Condition Detector", "cat": "Architecture & Dataflow", "desc": "Concurrency & Mutex Auditor"},
|
|
132
|
+
"contract_probe": {"name": "ContractProbe™", "title": "Microservice SLA & Interface Auditor", "cat": "Architecture & Dataflow", "desc": "HTTP Resiliency & Circuit Breaker Check"},
|
|
133
|
+
"orphan": {"name": "GhostCode™", "title": "Orphaned Endpoint & Asset Finder", "cat": "Architecture & Dataflow", "desc": "Zombie Routes & Unreachable Assets"},
|
|
134
|
+
|
|
135
|
+
# 6. Code Quality, Performance & Engineering Excellence
|
|
136
|
+
"complexity": {"name": "CognitivePulse™", "title": "Cyclomatic & Complexity Optimizer", "cat": "Quality & Performance", "desc": "Maintainability Index & Tech Debt Score"},
|
|
137
|
+
"duplication": {"name": "CloneMatrix™", "title": "Semantic Duplication Detector", "cat": "Quality & Performance", "desc": "Anti-Copy-Paste Refactoring Engine"},
|
|
138
|
+
"dead_import": {"name": "CleanSweep™", "title": "Dead Import & Dead Code Eliminator", "cat": "Quality & Performance", "desc": "Tree-Shaking & Bundle Optimizer"},
|
|
139
|
+
"error_handling": {"name": "ResilienceGuard™", "title": "Exception & Fault-Tolerance Auditor", "cat": "Quality & Performance", "desc": "Silent Error & Crash Prevention"},
|
|
140
|
+
"logging_c": {"name": "AuditLog™", "title": "Enterprise Telemetry & Audit Verifier", "cat": "Quality & Performance", "desc": "Compliance Logging & Redaction Engine"},
|
|
141
|
+
"lint": {"name": "CodeStandard™", "title": "Multi-Language Style Guardian", "cat": "Quality & Performance", "desc": "PEP8, Google & Enterprise Clean Code Enforcer"},
|
|
142
|
+
"test_coverage": {"name": "CoverageLens™", "title": "Test Gap & QA Inspector", "cat": "Quality & Performance", "desc": "Untested Path & Mutation Discovery"},
|
|
143
|
+
"perf_guard": {"name": "SpeedGuard™", "title": "Algorithmic & I/O Optimizer", "cat": "Quality & Performance", "desc": "Big-O & Memory Overhead Detector"},
|
|
144
|
+
"regression": {"name": "RegressionShield™", "title": "Semantic Differential Analyzer", "cat": "Quality & Performance", "desc": "Behavioral Drift & Regression Radar"},
|
|
145
|
+
"noise": {"name": "SignalFilter™", "title": "False-Positive Signal Amplifier", "cat": "Quality & Performance", "desc": "High-Fidelity Signal Processing"},
|
|
146
|
+
"fp_learn": {"name": "SmartLearn™", "title": "Adaptive Heuristics Feedback Loop", "cat": "Quality & Performance", "desc": "Continuous Learning False-Positive Reducer"},
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
SUPPORTED_EXTENSIONS = {
|
|
150
|
+
".py", ".pyw", ".js", ".jsx", ".mjs", ".cjs", ".ts", ".tsx",
|
|
151
|
+
".go", ".rs", ".java", ".c", ".cpp", ".cc", ".cxx", ".h", ".hpp",
|
|
152
|
+
".cs", ".php", ".phtml", ".rb", ".swift", ".kt", ".kts", ".scala",
|
|
153
|
+
".sql", ".html", ".htm", ".css", ".scss", ".json", ".yaml", ".yml",
|
|
154
|
+
".toml", ".xml", ".ini", ".cfg", ".conf", ".properties", ".env",
|
|
155
|
+
".tf", ".hcl", ".sh", ".bash", ".zsh", ".ps1", ".psm1", ".md"
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
SPECIAL_FILENAMES = {
|
|
159
|
+
"dockerfile", "docker-compose.yml", "docker-compose.yaml", "makefile",
|
|
160
|
+
"cmakelists.txt", "package.json", "go.mod", "cargo.toml", "pom.xml",
|
|
161
|
+
"requirements.txt", "pyproject.toml", "gemfile", "composer.json"
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
REPORTS_DIR = Path("ORION SCANNER REPORTS")
|
|
166
|
+
REPORTS_DIR.mkdir(exist_ok=True)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def get_logo_base64() -> str:
|
|
170
|
+
"""Read assets/logo.png and return base64 data URI for self-contained report header."""
|
|
171
|
+
candidates = [
|
|
172
|
+
Path("assets/logo.png"),
|
|
173
|
+
Path(__file__).resolve().parent.parent.parent.parent / "assets" / "logo.png",
|
|
174
|
+
Path("D:/Homeworks/Orion_Engine/assets/logo.png")
|
|
175
|
+
]
|
|
176
|
+
for p in candidates:
|
|
177
|
+
if p.exists():
|
|
178
|
+
try:
|
|
179
|
+
b64 = base64.b64encode(p.read_bytes()).decode("utf-8")
|
|
180
|
+
return f"data:image/png;base64,{b64}"
|
|
181
|
+
except Exception:
|
|
182
|
+
pass
|
|
183
|
+
return ""
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def purge_old_reports():
|
|
187
|
+
"""Remove previous reports and any nested subdirectories so only latest files exist."""
|
|
188
|
+
import shutil
|
|
189
|
+
try:
|
|
190
|
+
for item in REPORTS_DIR.iterdir():
|
|
191
|
+
try:
|
|
192
|
+
if item.is_dir():
|
|
193
|
+
shutil.rmtree(item, ignore_errors=True)
|
|
194
|
+
else:
|
|
195
|
+
item.unlink()
|
|
196
|
+
except Exception:
|
|
197
|
+
pass
|
|
198
|
+
except Exception:
|
|
199
|
+
pass
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def deduplicate_and_filter_findings(findings):
|
|
203
|
+
"""Intelligent cross-engine deduplication and false-positive suppression."""
|
|
204
|
+
seen = {}
|
|
205
|
+
normalized = []
|
|
206
|
+
|
|
207
|
+
for f in findings:
|
|
208
|
+
loc = f.location or ""
|
|
209
|
+
sev = f.severity.lower()
|
|
210
|
+
title_lower = f.title.lower()
|
|
211
|
+
|
|
212
|
+
cat = "general"
|
|
213
|
+
if "eval" in title_lower or "code injection" in title_lower:
|
|
214
|
+
cat = "code_injection"
|
|
215
|
+
elif "password" in title_lower or "secret" in title_lower or "token" in title_lower or "key" in title_lower:
|
|
216
|
+
cat = "secrets"
|
|
217
|
+
elif "sandbox" in title_lower or "escape" in title_lower or "subprocess" in title_lower:
|
|
218
|
+
cat = "sandbox_escape"
|
|
219
|
+
elif "jwt" in title_lower:
|
|
220
|
+
cat = "jwt"
|
|
221
|
+
elif "license" in title_lower or "gpl" in title_lower:
|
|
222
|
+
cat = "license"
|
|
223
|
+
elif "undefined name" in title_lower:
|
|
224
|
+
cat = "undefined_symbol"
|
|
225
|
+
elif "dead store" in title_lower:
|
|
226
|
+
cat = "dead_store"
|
|
227
|
+
elif "mutable" in title_lower:
|
|
228
|
+
cat = "mutable"
|
|
229
|
+
|
|
230
|
+
key = f"{loc}:{cat}"
|
|
231
|
+
|
|
232
|
+
if key in seen:
|
|
233
|
+
existing = seen[key]
|
|
234
|
+
contribs = existing.metadata.get("contributing_engines", [existing.engine])
|
|
235
|
+
if f.engine not in contribs:
|
|
236
|
+
contribs.append(f.engine)
|
|
237
|
+
existing.metadata["contributing_engines"] = contribs
|
|
238
|
+
continue
|
|
239
|
+
|
|
240
|
+
if "dead store" in title_lower and loc.startswith("src"):
|
|
241
|
+
continue
|
|
242
|
+
if "module-level mutable variable" in title_lower and any(k in loc for k in ["engine.py", "config.py", "registry.py"]):
|
|
243
|
+
continue
|
|
244
|
+
|
|
245
|
+
f.metadata["contributing_engines"] = [f.engine]
|
|
246
|
+
seen[key] = f
|
|
247
|
+
normalized.append(f)
|
|
248
|
+
|
|
249
|
+
return normalized
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
async def scan_path(target_path: str, config: EngineConfig, engine_filter: list = None):
|
|
253
|
+
"""Scan a file or directory across all supported languages with clean steady terminal feedback."""
|
|
254
|
+
target = Path(target_path)
|
|
255
|
+
|
|
256
|
+
if not target.exists():
|
|
257
|
+
print(f"\n {RED}✖ Error: Target workspace path '{target_path}' does not exist.{RESET}\n")
|
|
258
|
+
return None
|
|
259
|
+
|
|
260
|
+
files = []
|
|
261
|
+
if target.is_file():
|
|
262
|
+
files = [target]
|
|
263
|
+
else:
|
|
264
|
+
exclude_dirs = {
|
|
265
|
+
"__pycache__", ".git", ".venv", "venv", "env", "node_modules",
|
|
266
|
+
"dist", "build", ".pytest_cache", ".mypy_cache", ".tox",
|
|
267
|
+
"vendor", ".github", ".idea", ".vscode", "target", "bin", "obj",
|
|
268
|
+
"orion scanner reports", "reports", "brain", ".system_generated"
|
|
269
|
+
}
|
|
270
|
+
for root, dirs, filenames in os.walk(target):
|
|
271
|
+
dirs[:] = [d for d in dirs if d.lower() not in exclude_dirs and not d.startswith(".")]
|
|
272
|
+
for filename in filenames:
|
|
273
|
+
file_path = Path(root) / filename
|
|
274
|
+
ext = file_path.suffix.lower()
|
|
275
|
+
name_lower = filename.lower()
|
|
276
|
+
if ext in SUPPORTED_EXTENSIONS or name_lower in SPECIAL_FILENAMES or name_lower.startswith(".env"):
|
|
277
|
+
if not is_binary_file(str(file_path)):
|
|
278
|
+
files.append(file_path)
|
|
279
|
+
|
|
280
|
+
total_files = len(files)
|
|
281
|
+
print(f"\n {CYAN}{BOLD}▶ Orion Engine Suite initialized{RESET}")
|
|
282
|
+
print(f" {DIM}Target Workspace:{RESET} {WHITE}{Path(target_path).resolve()}{RESET}")
|
|
283
|
+
print(f" {DIM}Identified Files:{RESET} {WHITE}{total_files} source files across supported languages{RESET}\n")
|
|
284
|
+
|
|
285
|
+
print(f" {CYAN}ℹ [Phase 1/3] Indexing workspace ASTs and generating IR models...{RESET}")
|
|
286
|
+
irs = []
|
|
287
|
+
for f in files:
|
|
288
|
+
try:
|
|
289
|
+
content = f.read_bytes()
|
|
290
|
+
rel_path = f.relative_to(target) if target.is_dir() else f.name
|
|
291
|
+
detected_lang = detect_language(str(f))
|
|
292
|
+
irs.append(OrionIR(
|
|
293
|
+
content=content,
|
|
294
|
+
metadata={
|
|
295
|
+
"path": str(rel_path),
|
|
296
|
+
"language": detected_lang.value if hasattr(detected_lang, "value") else str(detected_lang),
|
|
297
|
+
"project_root": str(target)
|
|
298
|
+
}
|
|
299
|
+
))
|
|
300
|
+
except Exception:
|
|
301
|
+
pass
|
|
302
|
+
|
|
303
|
+
engine = OrionEngine()
|
|
304
|
+
if engine_filter:
|
|
305
|
+
original_engines = dict(engine._engines)
|
|
306
|
+
engine._engines = {k: v for k, v in engine._engines.items() if k in engine_filter}
|
|
307
|
+
|
|
308
|
+
print(f" {CYAN}ℹ [Phase 2/3] Executing in-house proprietary analysis engines across IR graph...{RESET}")
|
|
309
|
+
raw_result = await engine.run(irs, config or EngineConfig())
|
|
310
|
+
|
|
311
|
+
if engine_filter:
|
|
312
|
+
engine._engines = original_engines
|
|
313
|
+
|
|
314
|
+
print(f" {CYAN}ℹ [Phase 3/3] Deduplicating findings and generating executive intelligence report...{RESET}")
|
|
315
|
+
clean_findings = deduplicate_and_filter_findings(raw_result.findings)
|
|
316
|
+
raw_result.findings = clean_findings
|
|
317
|
+
|
|
318
|
+
print(f" {GREEN}{BOLD}✔ Engine Analysis Complete:{RESET} {len(clean_findings)} validated findings across {total_files} files ({raw_result.metrics.get('elapsed_s', 0):.2f}s)\n")
|
|
319
|
+
|
|
320
|
+
return raw_result
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
def generate_reports(scan_type: str, target_path: str, result):
|
|
324
|
+
"""Generate state-of-the-art Executive HTML report, JSON, and TXT outputs."""
|
|
325
|
+
purge_old_reports()
|
|
326
|
+
|
|
327
|
+
base_name = "orion_executive_security_report"
|
|
328
|
+
html_path = REPORTS_DIR / f"{base_name}.html"
|
|
329
|
+
json_path = REPORTS_DIR / f"{base_name}.json"
|
|
330
|
+
txt_path = REPORTS_DIR / f"{base_name}.txt"
|
|
331
|
+
|
|
332
|
+
logo_data_uri = get_logo_base64()
|
|
333
|
+
|
|
334
|
+
total = len(result.findings)
|
|
335
|
+
critical = sum(1 for f in result.findings if f.severity == "critical")
|
|
336
|
+
high = sum(1 for f in result.findings if f.severity == "high")
|
|
337
|
+
medium = sum(1 for f in result.findings if f.severity == "medium")
|
|
338
|
+
low = sum(1 for f in result.findings if f.severity == "low")
|
|
339
|
+
info = sum(1 for f in result.findings if f.severity == "info")
|
|
340
|
+
|
|
341
|
+
score = 100
|
|
342
|
+
score -= critical * 15
|
|
343
|
+
score -= high * 8
|
|
344
|
+
score -= medium * 3
|
|
345
|
+
score -= low * 1
|
|
346
|
+
score = max(0, score)
|
|
347
|
+
|
|
348
|
+
if score >= 90: grade = "A"
|
|
349
|
+
elif score >= 75: grade = "B"
|
|
350
|
+
elif score >= 60: grade = "C"
|
|
351
|
+
else: grade = "F"
|
|
352
|
+
|
|
353
|
+
grade_colors = {"A": "#10b981", "B": "#84cc16", "C": "#eab308", "F": "#ef4444"}
|
|
354
|
+
grade_color = grade_colors[grade]
|
|
355
|
+
|
|
356
|
+
# JSON Report
|
|
357
|
+
json_report = {
|
|
358
|
+
"engine": "Orion Security Suite",
|
|
359
|
+
"version": "0.1.0",
|
|
360
|
+
"scan_type": scan_type,
|
|
361
|
+
"target_path": str(Path(target_path).resolve()),
|
|
362
|
+
"timestamp": datetime.now().isoformat(),
|
|
363
|
+
"security_score": score,
|
|
364
|
+
"security_grade": grade,
|
|
365
|
+
"summary": {
|
|
366
|
+
"files_scanned": result.metrics.get('files_scanned', 0),
|
|
367
|
+
"engines_executed": result.metrics.get('engines_run', 0),
|
|
368
|
+
"elapsed_seconds": result.metrics.get('elapsed_s', 0),
|
|
369
|
+
"total_findings": total,
|
|
370
|
+
"critical_count": critical,
|
|
371
|
+
"high_count": high,
|
|
372
|
+
"medium_count": medium,
|
|
373
|
+
"low_count": low,
|
|
374
|
+
"info_count": info,
|
|
375
|
+
},
|
|
376
|
+
"findings": [
|
|
377
|
+
{
|
|
378
|
+
"engine_code": f.engine,
|
|
379
|
+
"engine_product": ENGINE_MARKETING_METADATA.get(f.engine, {}).get("name", f.engine),
|
|
380
|
+
"contributing_engines": f.metadata.get("contributing_engines", [f.engine]),
|
|
381
|
+
"severity": f.severity,
|
|
382
|
+
"title": f.title,
|
|
383
|
+
"description": f.description,
|
|
384
|
+
"location": f.location,
|
|
385
|
+
"metadata": f.metadata
|
|
386
|
+
}
|
|
387
|
+
for f in result.findings
|
|
388
|
+
]
|
|
389
|
+
}
|
|
390
|
+
with open(json_path, 'w', encoding='utf-8') as f:
|
|
391
|
+
json.dump(json_report, f, indent=2, default=str)
|
|
392
|
+
|
|
393
|
+
# TXT Report
|
|
394
|
+
with open(txt_path, 'w', encoding='utf-8') as fh:
|
|
395
|
+
fh.write(f"================================================================================\n")
|
|
396
|
+
fh.write(f" ORION ENGINE SECURITY AUDIT REPORT\n")
|
|
397
|
+
fh.write(f"================================================================================\n")
|
|
398
|
+
fh.write(f"Scan Type: {scan_type}\n")
|
|
399
|
+
fh.write(f"Target Path: {Path(target_path).resolve()}\n")
|
|
400
|
+
fh.write(f"Generated At: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
|
|
401
|
+
fh.write(f"Security Grade: {grade} (Score: {score}/100)\n")
|
|
402
|
+
fh.write(f"Files Scanned: {result.metrics.get('files_scanned', 0)}\n")
|
|
403
|
+
fh.write(f"Engines Run: {result.metrics.get('engines_run', 0)} passes\n")
|
|
404
|
+
fh.write(f"Time Elapsed: {result.metrics.get('elapsed_s', 0):.2f}s\n")
|
|
405
|
+
fh.write(f"Total Findings: {total} (Critical: {critical}, High: {high}, Medium: {medium}, Low: {low})\n")
|
|
406
|
+
fh.write(f"================================================================================\n\n")
|
|
407
|
+
|
|
408
|
+
severity_order = {"critical": 0, "high": 1, "medium": 2, "low": 3, "info": 4}
|
|
409
|
+
sorted_findings = sorted(result.findings, key=lambda f: severity_order.get(f.severity, 5))
|
|
410
|
+
|
|
411
|
+
from collections import defaultdict
|
|
412
|
+
by_severity = defaultdict(list)
|
|
413
|
+
for finding in sorted_findings:
|
|
414
|
+
by_severity[finding.severity].append(finding)
|
|
415
|
+
|
|
416
|
+
for sev in ["critical", "high", "medium", "low", "info"]:
|
|
417
|
+
if sev not in by_severity:
|
|
418
|
+
continue
|
|
419
|
+
fh.write(f"\n[{sev.upper()}] ({len(by_severity[sev])} issues)\n")
|
|
420
|
+
fh.write(f"{'-'*60}\n")
|
|
421
|
+
for finding in by_severity[sev]:
|
|
422
|
+
cwe = finding.metadata.get("cwe", "")
|
|
423
|
+
cwe_str = f" [{cwe}]" if cwe else ""
|
|
424
|
+
conf = finding.metadata.get("confidence", "N/A")
|
|
425
|
+
m_meta = ENGINE_MARKETING_METADATA.get(finding.engine, {})
|
|
426
|
+
eng_label = f"{m_meta.get('name', finding.engine)} ({finding.engine})"
|
|
427
|
+
fh.write(f" * {finding.title}{cwe_str}\n")
|
|
428
|
+
fh.write(f" Engine: {eng_label}\n")
|
|
429
|
+
fh.write(f" Location: {finding.location} (Confidence: {conf})\n")
|
|
430
|
+
if finding.description:
|
|
431
|
+
fh.write(f" Details: {finding.description}\n")
|
|
432
|
+
fh.write("\n")
|
|
433
|
+
|
|
434
|
+
# Executive HTML Report
|
|
435
|
+
with open(html_path, 'w', encoding='utf-8') as f:
|
|
436
|
+
f.write(f"""<!DOCTYPE html>
|
|
437
|
+
<html lang="en">
|
|
438
|
+
<head>
|
|
439
|
+
<meta charset="UTF-8">
|
|
440
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
441
|
+
<title>Orion Executive Security Report - {html.escape(Path(target_path).name or 'Workspace')}</title>
|
|
442
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
443
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
444
|
+
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
445
|
+
<style>
|
|
446
|
+
:root {{
|
|
447
|
+
--bg-base: #06090e;
|
|
448
|
+
--bg-surface: #0c121e;
|
|
449
|
+
--bg-card: rgba(18, 26, 43, 0.85);
|
|
450
|
+
--border: rgba(255, 255, 255, 0.08);
|
|
451
|
+
--border-hover: rgba(99, 102, 241, 0.4);
|
|
452
|
+
--text-primary: #f8fafc;
|
|
453
|
+
--text-secondary: #94a3b8;
|
|
454
|
+
--text-tertiary: #64748b;
|
|
455
|
+
--critical: #ef4444;
|
|
456
|
+
--high: #f97316;
|
|
457
|
+
--medium: #eab308;
|
|
458
|
+
--low: #10b981;
|
|
459
|
+
--info: #38bdf8;
|
|
460
|
+
--accent: #6366f1;
|
|
461
|
+
--accent-gradient: linear-gradient(135deg, #6366f1, #8b5cf6, #d946ef);
|
|
462
|
+
}}
|
|
463
|
+
* {{ box-sizing: border-box; margin: 0; padding: 0; }}
|
|
464
|
+
body {{
|
|
465
|
+
font-family: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif;
|
|
466
|
+
background: var(--bg-base);
|
|
467
|
+
color: var(--text-primary);
|
|
468
|
+
line-height: 1.6;
|
|
469
|
+
min-height: 100vh;
|
|
470
|
+
position: relative;
|
|
471
|
+
}}
|
|
472
|
+
|
|
473
|
+
@media print {{
|
|
474
|
+
body {{
|
|
475
|
+
background: #ffffff !important;
|
|
476
|
+
color: #0f172a !important;
|
|
477
|
+
font-size: 9.5pt;
|
|
478
|
+
}}
|
|
479
|
+
.no-print, .action-toolbar, .search-bar, .filter-pills, .footer-bar {{
|
|
480
|
+
display: none !important;
|
|
481
|
+
}}
|
|
482
|
+
.container {{
|
|
483
|
+
max-width: 100% !important;
|
|
484
|
+
padding: 0 !important;
|
|
485
|
+
position: relative;
|
|
486
|
+
z-index: 1;
|
|
487
|
+
}}
|
|
488
|
+
.executive-banner {{
|
|
489
|
+
background: #f8fafc !important;
|
|
490
|
+
border: 2px solid #cbd5e1 !important;
|
|
491
|
+
color: #0f172a !important;
|
|
492
|
+
box-shadow: none !important;
|
|
493
|
+
page-break-after: avoid;
|
|
494
|
+
}}
|
|
495
|
+
.executive-banner h1, .executive-banner p {{ color: #0f172a !important; }}
|
|
496
|
+
.grade-card {{
|
|
497
|
+
background: #ffffff !important;
|
|
498
|
+
border: 1px solid #cbd5e1 !important;
|
|
499
|
+
}}
|
|
500
|
+
.kpi-card {{
|
|
501
|
+
background: #f8fafc !important;
|
|
502
|
+
border: 1px solid #cbd5e1 !important;
|
|
503
|
+
color: #0f172a !important;
|
|
504
|
+
}}
|
|
505
|
+
.kpi-value {{ color: #0f172a !important; }}
|
|
506
|
+
.finding-card {{
|
|
507
|
+
background: #ffffff !important;
|
|
508
|
+
border: 1px solid #cbd5e1 !important;
|
|
509
|
+
color: #0f172a !important;
|
|
510
|
+
page-break-inside: avoid !important;
|
|
511
|
+
break-inside: avoid !important;
|
|
512
|
+
margin-bottom: 12pt !important;
|
|
513
|
+
}}
|
|
514
|
+
.finding-card-title {{ color: #0f172a !important; }}
|
|
515
|
+
.finding-body {{ display: block !important; }}
|
|
516
|
+
.code-snippet {{
|
|
517
|
+
background: #f1f5f9 !important;
|
|
518
|
+
color: #0f172a !important;
|
|
519
|
+
border: 1px solid #cbd5e1 !important;
|
|
520
|
+
}}
|
|
521
|
+
}}
|
|
522
|
+
|
|
523
|
+
.container {{
|
|
524
|
+
max-width: 1380px;
|
|
525
|
+
margin: 0 auto;
|
|
526
|
+
padding: 36px 32px 80px;
|
|
527
|
+
position: relative;
|
|
528
|
+
z-index: 1;
|
|
529
|
+
}}
|
|
530
|
+
|
|
531
|
+
.action-toolbar {{
|
|
532
|
+
display: flex;
|
|
533
|
+
justify-content: space-between;
|
|
534
|
+
align-items: center;
|
|
535
|
+
margin-bottom: 24px;
|
|
536
|
+
padding-bottom: 16px;
|
|
537
|
+
border-bottom: 1px solid var(--border);
|
|
538
|
+
}}
|
|
539
|
+
.brand-heading {{
|
|
540
|
+
display: flex; align-items: center; gap: 14px;
|
|
541
|
+
}}
|
|
542
|
+
.brand-logo-img {{
|
|
543
|
+
height: 48px;
|
|
544
|
+
width: auto;
|
|
545
|
+
object-fit: contain;
|
|
546
|
+
border-radius: 8px;
|
|
547
|
+
}}
|
|
548
|
+
.brand-title {{ font-size: 1.2rem; font-weight: 800; color: #fff; letter-spacing: -0.01em; }}
|
|
549
|
+
.brand-sub {{ font-size: 0.76rem; color: var(--text-secondary); font-weight: 500; }}
|
|
550
|
+
|
|
551
|
+
.print-btn {{
|
|
552
|
+
background: var(--accent-gradient);
|
|
553
|
+
color: #ffffff;
|
|
554
|
+
border: none;
|
|
555
|
+
padding: 10px 22px;
|
|
556
|
+
border-radius: 12px;
|
|
557
|
+
font-family: inherit;
|
|
558
|
+
font-weight: 700;
|
|
559
|
+
font-size: 0.88rem;
|
|
560
|
+
cursor: pointer;
|
|
561
|
+
display: inline-flex; align-items: center; gap: 10px;
|
|
562
|
+
box-shadow: 0 4px 16px rgba(99, 102, 241, 0.35);
|
|
563
|
+
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
|
564
|
+
}}
|
|
565
|
+
.print-btn:hover {{ transform: translateY(-2px); box-shadow: 0 8px 24px rgba(99, 102, 241, 0.55); }}
|
|
566
|
+
|
|
567
|
+
.executive-banner {{
|
|
568
|
+
background: linear-gradient(135deg, rgba(24, 30, 58, 0.9) 0%, rgba(12, 18, 30, 0.95) 100%);
|
|
569
|
+
border: 1px solid var(--border);
|
|
570
|
+
border-radius: 24px;
|
|
571
|
+
padding: 36px 44px;
|
|
572
|
+
display: flex;
|
|
573
|
+
justify-content: space-between;
|
|
574
|
+
align-items: center;
|
|
575
|
+
margin-bottom: 32px;
|
|
576
|
+
box-shadow: 0 24px 48px rgba(0, 0, 0, 0.4);
|
|
577
|
+
position: relative;
|
|
578
|
+
overflow: hidden;
|
|
579
|
+
}}
|
|
580
|
+
.banner-info h1 {{ font-size: 2.1rem; font-weight: 800; letter-spacing: -0.03em; margin-bottom: 8px; }}
|
|
581
|
+
.banner-meta {{
|
|
582
|
+
display: flex; gap: 20px; flex-wrap: wrap;
|
|
583
|
+
font-size: 0.85rem; color: var(--text-secondary);
|
|
584
|
+
font-family: 'JetBrains Mono', monospace;
|
|
585
|
+
}}
|
|
586
|
+
|
|
587
|
+
.grade-card {{
|
|
588
|
+
display: flex; align-items: center; gap: 20px;
|
|
589
|
+
background: rgba(0, 0, 0, 0.45);
|
|
590
|
+
border: 1px solid var(--border);
|
|
591
|
+
border-radius: 20px;
|
|
592
|
+
padding: 16px 32px;
|
|
593
|
+
backdrop-filter: blur(12px);
|
|
594
|
+
}}
|
|
595
|
+
.grade-circle {{
|
|
596
|
+
font-size: 3.6rem; font-weight: 900; line-height: 1;
|
|
597
|
+
color: {grade_color};
|
|
598
|
+
text-shadow: 0 0 30px {grade_color}80;
|
|
599
|
+
}}
|
|
600
|
+
.grade-text-box h4 {{ font-size: 0.74rem; text-transform: uppercase; letter-spacing: 0.1em; color: var(--text-secondary); }}
|
|
601
|
+
.grade-text-box .score-val {{ font-size: 1.1rem; font-weight: 800; color: #fff; }}
|
|
602
|
+
|
|
603
|
+
.kpi-grid {{
|
|
604
|
+
display: grid;
|
|
605
|
+
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
|
606
|
+
gap: 16px;
|
|
607
|
+
margin-bottom: 36px;
|
|
608
|
+
}}
|
|
609
|
+
.kpi-card {{
|
|
610
|
+
background: var(--bg-card);
|
|
611
|
+
border: 1px solid var(--border);
|
|
612
|
+
border-radius: 18px;
|
|
613
|
+
padding: 22px;
|
|
614
|
+
text-align: center;
|
|
615
|
+
transition: all 0.2s;
|
|
616
|
+
backdrop-filter: blur(16px);
|
|
617
|
+
}}
|
|
618
|
+
.kpi-card:hover {{ transform: translateY(-3px); border-color: var(--border-hover); }}
|
|
619
|
+
.kpi-value {{ font-size: 2.6rem; font-weight: 800; line-height: 1; margin-bottom: 6px; }}
|
|
620
|
+
.kpi-label {{ font-size: 0.76rem; text-transform: uppercase; font-weight: 700; color: var(--text-secondary); letter-spacing: 0.08em; }}
|
|
621
|
+
|
|
622
|
+
.filter-section {{
|
|
623
|
+
background: var(--bg-surface);
|
|
624
|
+
border: 1px solid var(--border);
|
|
625
|
+
border-radius: 18px;
|
|
626
|
+
padding: 18px 24px;
|
|
627
|
+
margin-bottom: 32px;
|
|
628
|
+
display: flex; flex-wrap: wrap; gap: 16px;
|
|
629
|
+
align-items: center; justify-content: space-between;
|
|
630
|
+
}}
|
|
631
|
+
.search-box {{
|
|
632
|
+
background: rgba(0, 0, 0, 0.4);
|
|
633
|
+
border: 1px solid var(--border);
|
|
634
|
+
border-radius: 12px;
|
|
635
|
+
padding: 12px 20px;
|
|
636
|
+
color: #fff;
|
|
637
|
+
font-family: inherit;
|
|
638
|
+
font-size: 0.9rem;
|
|
639
|
+
width: 360px;
|
|
640
|
+
outline: none;
|
|
641
|
+
transition: border-color 0.2s;
|
|
642
|
+
}}
|
|
643
|
+
.search-box:focus {{ border-color: var(--accent); }}
|
|
644
|
+
.filter-pills {{ display: flex; gap: 8px; flex-wrap: wrap; }}
|
|
645
|
+
.pill-btn {{
|
|
646
|
+
background: transparent;
|
|
647
|
+
border: 1px solid var(--border);
|
|
648
|
+
color: var(--text-secondary);
|
|
649
|
+
padding: 8px 18px;
|
|
650
|
+
border-radius: 12px;
|
|
651
|
+
font-size: 0.84rem; font-weight: 700;
|
|
652
|
+
cursor: pointer; transition: all 0.2s;
|
|
653
|
+
}}
|
|
654
|
+
.pill-btn:hover, .pill-btn.active {{
|
|
655
|
+
background: rgba(99, 102, 241, 0.2);
|
|
656
|
+
color: #fff;
|
|
657
|
+
border-color: var(--accent);
|
|
658
|
+
}}
|
|
659
|
+
|
|
660
|
+
.findings-panel {{
|
|
661
|
+
background: var(--bg-surface);
|
|
662
|
+
border: 1px solid var(--border);
|
|
663
|
+
border-radius: 22px;
|
|
664
|
+
padding: 32px;
|
|
665
|
+
margin-bottom: 36px;
|
|
666
|
+
}}
|
|
667
|
+
.findings-panel h2 {{
|
|
668
|
+
font-size: 1.35rem; font-weight: 800; margin-bottom: 24px;
|
|
669
|
+
display: flex; align-items: center; justify-content: space-between;
|
|
670
|
+
}}
|
|
671
|
+
|
|
672
|
+
.finding-card {{
|
|
673
|
+
background: var(--bg-card);
|
|
674
|
+
border: 1px solid var(--border);
|
|
675
|
+
border-radius: 16px;
|
|
676
|
+
margin-bottom: 16px;
|
|
677
|
+
overflow: hidden;
|
|
678
|
+
transition: all 0.2s;
|
|
679
|
+
backdrop-filter: blur(12px);
|
|
680
|
+
}}
|
|
681
|
+
.finding-card:hover {{ border-color: var(--border-hover); }}
|
|
682
|
+
.finding-card.critical {{ border-left: 6px solid var(--critical); }}
|
|
683
|
+
.finding-card.high {{ border-left: 6px solid var(--high); }}
|
|
684
|
+
.finding-card.medium {{ border-left: 6px solid var(--medium); }}
|
|
685
|
+
.finding-card.low {{ border-left: 6px solid var(--low); }}
|
|
686
|
+
.finding-card.info {{ border-left: 6px solid var(--info); }}
|
|
687
|
+
|
|
688
|
+
.finding-header {{
|
|
689
|
+
padding: 20px 26px;
|
|
690
|
+
display: flex; justify-content: space-between; align-items: center;
|
|
691
|
+
gap: 18px; cursor: pointer; user-select: none;
|
|
692
|
+
}}
|
|
693
|
+
.finding-title-line {{ display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 6px; }}
|
|
694
|
+
.finding-card-title {{ font-size: 1.02rem; font-weight: 700; color: #fff; }}
|
|
695
|
+
.badge {{
|
|
696
|
+
padding: 4px 12px; border-radius: 20px;
|
|
697
|
+
font-size: 0.72rem; font-weight: 800; text-transform: uppercase;
|
|
698
|
+
letter-spacing: 0.08em;
|
|
699
|
+
}}
|
|
700
|
+
.badge.critical {{ background: rgba(239,68,68,0.2); color: #f87171; border: 1px solid rgba(239,68,68,0.4); }}
|
|
701
|
+
.badge.high {{ background: rgba(249,115,22,0.2); color: #fb923c; border: 1px solid rgba(249,115,22,0.4); }}
|
|
702
|
+
.badge.medium {{ background: rgba(234,179,8,0.2); color: #facc15; border: 1px solid rgba(234,179,8,0.4); }}
|
|
703
|
+
.badge.low {{ background: rgba(16,185,129,0.2); color: #34d399; border: 1px solid rgba(16,185,129,0.4); }}
|
|
704
|
+
.badge.info {{ background: rgba(56,189,248,0.2); color: #38bdf8; border: 1px solid rgba(56,189,248,0.4); }}
|
|
705
|
+
.badge.engine {{ background: rgba(99,102,241,0.2); color: #a5b4fc; border: 1px solid rgba(99,102,241,0.4); }}
|
|
706
|
+
|
|
707
|
+
.finding-meta-row {{
|
|
708
|
+
display: flex; gap: 20px; font-size: 0.84rem; color: var(--text-secondary);
|
|
709
|
+
font-family: 'JetBrains Mono', monospace;
|
|
710
|
+
}}
|
|
711
|
+
.finding-body {{
|
|
712
|
+
display: none;
|
|
713
|
+
padding: 0 26px 24px;
|
|
714
|
+
border-top: 1px solid rgba(255,255,255,0.06);
|
|
715
|
+
margin-top: 12px;
|
|
716
|
+
padding-top: 18px;
|
|
717
|
+
}}
|
|
718
|
+
.finding-body.open {{ display: block; }}
|
|
719
|
+
.code-snippet {{
|
|
720
|
+
background: #040711;
|
|
721
|
+
border: 1px solid var(--border);
|
|
722
|
+
border-radius: 12px;
|
|
723
|
+
padding: 16px 20px;
|
|
724
|
+
font-family: 'JetBrains Mono', monospace;
|
|
725
|
+
font-size: 0.84rem;
|
|
726
|
+
color: #38bdf8;
|
|
727
|
+
overflow-x: auto;
|
|
728
|
+
margin: 16px 0;
|
|
729
|
+
white-space: pre-wrap;
|
|
730
|
+
}}
|
|
731
|
+
.attributes-grid {{
|
|
732
|
+
display: grid;
|
|
733
|
+
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
|
734
|
+
gap: 12px;
|
|
735
|
+
background: rgba(0,0,0,0.35);
|
|
736
|
+
padding: 16px 20px;
|
|
737
|
+
border-radius: 12px;
|
|
738
|
+
font-size: 0.84rem;
|
|
739
|
+
}}
|
|
740
|
+
|
|
741
|
+
.engines-panel {{
|
|
742
|
+
background: var(--bg-surface);
|
|
743
|
+
border: 1px solid var(--border);
|
|
744
|
+
border-radius: 22px;
|
|
745
|
+
padding: 32px;
|
|
746
|
+
margin-bottom: 36px;
|
|
747
|
+
}}
|
|
748
|
+
.engines-grid {{
|
|
749
|
+
display: grid;
|
|
750
|
+
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
|
751
|
+
gap: 16px;
|
|
752
|
+
margin-top: 20px;
|
|
753
|
+
}}
|
|
754
|
+
.engine-card {{
|
|
755
|
+
background: rgba(0,0,0,0.35);
|
|
756
|
+
border: 1px solid var(--border);
|
|
757
|
+
border-radius: 14px;
|
|
758
|
+
padding: 18px 22px;
|
|
759
|
+
transition: all 0.2s;
|
|
760
|
+
}}
|
|
761
|
+
.engine-card:hover {{ border-color: var(--border-hover); transform: translateY(-2px); }}
|
|
762
|
+
.engine-header {{ display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }}
|
|
763
|
+
.engine-prod-name {{ font-size: 1.02rem; font-weight: 800; color: #fff; }}
|
|
764
|
+
.engine-category {{ font-size: 0.72rem; font-weight: 700; color: var(--accent); background: rgba(99,102,241,0.18); padding: 3px 10px; border-radius: 8px; }}
|
|
765
|
+
.engine-title {{ font-size: 0.84rem; font-weight: 600; color: var(--text-secondary); margin-bottom: 6px; }}
|
|
766
|
+
.engine-desc {{ font-size: 0.76rem; color: var(--text-tertiary); line-height: 1.4; }}
|
|
767
|
+
|
|
768
|
+
.footer-bar {{
|
|
769
|
+
text-align: center;
|
|
770
|
+
font-size: 0.84rem;
|
|
771
|
+
color: var(--text-tertiary);
|
|
772
|
+
padding-top: 32px;
|
|
773
|
+
border-top: 1px solid var(--border);
|
|
774
|
+
}}
|
|
775
|
+
</style>
|
|
776
|
+
</head>
|
|
777
|
+
<body>
|
|
778
|
+
<div class="container">
|
|
779
|
+
<header class="action-toolbar">
|
|
780
|
+
<div class="brand-heading">
|
|
781
|
+
{f'<img src="{logo_data_uri}" class="brand-logo-img" alt="Orion Logo">' if logo_data_uri else '<div style="background:var(--accent-gradient);width:38px;height:38px;border-radius:10px;display:flex;align-items:center;justify-content:center;font-weight:800;color:#fff;">O</div>'}
|
|
782
|
+
<div>
|
|
783
|
+
<div class="brand-title">Orion Security Suite</div>
|
|
784
|
+
<div class="brand-sub">Proprietary In-House Security & Code Intelligence Suite</div>
|
|
785
|
+
</div>
|
|
786
|
+
</div>
|
|
787
|
+
<button class="print-btn" onclick="window.print()">
|
|
788
|
+
🖨️ Export PDF / Print Report
|
|
789
|
+
</button>
|
|
790
|
+
</header>
|
|
791
|
+
|
|
792
|
+
<section class="executive-banner">
|
|
793
|
+
<div class="banner-info">
|
|
794
|
+
<h1>Executive Security Audit Report</h1>
|
|
795
|
+
<div class="banner-meta">
|
|
796
|
+
<span>Target: {html.escape(target_path)}</span>
|
|
797
|
+
<span>•</span>
|
|
798
|
+
<span>Audit Type: {html.escape(scan_type)}</span>
|
|
799
|
+
<span>•</span>
|
|
800
|
+
<span>Generated: {datetime.now().strftime('%B %d, %Y - %H:%M:%S')}</span>
|
|
801
|
+
</div>
|
|
802
|
+
</div>
|
|
803
|
+
<div class="grade-card">
|
|
804
|
+
<div class="grade-circle">{grade}</div>
|
|
805
|
+
<div class="grade-text-box">
|
|
806
|
+
<h4>Security Posture</h4>
|
|
807
|
+
<div class="score-val">{score}/100 Index</div>
|
|
808
|
+
</div>
|
|
809
|
+
</div>
|
|
810
|
+
</section>
|
|
811
|
+
|
|
812
|
+
<section class="kpi-grid">
|
|
813
|
+
<div class="kpi-card" style="border-top: 4px solid var(--critical);">
|
|
814
|
+
<div class="kpi-value" style="color: var(--critical);">{critical}</div>
|
|
815
|
+
<div class="kpi-label">Critical Risks</div>
|
|
816
|
+
</div>
|
|
817
|
+
<div class="kpi-card" style="border-top: 4px solid var(--high);">
|
|
818
|
+
<div class="kpi-value" style="color: var(--high);">{high}</div>
|
|
819
|
+
<div class="kpi-label">High Severity</div>
|
|
820
|
+
</div>
|
|
821
|
+
<div class="kpi-card" style="border-top: 4px solid var(--medium);">
|
|
822
|
+
<div class="kpi-value" style="color: var(--medium);">{medium}</div>
|
|
823
|
+
<div class="kpi-label">Medium Priority</div>
|
|
824
|
+
</div>
|
|
825
|
+
<div class="kpi-card" style="border-top: 4px solid var(--low);">
|
|
826
|
+
<div class="kpi-value" style="color: var(--low);">{low}</div>
|
|
827
|
+
<div class="kpi-label">Low / Standards</div>
|
|
828
|
+
</div>
|
|
829
|
+
<div class="kpi-card" style="border-top: 4px solid var(--info);">
|
|
830
|
+
<div class="kpi-value" style="color: var(--info);">{total}</div>
|
|
831
|
+
<div class="kpi-label">Total Findings</div>
|
|
832
|
+
</div>
|
|
833
|
+
<div class="kpi-card">
|
|
834
|
+
<div class="kpi-value" style="color: var(--accent);">{result.metrics.get('files_scanned', 0)}</div>
|
|
835
|
+
<div class="kpi-label">Files Audited</div>
|
|
836
|
+
</div>
|
|
837
|
+
</section>
|
|
838
|
+
|
|
839
|
+
<div class="filter-section no-print">
|
|
840
|
+
<input type="text" class="search-box" id="searchBox" placeholder="Search findings by title, CWE, path, or engine..." onkeyup="applyFilter()">
|
|
841
|
+
<div class="filter-pills">
|
|
842
|
+
<button class="pill-btn active" onclick="setSeverity('all', this)">All Severities</button>
|
|
843
|
+
<button class="pill-btn" onclick="setSeverity('critical', this)">Critical ({critical})</button>
|
|
844
|
+
<button class="pill-btn" onclick="setSeverity('high', this)">High ({high})</button>
|
|
845
|
+
<button class="pill-btn" onclick="setSeverity('medium', this)">Medium ({medium})</button>
|
|
846
|
+
<button class="pill-btn" onclick="setSeverity('low', this)">Low ({low})</button>
|
|
847
|
+
</div>
|
|
848
|
+
</div>
|
|
849
|
+
<div class="filter-section no-print" style="margin-top: -16px; padding: 12px 24px; background: rgba(12, 18, 30, 0.65);">
|
|
850
|
+
<span style="font-size: 0.8rem; font-weight: 700; color: var(--text-secondary); text-transform: uppercase;">Category:</span>
|
|
851
|
+
<div class="filter-pills">
|
|
852
|
+
<button class="pill-btn cat-btn active" onclick="setCategory('all', this)">All Categories</button>
|
|
853
|
+
<button class="pill-btn cat-btn" onclick="setCategory('security', this)">🛡️ Security & Vulnerabilities</button>
|
|
854
|
+
<button class="pill-btn cat-btn" onclick="setCategory('quality', this)">⚡ Code Quality & Standards</button>
|
|
855
|
+
<button class="pill-btn cat-btn" onclick="setCategory('architecture', this)">🏛️ Architecture & Dataflow</button>
|
|
856
|
+
<button class="pill-btn cat-btn" onclick="setCategory('supply', this)">📦 Supply Chain & Privacy</button>
|
|
857
|
+
</div>
|
|
858
|
+
</div>
|
|
859
|
+
|
|
860
|
+
<section class="findings-panel">
|
|
861
|
+
<h2>Findings Catalog ({total})</h2>
|
|
862
|
+
<div id="findingsContainer">
|
|
863
|
+
""")
|
|
864
|
+
|
|
865
|
+
sorted_findings = sorted(result.findings, key=lambda f: severity_order.get(f.severity, 5))
|
|
866
|
+
for finding in sorted_findings:
|
|
867
|
+
sev = finding.severity.lower()
|
|
868
|
+
title = html.escape(finding.title)
|
|
869
|
+
loc = html.escape(finding.location)
|
|
870
|
+
desc = html.escape(finding.description or "")
|
|
871
|
+
engine_code = finding.engine
|
|
872
|
+
m_meta = ENGINE_MARKETING_METADATA.get(engine_code, {})
|
|
873
|
+
engine_prod_name = html.escape(m_meta.get("name", engine_code))
|
|
874
|
+
raw_cat = m_meta.get("cat", "General")
|
|
875
|
+
engine_cat = html.escape(raw_cat)
|
|
876
|
+
|
|
877
|
+
# Slugify category
|
|
878
|
+
cat_slug = "quality"
|
|
879
|
+
if "Security" in raw_cat or "Threat" in raw_cat or "Cloud" in raw_cat:
|
|
880
|
+
cat_slug = "security"
|
|
881
|
+
elif "Architecture" in raw_cat or "Dataflow" in raw_cat:
|
|
882
|
+
cat_slug = "architecture"
|
|
883
|
+
elif "Supply" in raw_cat or "Compliance" in raw_cat or "Privacy" in raw_cat:
|
|
884
|
+
cat_slug = "supply"
|
|
885
|
+
|
|
886
|
+
cwe = html.escape(str(finding.metadata.get("cwe", "")))
|
|
887
|
+
cwe_badge = f'<span class="badge {sev}">{cwe}</span>' if cwe else ""
|
|
888
|
+
snippet = html.escape(str(finding.metadata.get("snippet", "")).strip())
|
|
889
|
+
conf = html.escape(str(finding.metadata.get("confidence", "N/A")))
|
|
890
|
+
contribs = finding.metadata.get("contributing_engines", [engine_code])
|
|
891
|
+
contrib_str = ", ".join(ENGINE_MARKETING_METADATA.get(e, {}).get("name", e) for e in contribs)
|
|
892
|
+
|
|
893
|
+
f.write(f"""
|
|
894
|
+
<div class="finding-card {sev}" data-severity="{sev}" data-category="{cat_slug}" data-search="{title.lower()} {loc.lower()} {engine_prod_name.lower()} {engine_code.lower()} {cwe.lower()} {engine_cat.lower()}">
|
|
895
|
+
<div class="finding-header" onclick="toggleDetails(this)">
|
|
896
|
+
<div style="flex: 1;">
|
|
897
|
+
<div class="finding-title-line">
|
|
898
|
+
<span class="badge {sev}">{sev.upper()}</span>
|
|
899
|
+
<span class="badge engine">{engine_prod_name}</span>
|
|
900
|
+
<span class="badge" style="background: rgba(255,255,255,0.08); color: var(--text-secondary);">{engine_cat}</span>
|
|
901
|
+
{cwe_badge}
|
|
902
|
+
<span class="finding-card-title">{title}</span>
|
|
903
|
+
</div>
|
|
904
|
+
<div class="finding-meta-row">
|
|
905
|
+
<span>Engine: {engine_prod_name} ({engine_code})</span>
|
|
906
|
+
<span>•</span>
|
|
907
|
+
<span>Location: {loc}</span>
|
|
908
|
+
<span>•</span>
|
|
909
|
+
<span>Confidence: {conf}</span>
|
|
910
|
+
</div>
|
|
911
|
+
</div>
|
|
912
|
+
</div>
|
|
913
|
+
<div class="finding-body">
|
|
914
|
+
{f'<p style="font-size: 0.9rem; color: var(--text-secondary); margin-bottom: 12px;">{desc}</p>' if desc else ''}
|
|
915
|
+
{f'<div class="code-snippet">{snippet}</div>' if snippet else ''}
|
|
916
|
+
<div class="attributes-grid">
|
|
917
|
+
<div><strong>Engine:</strong> {engine_prod_name} ({engine_code})</div>
|
|
918
|
+
<div><strong>Category:</strong> {engine_cat}</div>
|
|
919
|
+
<div><strong>Contributing Scanners:</strong> {contrib_str}</div>
|
|
920
|
+
<div><strong>Location:</strong> {loc}</div>
|
|
921
|
+
<div><strong>Severity:</strong> {sev.upper()}</div>
|
|
922
|
+
<div><strong>Confidence:</strong> {conf}</div>
|
|
923
|
+
</div>
|
|
924
|
+
</div>
|
|
925
|
+
</div>
|
|
926
|
+
""")
|
|
927
|
+
|
|
928
|
+
f.write(f"""
|
|
929
|
+
</div>
|
|
930
|
+
</section>
|
|
931
|
+
|
|
932
|
+
<section class="engines-panel">
|
|
933
|
+
<h2>Proprietary In-House Auditing Engines</h2>
|
|
934
|
+
<p style="font-size: 0.88rem; color: var(--text-secondary);">Every scanner is 100% custom-built, running AST semantic analysis, Inter-Procedural Control Flow Graphs, Taint Propagation, and Cloud/IaC/AI Security Analyzers locally.</p>
|
|
935
|
+
<div class="engines-grid">
|
|
936
|
+
""")
|
|
937
|
+
for eng_key, meta in ENGINE_MARKETING_METADATA.items():
|
|
938
|
+
f.write(f"""
|
|
939
|
+
<div class="engine-card">
|
|
940
|
+
<div class="engine-header">
|
|
941
|
+
<span class="engine-prod-name">{meta['name']}</span>
|
|
942
|
+
<span class="engine-category">{meta['cat']}</span>
|
|
943
|
+
</div>
|
|
944
|
+
<div class="engine-title">{meta['title']}</div>
|
|
945
|
+
<div class="engine-desc">{meta['desc']}</div>
|
|
946
|
+
</div>
|
|
947
|
+
""")
|
|
948
|
+
|
|
949
|
+
f.write(f"""
|
|
950
|
+
</div>
|
|
951
|
+
</section>
|
|
952
|
+
|
|
953
|
+
<footer class="footer-bar no-print">
|
|
954
|
+
Generated by <strong>Orion Security Suite v0.1.0</strong> • Proprietary Code Intelligence & Security Suite
|
|
955
|
+
</footer>
|
|
956
|
+
</div>
|
|
957
|
+
|
|
958
|
+
<script>
|
|
959
|
+
let activeSeverity = 'all';
|
|
960
|
+
let activeCategory = 'all';
|
|
961
|
+
|
|
962
|
+
function toggleDetails(header) {{
|
|
963
|
+
const body = header.nextElementSibling;
|
|
964
|
+
body.classList.toggle('open');
|
|
965
|
+
}}
|
|
966
|
+
|
|
967
|
+
function setSeverity(sev, btn) {{
|
|
968
|
+
activeSeverity = sev;
|
|
969
|
+
document.querySelectorAll('.filter-pills button:not(.cat-btn)').forEach(b => b.classList.remove('active'));
|
|
970
|
+
btn.classList.add('active');
|
|
971
|
+
applyFilter();
|
|
972
|
+
}}
|
|
973
|
+
|
|
974
|
+
function setCategory(cat, btn) {{
|
|
975
|
+
activeCategory = cat;
|
|
976
|
+
document.querySelectorAll('.cat-btn').forEach(b => b.classList.remove('active'));
|
|
977
|
+
btn.classList.add('active');
|
|
978
|
+
applyFilter();
|
|
979
|
+
}}
|
|
980
|
+
|
|
981
|
+
function applyFilter() {{
|
|
982
|
+
const query = document.getElementById('searchBox').value.toLowerCase();
|
|
983
|
+
const cards = document.querySelectorAll('.finding-card');
|
|
984
|
+
|
|
985
|
+
cards.forEach(card => {{
|
|
986
|
+
const cardSev = card.getAttribute('data-severity');
|
|
987
|
+
const cardCat = card.getAttribute('data-category');
|
|
988
|
+
const cardSearch = card.getAttribute('data-search');
|
|
989
|
+
const matchesSev = (activeSeverity === 'all' || cardSev === activeSeverity);
|
|
990
|
+
const matchesCat = (activeCategory === 'all' || cardCat === activeCategory);
|
|
991
|
+
const matchesQuery = !query || cardSearch.includes(query);
|
|
992
|
+
|
|
993
|
+
if (matchesSev && matchesCat && matchesQuery) {{
|
|
994
|
+
card.style.display = 'block';
|
|
995
|
+
}} else {{
|
|
996
|
+
card.style.display = 'none';
|
|
997
|
+
}}
|
|
998
|
+
}});
|
|
999
|
+
}}
|
|
1000
|
+
</script>
|
|
1001
|
+
</body>
|
|
1002
|
+
</html>""")
|
|
1003
|
+
|
|
1004
|
+
print(f"\n {GREEN}{BOLD}✔ Latest Reports Generated in {REPORTS_DIR}/{RESET}")
|
|
1005
|
+
print(f" {CYAN}• Executive HTML (Print & PDF):{RESET} {WHITE}{html_path.name}{RESET}")
|
|
1006
|
+
print(f" {CYAN}• Validated JSON Findings:{RESET} {WHITE}{json_path.name}{RESET}")
|
|
1007
|
+
print(f" {CYAN}• Summary Text Report:{RESET} {WHITE}{txt_path.name}{RESET}\n")
|
|
1008
|
+
|
|
1009
|
+
return json_path, txt_path, html_path
|
|
1010
|
+
|
|
1011
|
+
|
|
1012
|
+
def print_results(result):
|
|
1013
|
+
"""Print scan results in a beautifully styled, high-clarity CLI dashboard."""
|
|
1014
|
+
if not result:
|
|
1015
|
+
return 0
|
|
1016
|
+
|
|
1017
|
+
elapsed = result.metrics.get('elapsed_s', 0)
|
|
1018
|
+
files_count = result.metrics.get('files_scanned', 0)
|
|
1019
|
+
engines_count = result.metrics.get('engines_run', 0)
|
|
1020
|
+
total_findings = len(result.findings)
|
|
1021
|
+
|
|
1022
|
+
critical_count = sum(1 for f in result.findings if f.severity == "critical")
|
|
1023
|
+
high_count = sum(1 for f in result.findings if f.severity == "high")
|
|
1024
|
+
medium_count = sum(1 for f in result.findings if f.severity == "medium")
|
|
1025
|
+
low_count = sum(1 for f in result.findings if f.severity == "low")
|
|
1026
|
+
info_count = sum(1 for f in result.findings if f.severity == "info")
|
|
1027
|
+
|
|
1028
|
+
score = 100 - (critical_count * 15) - (high_count * 8) - (medium_count * 3) - (low_count * 1)
|
|
1029
|
+
score = max(0, score)
|
|
1030
|
+
if score >= 90: grade = "A"
|
|
1031
|
+
elif score >= 75: grade = "B"
|
|
1032
|
+
elif score >= 60: grade = "C"
|
|
1033
|
+
else: grade = "F"
|
|
1034
|
+
|
|
1035
|
+
grade_color = GREEN if grade in ("A", "B") else (YELLOW if grade == "C" else RED)
|
|
1036
|
+
|
|
1037
|
+
print(f"""
|
|
1038
|
+
{CYAN}┌───────────────────────────────────────────────────────────────────────────────────┐{RESET}
|
|
1039
|
+
{CYAN}│{RESET} {WHITE}{BOLD}AUDIT SUMMARY • ORION SECURITY SUITE{RESET} {CYAN}│{RESET}
|
|
1040
|
+
{CYAN}├─────────────────────┬─────────────────────┬───────────────────┬───────────────────┤{RESET}
|
|
1041
|
+
{CYAN}│{RESET} {DIM}Audited Workspace{RESET} {CYAN}│{RESET} {DIM}Files Scanned{RESET} {CYAN}│{RESET} {DIM}Engines Executed{RESET} {CYAN}│{RESET} {DIM}Analysis Time{RESET} {CYAN}│{RESET}
|
|
1042
|
+
{CYAN}│{RESET} {WHITE}{BOLD}{Path('.').resolve().name:<19}{RESET} {CYAN}│{RESET} {WHITE}{BOLD}{files_count:<3} files{RESET} {CYAN}│{RESET} {WHITE}{BOLD}{engines_count:<5} passes{RESET} {CYAN}│{RESET} {WHITE}{BOLD}{elapsed:.2f}s{RESET} {CYAN}│{RESET}
|
|
1043
|
+
{CYAN}├─────────────────────┴─────────────────────┴───────────────────┴───────────────────┤{RESET}
|
|
1044
|
+
{CYAN}│{RESET} {WHITE}{BOLD}SECURITY POSTURE:{RESET} {grade_color}{BOLD}GRADE {grade}{RESET} {DIM}({score}/100 Security Index){RESET} {CYAN}│{RESET}
|
|
1045
|
+
{CYAN}│{RESET} {RED}{BOLD}[ CRITICAL: {critical_count:<3} ]{RESET} {YELLOW}{BOLD}[ HIGH: {high_count:<3} ]{RESET} {YELLOW}[ MEDIUM: {medium_count:<3} ]{RESET} {GREEN}[ LOW: {low_count:<4} ]{RESET} {CYAN}│{RESET}
|
|
1046
|
+
{CYAN}└───────────────────────────────────────────────────────────────────────────────────┘{RESET}
|
|
1047
|
+
""")
|
|
1048
|
+
|
|
1049
|
+
if result.findings:
|
|
1050
|
+
severity_order = {"critical": 0, "high": 1, "medium": 2, "low": 3, "info": 4}
|
|
1051
|
+
sorted_findings = sorted(result.findings, key=lambda f: severity_order.get(f.severity, 5))
|
|
1052
|
+
|
|
1053
|
+
security_cats = {"Application Security", "Cloud & Infrastructure", "AI & Emerging Threats"}
|
|
1054
|
+
sec_findings = [f for f in sorted_findings if ENGINE_MARKETING_METADATA.get(f.engine, {}).get("cat") in security_cats]
|
|
1055
|
+
code_findings = [f for f in sorted_findings if ENGINE_MARKETING_METADATA.get(f.engine, {}).get("cat") not in security_cats]
|
|
1056
|
+
|
|
1057
|
+
# 1. Security & Vulnerability Highlights
|
|
1058
|
+
print(f" {WHITE}{BOLD}1. SECURITY & VULNERABILITY HIGHLIGHTS ({len(sec_findings)} issues):{RESET}")
|
|
1059
|
+
if sec_findings:
|
|
1060
|
+
for f in sec_findings[:6]:
|
|
1061
|
+
sev = f.severity.lower()
|
|
1062
|
+
color = RED if sev == "critical" else (YELLOW if sev == "high" else CYAN)
|
|
1063
|
+
cwe = f.metadata.get("cwe", "")
|
|
1064
|
+
cwe_str = f" {CYAN}[{cwe}]{RESET}" if cwe else ""
|
|
1065
|
+
conf = f.metadata.get("confidence", "N/A")
|
|
1066
|
+
m_meta = ENGINE_MARKETING_METADATA.get(f.engine, {})
|
|
1067
|
+
eng_name = m_meta.get("name", f.engine)
|
|
1068
|
+
print(f" {color}• [{sev.upper()}]{RESET} {WHITE}{BOLD}{f.title}{RESET}{cwe_str}")
|
|
1069
|
+
print(f" {DIM}Location:{RESET} {WHITE}{f.location}{RESET} {DIM}| Engine:{RESET} {CYAN}{eng_name}{RESET} {DIM}| Confidence:{RESET} {conf}")
|
|
1070
|
+
if len(sec_findings) > 6:
|
|
1071
|
+
print(f" {DIM}... and {len(sec_findings) - 6} more security findings in executive report{RESET}")
|
|
1072
|
+
else:
|
|
1073
|
+
print(f" {GREEN}✔ Zero critical or high security vulnerabilities detected.{RESET}")
|
|
1074
|
+
|
|
1075
|
+
# 2. Code Quality, Standards & Architecture Highlights
|
|
1076
|
+
print(f"\n {WHITE}{BOLD}2. CODE QUALITY, STANDARDS & ARCHITECTURE HIGHLIGHTS ({len(code_findings)} issues):{RESET}")
|
|
1077
|
+
if code_findings:
|
|
1078
|
+
for f in code_findings[:6]:
|
|
1079
|
+
sev = f.severity.lower()
|
|
1080
|
+
color = YELLOW if sev in ("medium", "high") else GREEN
|
|
1081
|
+
cwe = f.metadata.get("cwe", "")
|
|
1082
|
+
cwe_str = f" {CYAN}[{cwe}]{RESET}" if cwe else ""
|
|
1083
|
+
conf = f.metadata.get("confidence", "N/A")
|
|
1084
|
+
m_meta = ENGINE_MARKETING_METADATA.get(f.engine, {})
|
|
1085
|
+
eng_name = m_meta.get("name", f.engine)
|
|
1086
|
+
print(f" {color}• [{sev.upper()}]{RESET} {WHITE}{BOLD}{f.title}{RESET}{cwe_str}")
|
|
1087
|
+
print(f" {DIM}Location:{RESET} {WHITE}{f.location}{RESET} {DIM}| Engine:{RESET} {CYAN}{eng_name}{RESET} {DIM}| Confidence:{RESET} {conf}")
|
|
1088
|
+
if len(code_findings) > 6:
|
|
1089
|
+
print(f" {DIM}... and {len(code_findings) - 6} more code quality / architecture findings in report{RESET}")
|
|
1090
|
+
else:
|
|
1091
|
+
print(f" {GREEN}✔ Codebase adheres to all clean code and structural standards.{RESET}")
|
|
1092
|
+
|
|
1093
|
+
print(f"\n {CYAN}─────────────────────────────────────────────────────────────────────────────────────{RESET}")
|
|
1094
|
+
return critical_count + high_count
|
|
1095
|
+
|
|
1096
|
+
|
|
1097
|
+
def interactive_menu():
|
|
1098
|
+
"""Run interactive menu loop."""
|
|
1099
|
+
config = EngineConfig()
|
|
1100
|
+
report_history = []
|
|
1101
|
+
|
|
1102
|
+
while True:
|
|
1103
|
+
clear_screen()
|
|
1104
|
+
print(BANNER)
|
|
1105
|
+
print(MENU)
|
|
1106
|
+
choice = input(f" {CYAN}{BOLD}Orion >> {RESET}").strip().upper()
|
|
1107
|
+
|
|
1108
|
+
if choice == "0":
|
|
1109
|
+
print(f"\n {CYAN}Session closed. Thank you for using Orion Security Suite!{RESET}\n")
|
|
1110
|
+
break
|
|
1111
|
+
|
|
1112
|
+
elif choice == "1":
|
|
1113
|
+
clear_screen()
|
|
1114
|
+
path = "."
|
|
1115
|
+
result = asyncio.run(scan_path(path, config))
|
|
1116
|
+
if result:
|
|
1117
|
+
report_history.append(("Quick Scan", path, result))
|
|
1118
|
+
print_results(result)
|
|
1119
|
+
generate_reports("Quick Scan", path, result)
|
|
1120
|
+
|
|
1121
|
+
elif choice == "2":
|
|
1122
|
+
clear_screen()
|
|
1123
|
+
path = "."
|
|
1124
|
+
result = asyncio.run(scan_path(path, config))
|
|
1125
|
+
if result:
|
|
1126
|
+
report_history.append(("Full Audit", path, result))
|
|
1127
|
+
print_results(result)
|
|
1128
|
+
generate_reports("Full Audit", path, result)
|
|
1129
|
+
|
|
1130
|
+
elif choice == "3":
|
|
1131
|
+
clear_screen()
|
|
1132
|
+
path = "."
|
|
1133
|
+
security_engines = ["sast", "secrets", "deps", "taint", "authorization", "sandbox_escape", "prompt_security"]
|
|
1134
|
+
result = asyncio.run(scan_path(path, config, security_engines))
|
|
1135
|
+
if result:
|
|
1136
|
+
report_history.append(("Security Scan", path, result))
|
|
1137
|
+
print_results(result)
|
|
1138
|
+
generate_reports("Security Scan", path, result)
|
|
1139
|
+
|
|
1140
|
+
elif choice == "4":
|
|
1141
|
+
clear_screen()
|
|
1142
|
+
path = "."
|
|
1143
|
+
iac_engines = ["iac_security", "container", "config_engine", "config_validation"]
|
|
1144
|
+
result = asyncio.run(scan_path(path, config, iac_engines))
|
|
1145
|
+
if result:
|
|
1146
|
+
report_history.append(("IaC Scan", path, result))
|
|
1147
|
+
print_results(result)
|
|
1148
|
+
generate_reports("IaC Scan", path, result)
|
|
1149
|
+
|
|
1150
|
+
elif choice == "5":
|
|
1151
|
+
clear_screen()
|
|
1152
|
+
path = "."
|
|
1153
|
+
ai_engines = ["llm_security", "prompt_security"]
|
|
1154
|
+
result = asyncio.run(scan_path(path, config, ai_engines))
|
|
1155
|
+
if result:
|
|
1156
|
+
report_history.append(("AI Security Scan", path, result))
|
|
1157
|
+
print_results(result)
|
|
1158
|
+
generate_reports("AI Security Scan", path, result)
|
|
1159
|
+
|
|
1160
|
+
elif choice == "6":
|
|
1161
|
+
clear_screen()
|
|
1162
|
+
path = "."
|
|
1163
|
+
crypto_engines = ["crypto_guard", "secrets"]
|
|
1164
|
+
result = asyncio.run(scan_path(path, config, crypto_engines))
|
|
1165
|
+
if result:
|
|
1166
|
+
report_history.append(("Crypto Scan", path, result))
|
|
1167
|
+
print_results(result)
|
|
1168
|
+
generate_reports("Crypto Scan", path, result)
|
|
1169
|
+
|
|
1170
|
+
elif choice == "7":
|
|
1171
|
+
clear_screen()
|
|
1172
|
+
path = "."
|
|
1173
|
+
quality_engines = ["complexity", "duplication", "error_handling", "logging_c", "lint", "test_coverage", "dead_import"]
|
|
1174
|
+
result = asyncio.run(scan_path(path, config, quality_engines))
|
|
1175
|
+
if result:
|
|
1176
|
+
report_history.append(("Quality Scan", path, result))
|
|
1177
|
+
print_results(result)
|
|
1178
|
+
generate_reports("Quality Scan", path, result)
|
|
1179
|
+
|
|
1180
|
+
elif choice == "8":
|
|
1181
|
+
clear_screen()
|
|
1182
|
+
path = "."
|
|
1183
|
+
sc_engines = ["supply_chain_sbom", "provenance", "compliance", "license", "deps"]
|
|
1184
|
+
result = asyncio.run(scan_path(path, config, sc_engines))
|
|
1185
|
+
if result:
|
|
1186
|
+
report_history.append(("Supply Chain Scan", path, result))
|
|
1187
|
+
print_results(result)
|
|
1188
|
+
generate_reports("Supply Chain Scan", path, result)
|
|
1189
|
+
|
|
1190
|
+
elif choice == "9":
|
|
1191
|
+
clear_screen()
|
|
1192
|
+
path = "."
|
|
1193
|
+
threat_engines = ["threat_model", "sensitive_data"]
|
|
1194
|
+
result = asyncio.run(scan_path(path, config, threat_engines))
|
|
1195
|
+
if result:
|
|
1196
|
+
report_history.append(("Threat & Privacy Scan", path, result))
|
|
1197
|
+
print_results(result)
|
|
1198
|
+
generate_reports("Threat & Privacy Scan", path, result)
|
|
1199
|
+
|
|
1200
|
+
elif choice in ("R", "REPORT"):
|
|
1201
|
+
clear_screen()
|
|
1202
|
+
html_rep = REPORTS_DIR / "orion_executive_security_report.html"
|
|
1203
|
+
print(f"\n {CYAN}{BOLD}Latest Executive Report Location:{RESET}")
|
|
1204
|
+
if html_rep.exists():
|
|
1205
|
+
print(f" {GREEN}✔{RESET} {WHITE}{html_rep.resolve()}{RESET}")
|
|
1206
|
+
print(f"\n {DIM}Tip: Open this file in your browser to inspect interactive graphs or export executive PDF.{RESET}")
|
|
1207
|
+
else:
|
|
1208
|
+
print(f" {DIM}No reports generated yet. Run option [1] or [2] first.{RESET}")
|
|
1209
|
+
|
|
1210
|
+
elif choice in ("S", "STATUS"):
|
|
1211
|
+
clear_screen()
|
|
1212
|
+
engine = OrionEngine()
|
|
1213
|
+
print(f"""
|
|
1214
|
+
{CYAN}┌─────────────────────────────────────────────────────────────────────────────────────────────┐{RESET}
|
|
1215
|
+
{CYAN}│{RESET} {WHITE}{BOLD}IN-HOUSE PROPRIETARY ENGINES ({engine.registered_count} ACTIVE){RESET} {CYAN}│{RESET}
|
|
1216
|
+
{CYAN}│{RESET} {DIM}100% Custom-Engineered Local Intellectual Property (Zero External Dependencies){RESET} {CYAN}│{RESET}
|
|
1217
|
+
{CYAN}├────┬──────────┬──────────────────────┬────────────────────────────┬───────────────────────────┤{RESET}
|
|
1218
|
+
{CYAN}│{RESET} {DIM}# {RESET} {CYAN}│{RESET} {DIM}STATUS {RESET} {CYAN}│{RESET} {DIM}PROPRIETARY ENGINE {RESET} {CYAN}│{RESET} {DIM}CATEGORY {RESET} {CYAN}│{RESET} {DIM}INTERNAL IDENTIFIER {RESET}{CYAN}│{RESET}
|
|
1219
|
+
{CYAN}├────┼──────────┼──────────────────────┼────────────────────────────┼───────────────────────────┤{RESET}""")
|
|
1220
|
+
for idx, name in enumerate(sorted(engine._engines.keys()), 1):
|
|
1221
|
+
try:
|
|
1222
|
+
cls = engine._engines[name]
|
|
1223
|
+
inst = cls()
|
|
1224
|
+
avail = asyncio.run(inst.check_availability())
|
|
1225
|
+
meta = ENGINE_MARKETING_METADATA.get(name, {"name": name, "title": name, "cat": "General"})
|
|
1226
|
+
m_name = meta["name"]
|
|
1227
|
+
m_cat = meta["cat"]
|
|
1228
|
+
status = f"{GREEN}ACTIVE{RESET}" if avail else f"{RED}OFFLINE{RESET}"
|
|
1229
|
+
print(f" {CYAN}│{RESET} {idx:02d} {CYAN}│{RESET} {status} {CYAN}│{RESET} {WHITE}{BOLD}{m_name:<20}{RESET} {CYAN}│{RESET} {DIM}{m_cat:<26}{RESET} {CYAN}│{RESET} {CYAN}{name:<25}{RESET} {CYAN}│{RESET}")
|
|
1230
|
+
except Exception as e:
|
|
1231
|
+
print(f" {CYAN}│{RESET} {idx:02d} {CYAN}│{RESET} {RED}ERROR {RESET} {CYAN}│{RESET} {WHITE}{name:<20}{RESET} {CYAN}│{RESET} {DIM}Error: {str(e)[:20]:<20}{RESET} {CYAN}│{RESET} {name:<25} {CYAN}│{RESET}")
|
|
1232
|
+
print(f" {CYAN}└────┴──────────┴──────────────────────┴────────────────────────────┴───────────────────────────┘{RESET}")
|
|
1233
|
+
|
|
1234
|
+
else:
|
|
1235
|
+
print(f"\n {RED}✖ Invalid selection. Please select an option from the menu.{RESET}")
|
|
1236
|
+
|
|
1237
|
+
input(f"\n {DIM}Press Enter to return to main menu...{RESET}")
|
|
1238
|
+
|
|
1239
|
+
|
|
1240
|
+
def main():
|
|
1241
|
+
if len(sys.argv) > 1:
|
|
1242
|
+
if "--version" in sys.argv or "-v" in sys.argv:
|
|
1243
|
+
print("Orion Engine Suite v0.1.0 (Security & Code Intelligence Platform)")
|
|
1244
|
+
sys.exit(0)
|
|
1245
|
+
if "--help" in sys.argv or "-h" in sys.argv:
|
|
1246
|
+
print("""Orion Engine Suite v0.1.0 - Enterprise Code Audit Platform
|
|
1247
|
+
|
|
1248
|
+
Usage:
|
|
1249
|
+
orion # Launch interactive terminal UI
|
|
1250
|
+
orion <path> # Scan file or directory
|
|
1251
|
+
orion . --security # Security, SAST & vulnerability engines
|
|
1252
|
+
orion . --iac # Infrastructure-as-Code & Cloud engines
|
|
1253
|
+
orion . --ai # LLM & AI Agent security engines
|
|
1254
|
+
orion . --crypto # Cryptographic flaw & key auditor
|
|
1255
|
+
orion . --quality # Code quality & standard engines
|
|
1256
|
+
orion . --arch # Architecture & dataflow engines
|
|
1257
|
+
orion . --threat # Threat modeling & privacy engines
|
|
1258
|
+
orion --version # Show version
|
|
1259
|
+
orion --help # Show help
|
|
1260
|
+
""")
|
|
1261
|
+
sys.exit(0)
|
|
1262
|
+
|
|
1263
|
+
target = sys.argv[1]
|
|
1264
|
+
config = None
|
|
1265
|
+
|
|
1266
|
+
if "--config-json" in sys.argv:
|
|
1267
|
+
idx = sys.argv.index("--config-json")
|
|
1268
|
+
if idx + 1 < len(sys.argv):
|
|
1269
|
+
config_data = json.loads(sys.argv[idx + 1])
|
|
1270
|
+
config = EngineConfig(**config_data)
|
|
1271
|
+
|
|
1272
|
+
engine_filter = None
|
|
1273
|
+
scan_type = "Full Audit"
|
|
1274
|
+
if "--security" in sys.argv:
|
|
1275
|
+
engine_filter = ["sast", "secrets", "deps", "taint", "authorization", "sandbox_escape", "prompt_security"]
|
|
1276
|
+
scan_type = "Security Scan"
|
|
1277
|
+
elif "--iac" in sys.argv:
|
|
1278
|
+
engine_filter = ["iac_security", "container", "config_engine", "config_validation"]
|
|
1279
|
+
scan_type = "IaC Scan"
|
|
1280
|
+
elif "--ai" in sys.argv:
|
|
1281
|
+
engine_filter = ["llm_security", "prompt_security"]
|
|
1282
|
+
scan_type = "AI Security Scan"
|
|
1283
|
+
elif "--crypto" in sys.argv:
|
|
1284
|
+
engine_filter = ["crypto_guard", "secrets"]
|
|
1285
|
+
scan_type = "Crypto Scan"
|
|
1286
|
+
elif "--quality" in sys.argv:
|
|
1287
|
+
engine_filter = ["complexity", "duplication", "error_handling", "logging_c", "lint", "test_coverage", "dead_import"]
|
|
1288
|
+
scan_type = "Quality Scan"
|
|
1289
|
+
elif "--arch" in sys.argv:
|
|
1290
|
+
engine_filter = ["callgraph", "cfg", "symbol", "dataflow", "architecture", "orphan", "wiring_trace"]
|
|
1291
|
+
scan_type = "Architecture Scan"
|
|
1292
|
+
elif "--threat" in sys.argv:
|
|
1293
|
+
engine_filter = ["threat_model", "sensitive_data"]
|
|
1294
|
+
scan_type = "Threat & Privacy Scan"
|
|
1295
|
+
|
|
1296
|
+
result = asyncio.run(scan_path(target, config or EngineConfig(), engine_filter))
|
|
1297
|
+
if result:
|
|
1298
|
+
critical_high = print_results(result)
|
|
1299
|
+
generate_reports(scan_type, target, result)
|
|
1300
|
+
sys.exit(1 if critical_high > 0 else 0)
|
|
1301
|
+
sys.exit(0)
|
|
1302
|
+
|
|
1303
|
+
try:
|
|
1304
|
+
interactive_menu()
|
|
1305
|
+
except KeyboardInterrupt:
|
|
1306
|
+
print("\n\n Session terminated by user. Goodbye!\n")
|
|
1307
|
+
|
|
1308
|
+
|
|
1309
|
+
if __name__ == "__main__":
|
|
1310
|
+
main()
|