@orionscanner/cli 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/README.md +135 -248
  2. package/bin/orion.js +30 -29
  3. package/dist/orion.exe +0 -0
  4. package/package.json +8 -10
  5. package/docs/API_REFERENCE.md +0 -211
  6. package/docs/ARCHITECTURE.md +0 -183
  7. package/docs/CHANGELOG.md +0 -112
  8. package/docs/CONTRIBUTING.md +0 -157
  9. package/docs/ENGINE_CATALOG.md +0 -87
  10. package/docs/GETTING_STARTED.md +0 -226
  11. package/pyproject.toml +0 -16
  12. package/src/orion/__init__.py +0 -0
  13. package/src/orion/__pycache__/__init__.cpython-313.pyc +0 -0
  14. package/src/orion/engine/__init__.py +0 -17
  15. package/src/orion/engine/__pycache__/__init__.cpython-313.pyc +0 -0
  16. package/src/orion/engine/__pycache__/config.cpython-313.pyc +0 -0
  17. package/src/orion/engine/__pycache__/core.cpython-313.pyc +0 -0
  18. package/src/orion/engine/__pycache__/ir.cpython-313.pyc +0 -0
  19. package/src/orion/engine/__pycache__/languages.cpython-313.pyc +0 -0
  20. package/src/orion/engine/__pycache__/registry.cpython-313.pyc +0 -0
  21. package/src/orion/engine/__pycache__/results.cpython-313.pyc +0 -0
  22. package/src/orion/engine/__pycache__/runner.cpython-313.pyc +0 -0
  23. package/src/orion/engine/api_security/__pycache__/engine.cpython-313.pyc +0 -0
  24. package/src/orion/engine/api_security/engine.py +0 -125
  25. package/src/orion/engine/architecture/__pycache__/engine.cpython-313.pyc +0 -0
  26. package/src/orion/engine/architecture/engine.py +0 -463
  27. package/src/orion/engine/authorization/__pycache__/engine.cpython-313.pyc +0 -0
  28. package/src/orion/engine/authorization/engine.py +0 -337
  29. package/src/orion/engine/callgraph/__pycache__/engine.cpython-313.pyc +0 -0
  30. package/src/orion/engine/callgraph/engine.py +0 -236
  31. package/src/orion/engine/cfg/__pycache__/engine.cpython-313.pyc +0 -0
  32. package/src/orion/engine/cfg/engine.py +0 -509
  33. package/src/orion/engine/chaos/__pycache__/engine.cpython-313.pyc +0 -0
  34. package/src/orion/engine/chaos/engine.py +0 -268
  35. package/src/orion/engine/chaos_config/__pycache__/engine.cpython-313.pyc +0 -0
  36. package/src/orion/engine/chaos_config/engine.py +0 -322
  37. package/src/orion/engine/complexity/__pycache__/engine.cpython-313.pyc +0 -0
  38. package/src/orion/engine/complexity/engine.py +0 -144
  39. package/src/orion/engine/compliance/__pycache__/engine.cpython-313.pyc +0 -0
  40. package/src/orion/engine/compliance/engine.py +0 -325
  41. package/src/orion/engine/config.py +0 -41
  42. package/src/orion/engine/config_engine/__pycache__/engine.cpython-313.pyc +0 -0
  43. package/src/orion/engine/config_engine/engine.py +0 -364
  44. package/src/orion/engine/config_validation/__pycache__/engine.cpython-313.pyc +0 -0
  45. package/src/orion/engine/config_validation/engine.py +0 -313
  46. package/src/orion/engine/container/__pycache__/engine.cpython-313.pyc +0 -0
  47. package/src/orion/engine/container/engine.py +0 -546
  48. package/src/orion/engine/contract_probe/__pycache__/engine.cpython-313.pyc +0 -0
  49. package/src/orion/engine/contract_probe/engine.py +0 -316
  50. package/src/orion/engine/core.py +0 -75
  51. package/src/orion/engine/crypto_guard/__pycache__/engine.cpython-313.pyc +0 -0
  52. package/src/orion/engine/crypto_guard/engine.py +0 -134
  53. package/src/orion/engine/data_residency/__pycache__/engine.cpython-313.pyc +0 -0
  54. package/src/orion/engine/data_residency/engine.py +0 -238
  55. package/src/orion/engine/dataflow/__pycache__/engine.cpython-313.pyc +0 -0
  56. package/src/orion/engine/dataflow/engine.py +0 -398
  57. package/src/orion/engine/dead_import/__pycache__/engine.cpython-313.pyc +0 -0
  58. package/src/orion/engine/dead_import/engine.py +0 -293
  59. package/src/orion/engine/deps/__pycache__/engine.cpython-313.pyc +0 -0
  60. package/src/orion/engine/deps/engine.py +0 -244
  61. package/src/orion/engine/dispatcher.py +0 -350
  62. package/src/orion/engine/docs/AUDIT_PROMPT.md +0 -1248
  63. package/src/orion/engine/duplication/__pycache__/engine.cpython-313.pyc +0 -0
  64. package/src/orion/engine/duplication/engine.py +0 -120
  65. package/src/orion/engine/error_handling/__pycache__/engine.cpython-313.pyc +0 -0
  66. package/src/orion/engine/error_handling/engine.py +0 -256
  67. package/src/orion/engine/fp_learn/__pycache__/engine.cpython-313.pyc +0 -0
  68. package/src/orion/engine/fp_learn/engine.py +0 -248
  69. package/src/orion/engine/hunter/__pycache__/engine.cpython-313.pyc +0 -0
  70. package/src/orion/engine/hunter/engine.py +0 -324
  71. package/src/orion/engine/iac_security/__pycache__/engine.cpython-313.pyc +0 -0
  72. package/src/orion/engine/iac_security/engine.py +0 -218
  73. package/src/orion/engine/ir.py +0 -22
  74. package/src/orion/engine/languages.py +0 -454
  75. package/src/orion/engine/license/__pycache__/engine.cpython-313.pyc +0 -0
  76. package/src/orion/engine/license/engine.py +0 -172
  77. package/src/orion/engine/lint/__pycache__/engine.cpython-313.pyc +0 -0
  78. package/src/orion/engine/lint/engine.py +0 -558
  79. package/src/orion/engine/llm_security/__pycache__/engine.cpython-313.pyc +0 -0
  80. package/src/orion/engine/llm_security/engine.py +0 -125
  81. package/src/orion/engine/logging_c/__pycache__/engine.cpython-313.pyc +0 -0
  82. package/src/orion/engine/logging_c/engine.py +0 -164
  83. package/src/orion/engine/noise/__pycache__/engine.cpython-313.pyc +0 -0
  84. package/src/orion/engine/noise/engine.py +0 -140
  85. package/src/orion/engine/orphan/__pycache__/engine.cpython-313.pyc +0 -0
  86. package/src/orion/engine/orphan/engine.py +0 -244
  87. package/src/orion/engine/perf_guard/__pycache__/engine.cpython-313.pyc +0 -0
  88. package/src/orion/engine/perf_guard/engine.py +0 -345
  89. package/src/orion/engine/prompt_security/__pycache__/engine.cpython-313.pyc +0 -0
  90. package/src/orion/engine/prompt_security/detectors/__init__.py +0 -4
  91. package/src/orion/engine/prompt_security/engine.py +0 -170
  92. package/src/orion/engine/provenance/__pycache__/engine.cpython-313.pyc +0 -0
  93. package/src/orion/engine/provenance/engine.py +0 -242
  94. package/src/orion/engine/registry.py +0 -55
  95. package/src/orion/engine/regression/__pycache__/engine.cpython-313.pyc +0 -0
  96. package/src/orion/engine/regression/engine.py +0 -213
  97. package/src/orion/engine/results.py +0 -21
  98. package/src/orion/engine/runner.py +0 -1310
  99. package/src/orion/engine/sandbox_escape/__pycache__/engine.cpython-313.pyc +0 -0
  100. package/src/orion/engine/sandbox_escape/engine.py +0 -284
  101. package/src/orion/engine/sast/__pycache__/engine.cpython-313.pyc +0 -0
  102. package/src/orion/engine/sast/engine.py +0 -217
  103. package/src/orion/engine/sast/patterns/__init__.py +0 -513
  104. package/src/orion/engine/sast/patterns/__pycache__/__init__.cpython-313.pyc +0 -0
  105. package/src/orion/engine/secrets/__pycache__/engine.cpython-313.pyc +0 -0
  106. package/src/orion/engine/secrets/engine.py +0 -77
  107. package/src/orion/engine/secrets/patterns/__init__.py +0 -74
  108. package/src/orion/engine/secrets/patterns/__pycache__/__init__.cpython-313.pyc +0 -0
  109. package/src/orion/engine/sensitive_data/__pycache__/engine.cpython-313.pyc +0 -0
  110. package/src/orion/engine/sensitive_data/engine.py +0 -143
  111. package/src/orion/engine/state/__pycache__/engine.cpython-313.pyc +0 -0
  112. package/src/orion/engine/state/engine.py +0 -218
  113. package/src/orion/engine/supply_chain_sbom/__pycache__/engine.cpython-313.pyc +0 -0
  114. package/src/orion/engine/supply_chain_sbom/engine.py +0 -290
  115. package/src/orion/engine/symbol/__pycache__/engine.cpython-313.pyc +0 -0
  116. package/src/orion/engine/symbol/engine.py +0 -463
  117. package/src/orion/engine/taint/__pycache__/engine.cpython-313.pyc +0 -0
  118. package/src/orion/engine/taint/engine.py +0 -464
  119. package/src/orion/engine/test_coverage/__pycache__/engine.cpython-313.pyc +0 -0
  120. package/src/orion/engine/test_coverage/engine.py +0 -445
  121. package/src/orion/engine/threat_model/__pycache__/engine.cpython-313.pyc +0 -0
  122. package/src/orion/engine/threat_model/engine.py +0 -126
  123. package/src/orion/engine/wiring_trace/__pycache__/engine.cpython-313.pyc +0 -0
  124. package/src/orion/engine/wiring_trace/engine.py +0 -200
  125. package/src/orion_engine.egg-info/PKG-INFO +0 -7
  126. package/src/orion_engine.egg-info/SOURCES.txt +0 -65
  127. package/src/orion_engine.egg-info/dependency_links.txt +0 -1
  128. package/src/orion_engine.egg-info/entry_points.txt +0 -2
  129. package/src/orion_engine.egg-info/top_level.txt +0 -1
@@ -1,144 +0,0 @@
1
- """Cyclomatic complexity engine - analyze function/method complexity."""
2
- import ast
3
- from orion.engine.config import EngineConfig
4
- from orion.engine.ir import OrionIR
5
- from orion.engine.results import EngineResult, Finding
6
-
7
-
8
- class Engine:
9
- name = "complexity"
10
- version = "1.0.0"
11
-
12
- async def check_availability(self) -> bool:
13
- return True
14
-
15
- def resource_limits(self):
16
- from orion.engine.config import ResourceLimits
17
- return ResourceLimits(max_cpu_seconds=30, max_memory_mb=128)
18
-
19
- async def run(self, ir: OrionIR, config: EngineConfig) -> EngineResult:
20
- try:
21
- text = ir.content.decode("utf-8", errors="replace")
22
- except Exception:
23
- text = str(ir.content)
24
-
25
- path = ir.metadata.get("path", "unknown")
26
- findings = []
27
- metrics = {"functions": []}
28
-
29
- if not path.endswith(".py"):
30
- return EngineResult(engine=self.name, findings=findings, metrics=metrics, ok=True)
31
-
32
- try:
33
- tree = ast.parse(text)
34
- except SyntaxError as e:
35
- return EngineResult(engine=self.name, findings=findings, metrics=metrics, ok=True, errors=[str(e)])
36
-
37
- lines = text.splitlines()
38
-
39
- for node in ast.walk(tree):
40
- if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
41
- cc = self._calculate_cyclomatic_complexity(node)
42
- cognitive = self._calculate_cognitive_complexity(node)
43
- func_metrics = {
44
- "name": node.name,
45
- "line": node.lineno,
46
- "cyclomatic_complexity": cc,
47
- "cognitive_complexity": cognitive,
48
- }
49
- metrics["functions"].append(func_metrics)
50
-
51
- if cc > 20:
52
- severity = "critical" if cc > 50 else "high"
53
- findings.append(Finding(
54
- engine=self.name,
55
- severity=severity,
56
- title=f"High cyclomatic complexity: {node.name} (CC={cc})",
57
- description=f"Function '{node.name}' has cyclomatic complexity of {cc} (cognitive: {cognitive}) - consider refactoring",
58
- location=f"{path}:{node.lineno}",
59
- metadata={
60
- "confidence": 1.0,
61
- "snippet": self._get_snippet(lines, node.lineno),
62
- "function": node.name,
63
- "cyclomatic_complexity": cc,
64
- "cognitive_complexity": cognitive,
65
- "threshold": "critical" if cc > 50 else "high",
66
- "cwe": "CWE-1121",
67
- "cvss": 4.0,
68
- },
69
- ))
70
- elif cc > 10:
71
- findings.append(Finding(
72
- engine=self.name,
73
- severity="medium",
74
- title=f"Elevated cyclomatic complexity: {node.name} (CC={cc})",
75
- description=f"Function '{node.name}' has cyclomatic complexity of {cc} - monitor for maintainability",
76
- location=f"{path}:{node.lineno}",
77
- metadata={
78
- "confidence": 1.0,
79
- "snippet": self._get_snippet(lines, node.lineno),
80
- "function": node.name,
81
- "cyclomatic_complexity": cc,
82
- "cognitive_complexity": cognitive,
83
- "threshold": "medium",
84
- "cwe": "CWE-1121",
85
- },
86
- ))
87
-
88
- return EngineResult(engine=self.name, findings=findings, metrics=metrics, ok=True)
89
-
90
- def _calculate_cyclomatic_complexity(self, node: ast.FunctionDef) -> int:
91
- complexity = 1
92
- for child in ast.walk(node):
93
- if isinstance(child, (ast.If, ast.While, ast.For, ast.AsyncFor)):
94
- complexity += 1
95
- elif isinstance(child, ast.ExceptHandler):
96
- complexity += 1
97
- elif isinstance(child, ast.BoolOp):
98
- complexity += len(child.values) - 1
99
- elif isinstance(child, ast.With):
100
- complexity += 1
101
- elif isinstance(child, (ast.ListComp, ast.SetComp, ast.DictComp, ast.GeneratorExp)):
102
- complexity += 1
103
- elif isinstance(child, ast.IfExp):
104
- complexity += 1
105
- elif isinstance(child, ast.Match):
106
- complexity += len(child.cases)
107
- return complexity
108
-
109
- def _calculate_cognitive_complexity(self, node: ast.FunctionDef) -> int:
110
- complexity = 0
111
- nesting = 0
112
-
113
- def walk(n, nest_level):
114
- nonlocal complexity
115
- current_nest = nest_level
116
- if isinstance(n, (ast.If, ast.While, ast.For, ast.AsyncFor, ast.With, ast.Try)):
117
- current_nest = nest_level + 1
118
- complexity += current_nest
119
- elif isinstance(n, ast.ExceptHandler):
120
- complexity += nest_level + 1
121
- elif isinstance(n, ast.BoolOp):
122
- complexity += len(n.values) - 1
123
- elif isinstance(n, ast.IfExp):
124
- complexity += nest_level + 1
125
- elif isinstance(n, (ast.ListComp, ast.SetComp, ast.DictComp, ast.GeneratorExp)):
126
- complexity += nest_level + 1
127
- elif isinstance(n, ast.Match):
128
- complexity += len(n.cases) * (nest_level + 1)
129
- current_nest = nest_level + 1
130
- elif isinstance(n, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef, ast.Lambda)):
131
- return
132
-
133
- for child in ast.iter_child_nodes(n):
134
- walk(child, current_nest)
135
-
136
- walk(node, 0)
137
- return complexity
138
-
139
- def _get_snippet(self, lines: list, line_no: int, context: int = 3) -> str:
140
- if line_no <= 0:
141
- return ""
142
- start = max(0, line_no - context - 1)
143
- end = min(len(lines), line_no + context)
144
- return "\n".join(lines[start:end])
@@ -1,325 +0,0 @@
1
- """Compliance mapping engine - maps findings to compliance frameworks."""
2
- from typing import List, Dict, Any, Optional
3
- from dataclasses import dataclass
4
- from collections import defaultdict
5
-
6
- from orion.engine.config import EngineConfig
7
- from orion.engine.ir import OrionIR
8
- from orion.engine.results import EngineResult, Finding
9
-
10
-
11
- @dataclass
12
- class ComplianceMapping:
13
- framework: str
14
- article: str
15
- control: str
16
- description: str
17
-
18
-
19
- class ComplianceEngine:
20
- name = "compliance"
21
- version = "1.0.0"
22
-
23
- # Mapping from finding patterns to compliance frameworks
24
- COMPLIANCE_MAP = {
25
- # GDPR mappings
26
- "sql_injection": [
27
- ComplianceMapping("GDPR", "Art. 32", "security_of_processing", "SQL injection allows unauthorized access to personal data"),
28
- ComplianceMapping("GDPR", "Art. 25", "privacy_by_design", "Lack of parameterized queries violates privacy by design"),
29
- ],
30
- "xss": [
31
- ComplianceMapping("GDPR", "Art. 32", "security_of_processing", "XSS can lead to personal data theft"),
32
- ComplianceMapping("GDPR", "Art. 25", "privacy_by_design", "Missing output encoding violates privacy by design"),
33
- ],
34
- "path_traversal": [
35
- ComplianceMapping("GDPR", "Art. 32", "security_of_processing", "Path traversal can expose personal data files"),
36
- ],
37
- "hardcoded_secret": [
38
- ComplianceMapping("GDPR", "Art. 32", "encryption_at_rest", "Hardcoded secrets violate encryption requirements"),
39
- ComplianceMapping("GDPR", "Art. 33", "breach_notification", "Exposed secrets require breach notification"),
40
- ],
41
- "hardcoded_credential": [
42
- ComplianceMapping("GDPR", "Art. 32", "encryption_at_rest", "Hardcoded credentials violate encryption requirements"),
43
- ],
44
- "weak_crypto": [
45
- ComplianceMapping("GDPR", "Art. 32", "encryption_at_rest", "Weak cryptography fails to protect personal data"),
46
- ComplianceMapping("GDPR", "Art. 25", "privacy_by_design", "Weak crypto violates privacy by design"),
47
- ],
48
- "md5": [
49
- ComplianceMapping("GDPR", "Art. 32", "encryption_at_rest", "MD5 is cryptographically broken"),
50
- ],
51
- "sha1": [
52
- ComplianceMapping("GDPR", "Art. 32", "encryption_at_rest", "SHA1 is cryptographically weak"),
53
- ],
54
- "insecure_deserialization": [
55
- ComplianceMapping("GDPR", "Art. 32", "security_of_processing", "Deserialization vulnerabilities can lead to data breach"),
56
- ],
57
- "missing_auth": [
58
- ComplianceMapping("GDPR", "Art. 32", "access_control", "Missing authentication violates access control requirements"),
59
- ],
60
- "authorization_bypass": [
61
- ComplianceMapping("GDPR", "Art. 32", "access_control", "Authorization bypass allows unauthorized data access"),
62
- ],
63
- "pii_logging": [
64
- ComplianceMapping("GDPR", "Art. 32", "security_of_processing", "Logging PII exposes personal data"),
65
- ComplianceMapping("GDPR", "Art. 25", "data_minimization", "Logging PII violates data minimization"),
66
- ],
67
- "sensitive_data_logging": [
68
- ComplianceMapping("GDPR", "Art. 32", "security_of_processing", "Logging sensitive data exposes it"),
69
- ],
70
- "missing_csp": [
71
- ComplianceMapping("GDPR", "Art. 32", "security_of_processing", "Missing CSP increases XSS risk"),
72
- ],
73
-
74
- # PCI-DSS mappings
75
- "sql_injection": [
76
- ComplianceMapping("PCI-DSS", "Req 6.5.1", "injection_flaws", "SQL injection is a primary injection flaw"),
77
- ],
78
- "xss": [
79
- ComplianceMapping("PCI-DSS", "Req 6.5.7", "cross_site_scripting", "XSS is explicitly mentioned in PCI-DSS"),
80
- ],
81
- "hardcoded_secret": [
82
- ComplianceMapping("PCI-DSS", "Req 3", "protect_stored_data", "Hardcoded secrets violate stored data protection"),
83
- ComplianceMapping("PCI-DSS", "Req 8", "identify_authenticate", "Hardcoded credentials violate authentication requirements"),
84
- ],
85
- "weak_crypto": [
86
- ComplianceMapping("PCI-DSS", "Req 3.4", "encrypt_transmission", "Weak crypto fails to protect cardholder data"),
87
- ComplianceMapping("PCI-DSS", "Req 4", "encrypt_transmission", "Weak crypto in transit violates encryption requirements"),
88
- ],
89
- "md5": [
90
- ComplianceMapping("PCI-DSS", "Req 3.4", "encrypt_transmission", "MD5 not allowed for protecting cardholder data"),
91
- ],
92
- "sha1": [
93
- ComplianceMapping("PCI-DSS", "Req 3.4", "encrypt_transmission", "SHA1 not allowed for protecting cardholder data"),
94
- ],
95
- "missing_auth": [
96
- ComplianceMapping("PCI-DSS", "Req 8", "identify_authenticate", "Missing authentication violates Req 8"),
97
- ],
98
- "insecure_deserialization": [
99
- ComplianceMapping("PCI-DSS", "Req 6.5.8", "insecure_deserialization", "Insecure deserialization is a software vulnerability"),
100
- ],
101
- "path_traversal": [
102
- ComplianceMapping("PCI-DSS", "Req 6.5.5", "improper_access_control", "Path traversal is improper access control"),
103
- ],
104
-
105
- # SOC2 mappings
106
- "sql_injection": [
107
- ComplianceMapping("SOC2", "CC6.1", "logical_access", "SQL injection bypasses logical access controls"),
108
- ],
109
- "xss": [
110
- ComplianceMapping("SOC2", "CC6.1", "logical_access", "XSS bypasses logical access controls"),
111
- ],
112
- "hardcoded_secret": [
113
- ComplianceMapping("SOC2", "CC6.1", "logical_access", "Hardcoded secrets bypass logical access controls"),
114
- ComplianceMapping("SOC2", "CC6.7", "data_transmission", "Secrets in code can be transmitted"),
115
- ],
116
- "weak_crypto": [
117
- ComplianceMapping("SOC2", "CC6.7", "data_transmission", "Weak crypto fails to protect data in transmission"),
118
- ],
119
- "missing_auth": [
120
- ComplianceMapping("SOC2", "CC6.1", "logical_access", "Missing authentication violates logical access"),
121
- ],
122
- "authorization_bypass": [
123
- ComplianceMapping("SOC2", "CC6.1", "logical_access", "Authorization bypass violates logical access"),
124
- ],
125
- "pii_logging": [
126
- ComplianceMapping("SOC2", "CC6.7", "data_transmission", "Logging PII exposes data in transmission"),
127
- ],
128
- "missing_csp": [
129
- ComplianceMapping("SOC2", "CC7.2", "system_monitoring", "Missing CSP reduces monitoring effectiveness"),
130
- ],
131
- "insecure_deserialization": [
132
- ComplianceMapping("SOC2", "CC6.1", "logical_access", "Deserialization bypasses logical access"),
133
- ],
134
-
135
- # HIPAA mappings
136
- "sql_injection": [
137
- ComplianceMapping("HIPAA", "164.312(a)(1)", "access_control", "SQL injection bypasses access control"),
138
- ],
139
- "xss": [
140
- ComplianceMapping("HIPAA", "164.312(a)(1)", "access_control", "XSS bypasses access control"),
141
- ],
142
- "hardcoded_secret": [
143
- ComplianceMapping("HIPAA", "164.312(a)(1)", "access_control", "Hardcoded secrets bypass access control"),
144
- ComplianceMapping("HIPAA", "164.312(e)(1)", "transmission_security", "Secrets in code violate transmission security"),
145
- ],
146
- "weak_crypto": [
147
- ComplianceMapping("HIPAA", "164.312(e)(1)", "transmission_security", "Weak crypto violates transmission security"),
148
- ComplianceMapping("HIPAA", "164.312(a)(2)(iv)", "encryption", "Weak crypto fails encryption standard"),
149
- ],
150
- "md5": [
151
- ComplianceMapping("HIPAA", "164.312(e)(1)", "transmission_security", "MD5 not approved for ePHI"),
152
- ],
153
- "sha1": [
154
- ComplianceMapping("HIPAA", "164.312(e)(1)", "transmission_security", "SHA1 not approved for ePHI"),
155
- ],
156
- "insecure_deserialization": [
157
- ComplianceMapping("HIPAA", "164.312(a)(1)", "access_control", "Deserialization bypasses access control"),
158
- ],
159
- "pii_logging": [
160
- ComplianceMapping("HIPAA", "164.312(a)(1)", "access_control", "Logging ePHI violates access control"),
161
- ComplianceMapping("HIPAA", "164.312(b)", "audit_controls", "Improper logging violates audit controls"),
162
- ],
163
- "missing_auth": [
164
- ComplianceMapping("HIPAA", "164.312(a)(1)", "access_control", "Missing authentication violates access control"),
165
- ],
166
-
167
- # Additional mappings
168
- "cmd_injection": [
169
- ComplianceMapping("GDPR", "Art. 32", "security_of_processing", "Command injection allows system compromise"),
170
- ComplianceMapping("PCI-DSS", "Req 6.5.1", "injection_flaws", "Command injection is an injection flaw"),
171
- ComplianceMapping("SOC2", "CC6.1", "logical_access", "Command injection bypasses logical access"),
172
- ComplianceMapping("HIPAA", "164.312(a)(1)", "access_control", "Command injection bypasses access control"),
173
- ],
174
- "ssrf": [
175
- ComplianceMapping("GDPR", "Art. 32", "security_of_processing", "SSRF allows internal network access"),
176
- ComplianceMapping("PCI-DSS", "Req 1.3", "network_segmentation", "SSRF bypasses network segmentation"),
177
- ComplianceMapping("SOC2", "CC6.1", "logical_access", "SSRF bypasses logical access"),
178
- ],
179
- "missing_healthcheck": [
180
- ComplianceMapping("SOC2", "CC7.2", "system_monitoring", "Missing health checks reduce monitoring"),
181
- ],
182
- "missing_resource_limits": [
183
- ComplianceMapping("SOC2", "CC7.2", "system_monitoring", "Missing resource limits affect availability"),
184
- ],
185
- "privileged_container": [
186
- ComplianceMapping("GDPR", "Art. 32", "security_of_processing", "Privileged containers increase attack surface"),
187
- ComplianceMapping("PCI-DSS", "Req 2.2", "secure_configuration", "Privileged containers violate secure config"),
188
- ComplianceMapping("SOC2", "CC6.1", "logical_access", "Privileged containers bypass logical access"),
189
- ],
190
- "run_as_root": [
191
- ComplianceMapping("GDPR", "Art. 32", "security_of_processing", "Running as root increases risk"),
192
- ComplianceMapping("PCI-DSS", "Req 2.2", "secure_configuration", "Running as root violates secure config"),
193
- ],
194
- "allow_privilege_escalation": [
195
- ComplianceMapping("GDPR", "Art. 32", "security_of_processing", "Privilege escalation increases risk"),
196
- ComplianceMapping("PCI-DSS", "Req 2.2", "secure_configuration", "Privilege escalation violates secure config"),
197
- ],
198
- "host_network": [
199
- ComplianceMapping("PCI-DSS", "Req 1.3", "network_segmentation", "Host network bypasses segmentation"),
200
- ],
201
- "missing_egress_control": [
202
- ComplianceMapping("PCI-DSS", "Req 1.3", "network_segmentation", "Missing egress control violates segmentation"),
203
- ComplianceMapping("SOC2", "CC6.7", "data_transmission", "Missing egress control allows data exfiltration"),
204
- ],
205
- }
206
-
207
- async def check_availability(self) -> bool:
208
- return True
209
-
210
- def resource_limits(self):
211
- from orion.engine.config import ResourceLimits
212
- return ResourceLimits(max_cpu_seconds=10, max_memory_mb=64)
213
-
214
- def _extract_pattern_key(self, finding: Finding) -> str:
215
- """Extract normalized pattern key from finding."""
216
- # Try metadata first
217
- pattern = finding.metadata.get("pattern", "")
218
- if pattern:
219
- return pattern.lower()
220
-
221
- # Try title
222
- title = finding.title.lower()
223
- # Map common patterns
224
- patterns = [
225
- "sql_injection", "sqli", "xss", "cmd_injection", "ssrf",
226
- "path_traversal", "hardcoded_secret", "hardcoded_credential",
227
- "weak_crypto", "md5", "sha1", "insecure_deserialization",
228
- "pickle", "yaml", "eval", "exec", "subprocess", "shell",
229
- "missing_auth", "authorization", "csp", "logging",
230
- "pii", "sensitive", "privileged", "run_as_root",
231
- "allow_privilege_escalation", "host_network", "host_pid", "host_ipc",
232
- "missing_healthcheck", "missing_resource_limits", "read_only",
233
- "cap_add", "network_mode", "pid_mode", "ipc_mode",
234
- "missing_egress_control", "allow_all_outbound",
235
- ]
236
- for p in patterns:
237
- if p in title:
238
- return p
239
- return title[:50]
240
-
241
- def _get_mappings(self, pattern_key: str) -> List[ComplianceMapping]:
242
- """Get compliance mappings for a pattern key."""
243
- mappings = []
244
- for key, comp_mappings in self.COMPLIANCE_MAP.items():
245
- if key in pattern_key or pattern_key in key:
246
- mappings.extend(comp_mappings)
247
- return mappings
248
-
249
- async def run(self, ir: OrionIR, config: EngineConfig) -> EngineResult:
250
- # Get all findings from context
251
- all_findings = ir.metadata.get("all_findings", [])
252
-
253
- # Also check project context
254
- project_ctx = ir.metadata.get("project_context")
255
- if project_ctx and hasattr(project_ctx, 'findings'):
256
- all_findings.extend(project_ctx.findings)
257
-
258
- if not all_findings:
259
- return EngineResult(engine=self.name, ok=True, metrics={"findings_processed": 0})
260
-
261
- # Process each finding and add compliance metadata
262
- enriched_findings = []
263
- compliance_stats = defaultdict(int)
264
-
265
- for finding in all_findings:
266
- pattern_key = self._extract_pattern_key(finding)
267
- mappings = self._get_mappings(pattern_key)
268
-
269
- if mappings:
270
- # Add compliance metadata to finding
271
- compliance_metadata = []
272
- for m in mappings:
273
- compliance_metadata.append({
274
- "framework": m.framework,
275
- "article": m.article,
276
- "control": m.control,
277
- "description": m.description,
278
- })
279
- compliance_stats[m.framework] += 1
280
-
281
- # Create enriched finding with compliance metadata
282
- enriched = Finding(
283
- engine=finding.engine,
284
- severity=finding.severity,
285
- title=finding.title,
286
- description=finding.description,
287
- location=finding.location,
288
- metadata={
289
- **finding.metadata,
290
- "compliance": compliance_metadata,
291
- },
292
- )
293
- enriched_findings.append(enriched)
294
- else:
295
- enriched_findings.append(finding)
296
-
297
- # Create summary finding
298
- if compliance_stats:
299
- summary = Finding(
300
- engine=self.name,
301
- severity="info",
302
- title="Compliance mapping summary",
303
- description=f"Mapped findings to compliance frameworks: {dict(compliance_stats)}",
304
- location="",
305
- metadata={
306
- "rule": "compliance_summary",
307
- "frameworks": dict(compliance_stats),
308
- "total_mappings": sum(compliance_stats.values()),
309
- },
310
- )
311
- enriched_findings.append(summary)
312
-
313
- return EngineResult(
314
- engine=self.name,
315
- findings=enriched_findings,
316
- ok=True,
317
- metrics={
318
- "findings_processed": len(all_findings),
319
- "findings_with_mappings": len([f for f in enriched_findings if "compliance" in f.metadata]),
320
- "compliance_stats": dict(compliance_stats),
321
- },
322
- )
323
-
324
-
325
- Engine = ComplianceEngine
@@ -1,41 +0,0 @@
1
- import hashlib
2
- from dataclasses import dataclass, field
3
- from typing import Optional
4
-
5
-
6
- @dataclass
7
- class ResourceLimits:
8
- max_memory_mb: int = 512
9
- max_cpu_seconds: int = 60
10
- max_file_size_mb: int = 10
11
- max_files: int = 50000
12
-
13
-
14
- @dataclass
15
- class NetworkPolicy:
16
- allow_outbound: bool = False
17
- allowed_hosts: list = field(default_factory=list)
18
-
19
-
20
- @dataclass
21
- class EngineConfig:
22
- toggles: dict = field(default_factory=dict)
23
- resource_limits: dict = field(default_factory=dict)
24
- network_policy: dict = field(default_factory=dict)
25
-
26
- def get_limits(self) -> ResourceLimits:
27
- defaults = ResourceLimits()
28
- rl = self.resource_limits or {}
29
- return ResourceLimits(
30
- max_memory_mb=rl.get("max_memory_mb", defaults.max_memory_mb),
31
- max_cpu_seconds=rl.get("max_cpu_seconds", defaults.max_cpu_seconds),
32
- max_file_size_mb=rl.get("max_file_size_mb", defaults.max_file_size_mb),
33
- max_files=rl.get("max_files", defaults.max_files),
34
- )
35
-
36
- def get_network_policy(self) -> NetworkPolicy:
37
- np = self.network_policy or {}
38
- return NetworkPolicy(
39
- allow_outbound=np.get("allow_outbound", False),
40
- allowed_hosts=np.get("allowed_hosts", []),
41
- )