gitgalaxy 1.1.1__tar.gz → 1.1.2__tar.gz
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.
- {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/PKG-INFO +1 -1
- {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/galaxyscope.py +71 -10
- {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/gitgalaxy_standards_v1.py +74 -0
- {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/llm_recorder.py +1 -1
- gitgalaxy-1.1.2/gitgalaxy/security_lens.py +174 -0
- {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/signal_processor.py +70 -5
- {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy.egg-info/PKG-INFO +1 -1
- {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/pyproject.toml +1 -1
- gitgalaxy-1.1.1/gitgalaxy/security_lens.py +0 -181
- {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/LICENSE +0 -0
- {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/README.md +0 -0
- {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/__init__.py +0 -0
- {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/aperture.py +0 -0
- {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/audit_recorder.py +0 -0
- {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/chronometer.py +0 -0
- {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/detector.py +0 -0
- {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/gpu_recorder.py +0 -0
- {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/guidestar_lens.py +0 -0
- {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/language_lens.py +0 -0
- {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/prism.py +0 -0
- {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/record_keeper.py +0 -0
- {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/spectral_auditor.py +0 -0
- {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy.egg-info/SOURCES.txt +0 -0
- {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy.egg-info/dependency_links.txt +0 -0
- {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy.egg-info/entry_points.txt +0 -0
- {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy.egg-info/top_level.txt +0 -0
- {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gitgalaxy
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.2
|
|
4
4
|
Summary: A high-speed static analysis engine that sequences source code like DNA to map architectural risk and security threats.
|
|
5
5
|
Author: Joe Esquibel
|
|
6
6
|
License: PolyForm Noncommercial License 1.0.0
|
|
@@ -90,6 +90,12 @@ def _init_worker(root_str: str, config: Dict[str, Any], ext_tally: Dict[str, int
|
|
|
90
90
|
if lang_id not in splicer_cache:
|
|
91
91
|
splicer_cache[lang_id] = LogicSplicer(lang_id, lang_defs, parent_logger=worker_logger)
|
|
92
92
|
|
|
93
|
+
# --- NEW: Decide the Rules of Engagement before booting the engines ---
|
|
94
|
+
if os.environ.get("GITGALAXY_DATA_DIR"):
|
|
95
|
+
active_policy = scanning_config.ThreatPolicy.get_policy("paranoid")
|
|
96
|
+
else:
|
|
97
|
+
active_policy = scanning_config.ThreatPolicy.get_policy("baseline")
|
|
98
|
+
|
|
93
99
|
_worker_state.update({
|
|
94
100
|
'root': root,
|
|
95
101
|
'config': config,
|
|
@@ -103,7 +109,13 @@ def _init_worker(root_str: str, config: Dict[str, Any], ext_tally: Dict[str, int
|
|
|
103
109
|
'detector': LanguageDetector(lang_defs, comm_defs),
|
|
104
110
|
'prism': Prism(comm_defs, lang_defs, parent_logger=worker_logger),
|
|
105
111
|
'splicer_cache': splicer_cache,
|
|
106
|
-
'word_tokenizer': re.compile(r'\b\w+\b')
|
|
112
|
+
'word_tokenizer': re.compile(r'\b\w+\b'),
|
|
113
|
+
|
|
114
|
+
# --- NEW: Boot the physics engines into worker memory ---
|
|
115
|
+
'chronometer': Chronometer(root, parent_logger=worker_logger),
|
|
116
|
+
'signal': SignalProcessor(aperture_config=config, parent_logger=worker_logger),
|
|
117
|
+
'security': SecurityLens(policy=active_policy)
|
|
118
|
+
# --------------------------------------------------------
|
|
107
119
|
})
|
|
108
120
|
|
|
109
121
|
_worker_state['guidestar'].align_telescope()
|
|
@@ -153,6 +165,12 @@ def _process_file_worker(rel_path: str) -> Dict[str, Any]:
|
|
|
153
165
|
splicer_cache = _worker_state['splicer_cache']
|
|
154
166
|
tokenizer = _worker_state['word_tokenizer']
|
|
155
167
|
|
|
168
|
+
# --- NEW: Extract the physics engines from worker memory ---
|
|
169
|
+
chronometer = _worker_state['chronometer']
|
|
170
|
+
signal = _worker_state['signal']
|
|
171
|
+
security = _worker_state['security']
|
|
172
|
+
# -----------------------------------------------------------
|
|
173
|
+
|
|
156
174
|
has_prior, intent_vector = guidestar.get_intent_status(full_path_str)
|
|
157
175
|
observation = {"rel_path": rel_path, "status": "filtered", "reason": "Aperture block", "data": {}}
|
|
158
176
|
|
|
@@ -312,6 +330,16 @@ class Orchestrator:
|
|
|
312
330
|
self.audit_recorder = AuditRecorder(parent_logger=logger)
|
|
313
331
|
self.llm_recorder = LLMRecorder(parent_logger=logger)
|
|
314
332
|
|
|
333
|
+
# --- NEW: THE SMART THREAT SWITCH (MAIN THREAD) ---
|
|
334
|
+
if os.environ.get("GITGALAXY_DATA_DIR"):
|
|
335
|
+
logger.info("☣️ HAZMAT SANDBOX DETECTED: Engaging PARANOID threat thresholds.")
|
|
336
|
+
active_policy = scanning_config.ThreatPolicy.get_policy("paranoid")
|
|
337
|
+
else:
|
|
338
|
+
active_policy = scanning_config.ThreatPolicy.get_policy("baseline")
|
|
339
|
+
|
|
340
|
+
self.security_analyzer = SecurityLens(policy=active_policy)
|
|
341
|
+
# --------------------------------------------------
|
|
342
|
+
|
|
315
343
|
# State Arrays
|
|
316
344
|
self.census: Set[str] = set()
|
|
317
345
|
self.stem_map: Dict[str, str] = {}
|
|
@@ -731,6 +759,25 @@ class Orchestrator:
|
|
|
731
759
|
"""Pass 2: Universal Exposure Framework & Signal Processing."""
|
|
732
760
|
logger.info("PASS_2: Calculating structural physics and Tiered Normalization.")
|
|
733
761
|
|
|
762
|
+
# ==============================================================
|
|
763
|
+
# NEW: CALCULATE FOLDER CONTEXTS (For Domain Ontologies)
|
|
764
|
+
# Tally the languages in every folder to find the dominant ecosystem
|
|
765
|
+
# ==============================================================
|
|
766
|
+
folder_tallies = {}
|
|
767
|
+
for rel_path, meta in self.cryolink.items():
|
|
768
|
+
folder = str(Path(rel_path).parent)
|
|
769
|
+
lang = meta.get("lang_id", "unknown")
|
|
770
|
+
|
|
771
|
+
if folder not in folder_tallies:
|
|
772
|
+
folder_tallies[folder] = {}
|
|
773
|
+
folder_tallies[folder][lang] = folder_tallies[folder].get(lang, 0) + 1
|
|
774
|
+
|
|
775
|
+
folder_dominant_langs = {}
|
|
776
|
+
for folder, tallies in folder_tallies.items():
|
|
777
|
+
if tallies:
|
|
778
|
+
# The language with the most files wins the neighborhood
|
|
779
|
+
folder_dominant_langs[folder] = max(tallies, key=tallies.get)
|
|
780
|
+
|
|
734
781
|
# --- NEW: CALCULATE THE GLOBAL TEST UMBRELLA ---
|
|
735
782
|
total_loc = 0
|
|
736
783
|
test_loc = 0
|
|
@@ -751,6 +798,15 @@ class Orchestrator:
|
|
|
751
798
|
|
|
752
799
|
for rel_path, meta in self.cryolink.items():
|
|
753
800
|
|
|
801
|
+
# ---> NEW: INJECT THE FOLDER CONTEXT FOR THE SIGNAL PROCESSOR <---
|
|
802
|
+
folder = str(Path(rel_path).parent)
|
|
803
|
+
if "metadata" not in meta:
|
|
804
|
+
meta["metadata"] = {}
|
|
805
|
+
|
|
806
|
+
# Grab the winning language for this folder (defaulting to the file's own language)
|
|
807
|
+
meta["metadata"]["folder_dominant_lang"] = folder_dominant_langs.get(folder, meta.get("lang_id", "unknown"))
|
|
808
|
+
# -----------------------------------------------------------------
|
|
809
|
+
|
|
754
810
|
meta["temporal_telemetry"] = self.chronometer.get_temporal_signals(rel_path)
|
|
755
811
|
meta["authors"] = meta["temporal_telemetry"].get("authors", {})
|
|
756
812
|
stem = Path(rel_path).stem.lower()
|
|
@@ -1079,15 +1135,20 @@ def main():
|
|
|
1079
1135
|
merged_langs[lang]['rules'].update(rules_patch)
|
|
1080
1136
|
logging.debug(f" -> Patched '{lang}' geometry rules.")
|
|
1081
1137
|
|
|
1082
|
-
#
|
|
1083
|
-
#
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1138
|
+
# --- THE SMART THREAT SWITCH ---
|
|
1139
|
+
# If the engine detects the Docker airlock environment variable, it goes into full lockdown.
|
|
1140
|
+
if os.environ.get("GITGALAXY_DATA_DIR"):
|
|
1141
|
+
# We are in the sandbox. Engage Paranoid Mode.
|
|
1142
|
+
active_policy = scanning_config.ThreatPolicy.get_policy("paranoid")
|
|
1143
|
+
# Optional: Print a cool warning so you know it worked in the logs
|
|
1144
|
+
logging.getLogger("GalaxyScope").info("☣️ HAZMAT SANDBOX DETECTED: Engaging PARANOID threat thresholds.")
|
|
1145
|
+
else:
|
|
1146
|
+
# Normal developer scan. Engage Baseline Mode.
|
|
1147
|
+
active_policy = scanning_config.ThreatPolicy.get_policy("baseline")
|
|
1148
|
+
|
|
1149
|
+
# Boot the lens with the chosen policy
|
|
1150
|
+
security_lens = SecurityLens(policy=active_policy)
|
|
1151
|
+
# -------------------------------
|
|
1091
1152
|
|
|
1092
1153
|
# ---------------------------------------------------------
|
|
1093
1154
|
# 3. Assemble the Final Configuration
|
|
@@ -21,6 +21,36 @@ Contains:
|
|
|
21
21
|
|
|
22
22
|
"""
|
|
23
23
|
|
|
24
|
+
class ThreatPolicy:
|
|
25
|
+
"""Defines the threshold at which a structural anomaly becomes a critical threat."""
|
|
26
|
+
|
|
27
|
+
PROFILES = {
|
|
28
|
+
# The Baseline: For standard, internal development where some low-level logic is expected.
|
|
29
|
+
"baseline": {
|
|
30
|
+
"secrets_risk_threshold": 0.001, # 0.1% density
|
|
31
|
+
"hidden_malware_threshold": 0.60, # 60% density
|
|
32
|
+
"logic_bomb_threshold": 0.50, # 50% density
|
|
33
|
+
"injection_surface_threshold": 0.65, # 65% density
|
|
34
|
+
"memory_corruption_threshold": 0.60 # 60% density
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
# The Hazmat Suit: For scanning unknown PyPI/npm packages in a quarantine sandbox.
|
|
38
|
+
"paranoid": {
|
|
39
|
+
"secrets_risk_threshold": 0.0001, # Any trace is critical
|
|
40
|
+
"hidden_malware_threshold": 0.15, # 15% density trips the wire
|
|
41
|
+
"logic_bomb_threshold": 0.20, # 20% density
|
|
42
|
+
"injection_surface_threshold": 0.25, # 25% density
|
|
43
|
+
"memory_corruption_threshold": 0.10 # 10% density
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@staticmethod
|
|
48
|
+
def get_policy(mode="baseline"):
|
|
49
|
+
"""Returns the specific threat thresholds based on the deployment mode."""
|
|
50
|
+
return ThreatPolicy.PROFILES.get(mode, ThreatPolicy.PROFILES["baseline"])
|
|
51
|
+
|
|
52
|
+
#
|
|
53
|
+
|
|
24
54
|
|
|
25
55
|
# ------------------------------------------------------------------------------
|
|
26
56
|
# 1. OPTICAL LAYER (Consumed by aperture.py & guidestar_lens.py)
|
|
@@ -10402,6 +10432,50 @@ RISK_EQUATION_TUNING = {
|
|
|
10402
10432
|
}
|
|
10403
10433
|
}
|
|
10404
10434
|
|
|
10435
|
+
# ------------------------------------------------------------------------------
|
|
10436
|
+
# 4.6 LANGUAGE SECURITY PROFILES (The Context vs. Entity Matrix)
|
|
10437
|
+
# Defines domain ontologies to cure the "Apollo Paradox" and detect Trojan Horses.
|
|
10438
|
+
# ------------------------------------------------------------------------------
|
|
10439
|
+
LANGUAGE_SECURITY_PROFILES = {
|
|
10440
|
+
"ECOSYSTEMS": {
|
|
10441
|
+
# Bare metal, embedded, and legacy mainframe. Pointer math and direct OS hooks are native.
|
|
10442
|
+
"systems": {
|
|
10443
|
+
"c", "cpp", "rust", "assembly", "agc_assembly", "zig", "cobol",
|
|
10444
|
+
"fortran", "micropython", "objective-c"
|
|
10445
|
+
},
|
|
10446
|
+
# High DOM flux, UI components, and massive string manipulation. Highly vulnerable to XSS.
|
|
10447
|
+
"web": {
|
|
10448
|
+
"javascript", "typescript", "html", "css", "php", "ruby",
|
|
10449
|
+
"dart", "livecode"
|
|
10450
|
+
},
|
|
10451
|
+
# Deployment, orchestration, and scripting. OS execution is the literal purpose.
|
|
10452
|
+
"infra": {
|
|
10453
|
+
"shell", "powershell", "dockerfile", "yaml", "makefile", "m4",
|
|
10454
|
+
"xml", "json", "toml", "sqlite", "csv", "plaintext"
|
|
10455
|
+
},
|
|
10456
|
+
# Data processing, APIs, and strict-typed object orientation.
|
|
10457
|
+
"backend": {
|
|
10458
|
+
"python", "java", "go", "csharp", "kotlin", "scala", "scheme",
|
|
10459
|
+
"tcl", "matlab", "perl", "haskell", "lua", "apex", "swift"
|
|
10460
|
+
}
|
|
10461
|
+
},
|
|
10462
|
+
|
|
10463
|
+
# Baseline multipliers applied when the file MATCHES its neighborhood's dominant ecosystem
|
|
10464
|
+
"NATIVE_WEIGHTS": {
|
|
10465
|
+
"systems": {"memory": 0.1, "logic_bomb": 0.2, "flux": 1.0, "injection": 1.0}, # Pointer math is normal
|
|
10466
|
+
"web": {"memory": 1.0, "logic_bomb": 1.0, "flux": 0.3, "injection": 2.0}, # DOM flux is normal, XSS is deadly
|
|
10467
|
+
"infra": {"memory": 1.0, "logic_bomb": 0.0, "flux": 1.0, "injection": 1.0}, # OS commands are literally the point
|
|
10468
|
+
"backend": {"memory": 1.5, "logic_bomb": 1.0, "flux": 1.5, "injection": 1.5} # Standard aggressive baseline
|
|
10469
|
+
},
|
|
10470
|
+
|
|
10471
|
+
# Aggressive penalties applied when the file is an ALIEN in its neighborhood
|
|
10472
|
+
"ALIEN_WEIGHTS": {
|
|
10473
|
+
"systems_in_web": {"memory": 5.0, "logic_bomb": 3.0}, # C code hiding in a JS app = Trojan
|
|
10474
|
+
"infra_in_web": {"logic_bomb": 4.0}, # Shell script hiding in a JS app = Backdoor
|
|
10475
|
+
"web_in_systems": {"flux": 3.0} # JS embedded in C firmware = Bizarre architecture
|
|
10476
|
+
}
|
|
10477
|
+
}
|
|
10478
|
+
|
|
10405
10479
|
# ------------------------------------------------------------------------------
|
|
10406
10480
|
# 5. SCHEMA & EXPORT REGISTRY (Consumed by recorders & SQLite)
|
|
10407
10481
|
# ------------------------------------------------------------------------------
|
|
@@ -200,7 +200,7 @@ class LLMRecorder:
|
|
|
200
200
|
lines.append("> Most scores use a Sigmoid curve based on density (Hits / LOC) to prevent massive files from mathematically hiding their flaws.")
|
|
201
201
|
lines.append("> ")
|
|
202
202
|
lines.append("> 1. **Cognitive Load Exposure:** Measures the mental effort required for a developer to read and understand the file. `Density(Branches + (Flux * 2) + Async/Danger)` mitigated by `Doc Coverage`. High scores indicate a high density of decision-making, conditional branching, and complex state management packed into a small area.")
|
|
203
|
-
lines.append("> 2. **Safety Risk Exposure:** Measures structural integrity and resilience against runtime errors. `Net Exposure = (Danger + Safety_Neg + Flux) - (Safety + Tests + Docs)`. High scores mean risky operations (dynamic execution, type bypasses, unhandled mutations) exceed defensive guardrails (try/catch blocks, type checks, assertions). **Breach Cap:** If danger density is too high, the score is mathematically floored to a high-risk state regardless of defense.")
|
|
203
|
+
lines.append("> 2. **Safety Risk Exposure:** Measures structural integrity and resilience against runtime errors. `Net Exposure = (Danger + Safety_Neg + Flux) - (Safety + Tests + Docs)`. High scores mean risky operations (dynamic execution, type bypasses, unhandled mutations) exceed defensive guardrails (try/catch blocks, type checks, assertions). **Breach Cap:** If danger density is too high, the score is mathematically floored to a high-risk state regardless of defense. A value of near 30 is near minimum floor as gitglaxay tests for testing file pairs, testing folders but not actually their contents.")
|
|
204
204
|
lines.append("> 3. **Tech Debt Exposure:** Measures the density of developer-annotated structural stress. `Density(TODOs [1x] + FIXMEs/Hacks [3x] + Empty Stubs [0.5x])`. High scores indicate a high volume of temporary workarounds, fragile logic, and incomplete implementations relative to the file size.")
|
|
205
205
|
lines.append("> 4. **Verification (Testing) Risk Exposure:** Measures the density of unit testing and programmatic assertions. Evaluates `Test Density` + `Sibling Bonus` (if a dedicated test file exists). High scores (100% risk) mean the logic lacks internal test coverage and has no dedicated sibling test file, increasing the risk of silent failures during refactoring. **Mass Penalty:** Files over 300 LOC get an automatic risk penalty because massive files are inherently harder to test completely.")
|
|
206
206
|
lines.append("> 5. **API Risk Exposure:** Measures the public surface area of a module. `Ratio(API Hits / Total Functions & Classes)`. Weighted by logarithmic volume. High scores indicate that a large percentage of the file's functions and classes are explicitly exported or publicly accessible by external systems.")
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
3
|
+
class SecurityLens:
|
|
4
|
+
"""
|
|
5
|
+
The GitGalaxy Physics Engine for Threat Detection.
|
|
6
|
+
Measures raw structural realities (Regex Hits) and compares them
|
|
7
|
+
against dynamically injected Policy Thresholds.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
def __init__(self, policy=None):
|
|
11
|
+
# ------------------------------------------------------------------
|
|
12
|
+
# DYNAMIC POLICY INJECTION
|
|
13
|
+
# The lens no longer makes the rules. It receives its thresholds
|
|
14
|
+
# from gitgalaxy_standards.ThreatPolicy. If none is provided, it
|
|
15
|
+
# defaults to a safe baseline.
|
|
16
|
+
# ------------------------------------------------------------------
|
|
17
|
+
self.policy = policy or {
|
|
18
|
+
"secrets_risk_threshold": 0.001,
|
|
19
|
+
"hidden_malware_threshold": 0.60,
|
|
20
|
+
"logic_bomb_threshold": 0.50,
|
|
21
|
+
"injection_surface_threshold": 0.65,
|
|
22
|
+
"memory_corruption_threshold": 0.60
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
# ------------------------------------------------------------------
|
|
26
|
+
# RAW SENSORS (The Physics Engine)
|
|
27
|
+
# These remain untouched. They strictly measure structural reality.
|
|
28
|
+
# ------------------------------------------------------------------
|
|
29
|
+
self.THREAT_SIGNATURES = {
|
|
30
|
+
# 1. THE GLASSWORM (Obfuscation & Heat Signatures)
|
|
31
|
+
"heat_triggers": re.compile(
|
|
32
|
+
r'\b(?:atob|btoa|base64_decode|base64_encode|gzuncompress|str_rot13)\b|'
|
|
33
|
+
r'\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4}|'
|
|
34
|
+
r'(?:\w{15,}[ \t]*=[ \t]*["\'][A-Za-z0-9+/]{40,}={0,2}["\'])|'
|
|
35
|
+
r'[\u200B-\u200D\uFEFF\u200E\u200F\u202A-\u202E]', # Invisible Unicode
|
|
36
|
+
re.I
|
|
37
|
+
),
|
|
38
|
+
|
|
39
|
+
# 2. THE TROJAN (Identity Masking & Safety Bypasses)
|
|
40
|
+
"safety_neg": re.compile(
|
|
41
|
+
r'\b(?:atob|btoa|base64_decode|gzinflate|gzuncompress|str_rot13|urldecode)[ \t]*\([ \t]*(?:atob|btoa|base64_decode|gzinflate|gzuncompress|str_rot13|urldecode)\b|'
|
|
42
|
+
r'\b(?:auto_prepend_file|auto_append_file)\b|'
|
|
43
|
+
r'\b(?:ini_set|ini_restore|putenv)[ \t]*\([ \t]*["\'](?:disable_functions|safe_mode|open_basedir|allow_url_fopen)["\'][ \t]*,[ \t]*["\']?(?:0|off|false|)["\']?\)|'
|
|
44
|
+
r'\b(?:disable_functions|safe_mode|open_basedir)\b[ \t]*=[ \t]*(?:off|0|false|""|\'\')|'
|
|
45
|
+
r'process\.env\.NODE_TLS_REJECT_UNAUTHORIZED[ \t]*=[ \t]*["\']?0["\']?|'
|
|
46
|
+
r'\b(?:verify|strictSSL|rejectUnauthorized|CURLOPT_SSL_VERIFYPEER)[ \t]*[=:,][ \t]*(?:False|false|0)\b',
|
|
47
|
+
re.I
|
|
48
|
+
),
|
|
49
|
+
|
|
50
|
+
# 3. EXFILTRATION VECTORS (System Gravity)
|
|
51
|
+
"io": re.compile(
|
|
52
|
+
r'\b(?:fetch|XMLHttpRequest|WebSocket|http\.request|https\.request|requests\.(?:post|put|get)|urllib\.request\.urlopen)\b\s*\(|'
|
|
53
|
+
r'\b(?:curl_exec|fsockopen|pfsockopen|stream_socket_client|file_get_contents)\b\s*\(|'
|
|
54
|
+
r'\b(?:dns_get_record|gethostbyname|socket\.gethostbyname|resolve(?:4|6|Cname|Txt)?)\b\s*\(|'
|
|
55
|
+
r'(?:https?|ftp|tcp|udp|wss?):\/\/(?:(?:\d{1,3}\.){3}\d{1,3}|\[[0-9a-fA-F:]+\]|.*?\.(?:ngrok\.io|ngrok-free\.app|localtunnel\.me|pastebin\.com|workers\.dev|s3\.amazonaws\.com|requestbin\.net|pipedream\.net))',
|
|
56
|
+
re.I | re.X
|
|
57
|
+
),
|
|
58
|
+
|
|
59
|
+
# 4. THE EXECUTIONER (Dynamic Payloads)
|
|
60
|
+
"danger": re.compile(
|
|
61
|
+
r'\b(?:eval|Function|setTimeout|setInterval)\b\s*\(\s*(?:atob|base64|["\']|`)|'
|
|
62
|
+
r'\b(?:document\.write|location\.replace|assert|create_function|passthru|shell_exec|system)\b|'
|
|
63
|
+
r'child_process\.(?:exec|spawn|fork)|'
|
|
64
|
+
r'(?:window|global|this|globalThis)\[[ \t]*(?:["\'][a-zA-Z]["\'][ \t]*\+[ \t]*){1,15}["\'][a-zA-Z]["\'][ \t]*\][ \t]*\(|'
|
|
65
|
+
r'\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\s*\(\s*\$_(?:POST|GET|COOKIE|REQUEST|HEADERS)|'
|
|
66
|
+
r'getattr\s*\(\s*__import__\s*\(|__builtins__\[|Assembly\.Load\s*\(',
|
|
67
|
+
re.I | re.X
|
|
68
|
+
),
|
|
69
|
+
|
|
70
|
+
# 5. ENVIRONMENT POISONING (State Flux)
|
|
71
|
+
"flux": re.compile(
|
|
72
|
+
r'\b[A-Za-z0-9_]+\.prototype\.[A-Za-z0-9_]+[ \t]*=|'
|
|
73
|
+
r'\.__proto__[ \t]*=[ \t]*[{a-zA-Z]|'
|
|
74
|
+
r'\b(?:window|global|globalThis|document)\.(?:fetch|eval|setTimeout|setInterval|Promise|console|JSON)[ \t]*=|'
|
|
75
|
+
r'\$(?:GLOBALS|_(?:SERVER|GET|POST|COOKIE|REQUEST|ENV|SESSION))\[[^\]]+\][ \t]*=[ \t]*[^=]|'
|
|
76
|
+
r'\bextract[ \t]*\([ \t]*\$(?:_(?:GET|POST|REQUEST|COOKIE)|GLOBALS)\b|'
|
|
77
|
+
r'\b__builtins__\[[^\]]+\][ \t]*=|'
|
|
78
|
+
r'\bsys\.modules\[[^\]]+\][ \t]*=',
|
|
79
|
+
re.I
|
|
80
|
+
),
|
|
81
|
+
|
|
82
|
+
# 6. SHADOW LOGIC (Necrosis / Graveyard)
|
|
83
|
+
"graveyard": re.compile(
|
|
84
|
+
r'(?://|#|--)[^\n]*?\b(?:http|bash|curl|wget|eval|base64|nc\s+-e|/dev/tcp)\b|'
|
|
85
|
+
r'/\*(?:(?!\*/).){0,500}?\b(?:http|bash|curl|wget|eval|base64|nc\s+-e|/dev/tcp)\b',
|
|
86
|
+
re.I
|
|
87
|
+
),
|
|
88
|
+
|
|
89
|
+
# 7. SUB-ATOMIC DECRYPTION (Bitwise Hits)
|
|
90
|
+
"bitwise_hits": re.compile(
|
|
91
|
+
r'\b\w+[ \t]*=[ \t]*(?:\w+[ \t]*\^[ \t]*\w+[ \t]*){2,20}|'
|
|
92
|
+
r'(?:\w+\[[^\]\n]{1,50}\][ \t]*\^[ \t]*=?[ \t]*(?:0x[0-9a-fA-F]+|\d+|\w+)[ \t]*;[ \t]*){3,20}',
|
|
93
|
+
re.I
|
|
94
|
+
),
|
|
95
|
+
|
|
96
|
+
# 8. SHADOW IMPORTS (The Switcharoo / Steganography)
|
|
97
|
+
"shadow_imports": re.compile(
|
|
98
|
+
r'\b(?:require|include|import|require_once|include_once|source|load|dofile)\b\s*\(?\s*'
|
|
99
|
+
r'["\'][^"\']+\.(?:png|jpg|jpeg|gif|ico|pdf|zip|tar|dat|tmp|log|txt|csv|wav|mp3)["\']',
|
|
100
|
+
re.I
|
|
101
|
+
),
|
|
102
|
+
|
|
103
|
+
# 9. UNICODE SMUGGLING (Homoglyphs & Typosquatting)
|
|
104
|
+
"homoglyphs": re.compile(
|
|
105
|
+
r'\b(?:import|from|require|include|require_once|fetch|XMLHttpRequest)\b'
|
|
106
|
+
r'[^\n]*?(?:[\u0400-\u04FF]|'
|
|
107
|
+
r'[\u0370-\u03FF]|'
|
|
108
|
+
r'[\u1D400-\u1D7FF]|'
|
|
109
|
+
r'\u3164)',
|
|
110
|
+
re.I
|
|
111
|
+
),
|
|
112
|
+
|
|
113
|
+
# 10. THE VAULT DOOR (Credential & Secret Leaks)
|
|
114
|
+
"private_info": re.compile(
|
|
115
|
+
r"\b(password|secret|token|api[_-]?key|client[_-]?secret|credentials|private[_-]?key|auth[_-]?token)\b[ \t]*(?:[:=]|=>)[ \t]*[\"'][A-Za-z0-9\-_+/=]{16,}[\"']",
|
|
116
|
+
re.I
|
|
117
|
+
),
|
|
118
|
+
|
|
119
|
+
# 11. RAW MEMORY OVERRIDES (From previous context)
|
|
120
|
+
"memory_corruption": re.compile(
|
|
121
|
+
r'\b(?:malloc|calloc|realloc|free|memcpy|memset|memmove|strcpy|strcat|sprintf)\b\s*\(|'
|
|
122
|
+
r'\b(?:asm|__asm__|__asm)\b\s*[\(\{]',
|
|
123
|
+
re.I
|
|
124
|
+
)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
def scan_content(self, file_content, total_loc):
|
|
128
|
+
"""
|
|
129
|
+
Scans raw text and returns the raw hits for the engine to aggregate.
|
|
130
|
+
"""
|
|
131
|
+
hits = {key: len(pattern.findall(file_content)) for key, pattern in self.THREAT_SIGNATURES.items()}
|
|
132
|
+
return hits
|
|
133
|
+
|
|
134
|
+
def evaluate_risk(self, aggregated_hits, total_loc):
|
|
135
|
+
"""
|
|
136
|
+
Takes the raw physics hits, calculates the density, and checks
|
|
137
|
+
if it breaches the dynamically injected policy thresholds.
|
|
138
|
+
"""
|
|
139
|
+
# Prevent division by zero
|
|
140
|
+
loc_safe = total_loc if total_loc > 0 else 1
|
|
141
|
+
|
|
142
|
+
exposures = {}
|
|
143
|
+
|
|
144
|
+
# 1. Hidden Malware Risk (Combines heat, bitwise math, and shadow imports)
|
|
145
|
+
malware_hits = aggregated_hits.get("heat_triggers", 0) + aggregated_hits.get("bitwise_hits", 0) + aggregated_hits.get("shadow_imports", 0) + aggregated_hits.get("homoglyphs", 0)
|
|
146
|
+
malware_density = malware_hits / loc_safe
|
|
147
|
+
if malware_density >= self.policy["hidden_malware_threshold"]:
|
|
148
|
+
exposures["Hidden Malware Risk"] = malware_density
|
|
149
|
+
|
|
150
|
+
# 2. Logic Bomb / Sabotage Risk
|
|
151
|
+
sabotage_hits = aggregated_hits.get("graveyard", 0) + (aggregated_hits.get("danger", 0) * 1.5)
|
|
152
|
+
sabotage_density = sabotage_hits / loc_safe
|
|
153
|
+
if sabotage_density >= self.policy["logic_bomb_threshold"]:
|
|
154
|
+
exposures["Logic Bomb Risk"] = sabotage_density
|
|
155
|
+
|
|
156
|
+
# 3. Data Injection Risk
|
|
157
|
+
injection_hits = aggregated_hits.get("io", 0) + aggregated_hits.get("danger", 0) + aggregated_hits.get("flux", 0)
|
|
158
|
+
injection_density = injection_hits / loc_safe
|
|
159
|
+
if injection_density >= self.policy["injection_surface_threshold"]:
|
|
160
|
+
exposures["Data Injection Risk"] = injection_density
|
|
161
|
+
|
|
162
|
+
# 4. Memory Corruption Risk
|
|
163
|
+
memory_hits = aggregated_hits.get("memory_corruption", 0)
|
|
164
|
+
memory_density = memory_hits / loc_safe
|
|
165
|
+
if memory_density >= self.policy["memory_corruption_threshold"]:
|
|
166
|
+
exposures["Memory Corruption Risk"] = memory_density
|
|
167
|
+
|
|
168
|
+
# 5. Secrets Risk (Highly sensitive)
|
|
169
|
+
secrets_hits = aggregated_hits.get("private_info", 0)
|
|
170
|
+
secrets_density = secrets_hits / loc_safe
|
|
171
|
+
if secrets_density >= self.policy["secrets_risk_threshold"]:
|
|
172
|
+
exposures["Secrets Leak Risk"] = secrets_density
|
|
173
|
+
|
|
174
|
+
return exposures
|
|
@@ -78,8 +78,68 @@ class SignalProcessor:
|
|
|
78
78
|
self.risk_tuning = getattr(config, "RISK_EQUATION_TUNING", {})
|
|
79
79
|
self.is_paranoid = self.config.get("PARANOID_MODE", False)
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
# ======================================================================
|
|
82
|
+
# THE CONTEXT VS. ENTITY MATRIX (Domain Ontologies)
|
|
83
|
+
# ======================================================================
|
|
84
|
+
# We now fetch this dynamically from gitgalaxy_standards_v1.py instead of hardcoding it!
|
|
85
|
+
security_profiles = getattr(config, "LANGUAGE_SECURITY_PROFILES", {})
|
|
86
|
+
self.ECOSYSTEMS = security_profiles.get("ECOSYSTEMS", {})
|
|
87
|
+
self.NATIVE_WEIGHTS = security_profiles.get("NATIVE_WEIGHTS", {})
|
|
88
|
+
self.ALIEN_WEIGHTS = security_profiles.get("ALIEN_WEIGHTS", {})
|
|
89
|
+
|
|
90
|
+
self.logger.info(f"Signal Processor Online | Context-Aware Security Profiles loaded.")
|
|
91
|
+
|
|
92
|
+
# Aggressive penalties applied when the file is an ALIEN in its neighborhood
|
|
93
|
+
self.ALIEN_WEIGHTS = {
|
|
94
|
+
"systems_in_web": {"memory": 5.0, "logic_bomb": 3.0}, # C code hiding in a JS app = Trojan
|
|
95
|
+
"infra_in_web": {"logic_bomb": 4.0}, # Shell script hiding in a JS app = Backdoor
|
|
96
|
+
"web_in_systems": {"flux": 3.0} # JS embedded in C firmware = Bizarre architecture
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
self.logger.info(f"Signal Processor Online | Context-Aware Risk Schema loaded.")
|
|
100
|
+
|
|
101
|
+
def _get_context_multipliers(self, file_lang: str, folder_lang: str) -> Dict[str, float]:
|
|
102
|
+
"""
|
|
103
|
+
Calculates risk multipliers by comparing a file's language to its neighborhood.
|
|
104
|
+
Prevents the 'Apollo Paradox' and catches 'Trojan Horse' entities.
|
|
105
|
+
"""
|
|
106
|
+
# Default multipliers if no specific context rules apply
|
|
107
|
+
multipliers = {"memory": 1.0, "logic_bomb": 1.0, "flux": 1.0, "injection": 1.0}
|
|
108
|
+
|
|
109
|
+
file_lang = file_lang.lower()
|
|
110
|
+
folder_lang = folder_lang.lower() if folder_lang else file_lang
|
|
111
|
+
|
|
112
|
+
# Determine the ecosystem of the specific File
|
|
113
|
+
file_eco = "backend" # Default fallback
|
|
114
|
+
for eco, langs in self.ECOSYSTEMS.items():
|
|
115
|
+
if file_lang in langs:
|
|
116
|
+
file_eco = eco
|
|
117
|
+
break
|
|
118
|
+
|
|
119
|
+
# Determine the ecosystem of the surrounding Folder
|
|
120
|
+
folder_eco = "backend"
|
|
121
|
+
for eco, langs in self.ECOSYSTEMS.items():
|
|
122
|
+
if folder_lang in langs:
|
|
123
|
+
folder_eco = eco
|
|
124
|
+
break
|
|
125
|
+
|
|
126
|
+
# SCENARIO 1: The Entity matches the Context (Native)
|
|
127
|
+
if file_eco == folder_eco:
|
|
128
|
+
return self.NATIVE_WEIGHTS.get(file_eco, multipliers)
|
|
129
|
+
|
|
130
|
+
# SCENARIO 2: The Entity is an Alien (Context Mismatch)
|
|
131
|
+
alien_key = f"{file_eco}_in_{folder_eco}"
|
|
132
|
+
alien_penalties = self.ALIEN_WEIGHTS.get(alien_key, {})
|
|
133
|
+
|
|
134
|
+
# Apply standard weights of the file, but overwrite with severe alien penalties
|
|
135
|
+
base_weights = self.NATIVE_WEIGHTS.get(file_eco, multipliers).copy()
|
|
136
|
+
base_weights.update(alien_penalties)
|
|
137
|
+
|
|
138
|
+
if alien_penalties:
|
|
139
|
+
self.logger.warning(f"👽 ALIEN ENTITY DETECTED: {file_lang} file hiding in a {folder_eco} neighborhood. Applying severe penalties: {alien_penalties}")
|
|
82
140
|
|
|
141
|
+
return base_weights
|
|
142
|
+
|
|
83
143
|
def _calculate_silo_risk(self, authors: dict) -> float:
|
|
84
144
|
"""
|
|
85
145
|
Calculates the 'Bus Factor' risk of a file.
|
|
@@ -173,8 +233,13 @@ class SignalProcessor:
|
|
|
173
233
|
fc = self.TIER_VARS[tier]["fc"]
|
|
174
234
|
irc = self.TIER_VARS[tier]["irc"]
|
|
175
235
|
|
|
176
|
-
# Environmental Context
|
|
236
|
+
# Environmental Context (Path-based overrides)
|
|
177
237
|
mp_map = self._get_locational_multipliers(rel_path)
|
|
238
|
+
|
|
239
|
+
# ---> NEW: Context vs. Entity Ontology Matrix <---
|
|
240
|
+
# Fetch the folder's dominant language (Assumes your upstream parser injects this)
|
|
241
|
+
folder_lang = meta.get("metadata", {}).get("folder_dominant_lang", lang_id)
|
|
242
|
+
eco_mp = self._get_context_multipliers(lang_id, folder_lang)
|
|
178
243
|
|
|
179
244
|
self.logger.debug(f"[{rel_path}] Physics Calc | Lang: {lang_id} (Fc: {fc:.2f}, Irc: {irc})")
|
|
180
245
|
|
|
@@ -223,9 +288,9 @@ class SignalProcessor:
|
|
|
223
288
|
"civil_war": self._calc_civil_war(equations),
|
|
224
289
|
# --- THE SECURITY & VULNERABILITY LENSES ---
|
|
225
290
|
"obscured_payload": self._calc_obscured_payload(loc, equations, mp_map.get("obscured", 1.0)),
|
|
226
|
-
"logic_bomb": self._calc_logic_bomb(loc, equations, mp_map.get("logic_bomb", 1.0)),
|
|
227
|
-
"injection_surface": self._calc_injection_surface(loc, equations, mp_map.get("injection", 1.0)),
|
|
228
|
-
"memory_corruption": self._calc_memory_corruption(loc, equations, mp_map.get("memory", 1.0), lang_id),
|
|
291
|
+
"logic_bomb": self._calc_logic_bomb(loc, equations, mp_map.get("logic_bomb", 1.0) * eco_mp.get("logic_bomb", 1.0)),
|
|
292
|
+
"injection_surface": self._calc_injection_surface(loc, equations, mp_map.get("injection", 1.0) * eco_mp.get("injection", 1.0)),
|
|
293
|
+
"memory_corruption": self._calc_memory_corruption(loc, equations, mp_map.get("memory", 1.0) * eco_mp.get("memory", 1.0), lang_id),
|
|
229
294
|
"secrets_risk": self._calc_secrets_risk(loc, equations, mp_map.get("secrets", 1.0))
|
|
230
295
|
}
|
|
231
296
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gitgalaxy
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.2
|
|
4
4
|
Summary: A high-speed static analysis engine that sequences source code like DNA to map architectural risk and security threats.
|
|
5
5
|
Author: Joe Esquibel
|
|
6
6
|
License: PolyForm Noncommercial License 1.0.0
|
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
import re
|
|
2
|
-
import copy
|
|
3
|
-
import logging
|
|
4
|
-
from typing import Dict, Any
|
|
5
|
-
|
|
6
|
-
# ==============================================================================
|
|
7
|
-
# GitGalaxy Security Lens (Passive Threat Observer)
|
|
8
|
-
# Protocol: Glassworm, Trojan, and Exfiltration Hunting
|
|
9
|
-
# ==============================================================================
|
|
10
|
-
|
|
11
|
-
class SecurityLens:
|
|
12
|
-
"""
|
|
13
|
-
PURPOSE:
|
|
14
|
-
Acts as a Passive Observer within the GitGalaxy Physics Engine.
|
|
15
|
-
It runs alongside the standard architectural audit, silently collecting
|
|
16
|
-
malicious intent, obfuscation, and exfiltration metrics into RAM.
|
|
17
|
-
|
|
18
|
-
MECHANISM:
|
|
19
|
-
Injects high-priority threat signatures into the primary language rulesets
|
|
20
|
-
using a 'sec_' prefix. This ensures standard metrics (like tech debt) are
|
|
21
|
-
calculated normally, while security anomalies are passively cached for later extraction.
|
|
22
|
-
"""
|
|
23
|
-
|
|
24
|
-
def __init__(self, parent_logger: logging.Logger = None):
|
|
25
|
-
self.logger = parent_logger.getChild("security_lens") if parent_logger else logging.getLogger("security_lens")
|
|
26
|
-
self.logger.setLevel(logging.INFO)
|
|
27
|
-
|
|
28
|
-
# ======================================================================
|
|
29
|
-
# THE THREAT REGISTRY (Security Overlay V2 - O(N) Safe)
|
|
30
|
-
# ======================================================================
|
|
31
|
-
self.THREAT_SIGNATURES = {
|
|
32
|
-
# ------------------------------------------------------------------
|
|
33
|
-
# 1. THE GLASSWORM (Obfuscation & Heat Signatures)
|
|
34
|
-
# Targets decoding functions, massive blobs, and invisible steganography.
|
|
35
|
-
# ------------------------------------------------------------------
|
|
36
|
-
"heat_triggers": re.compile(
|
|
37
|
-
r'\b(?:atob|btoa|base64_decode|base64_encode|gzuncompress|str_rot13)\b|'
|
|
38
|
-
r'\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4}|'
|
|
39
|
-
r'(?:\w{15,}[ \t]*=[ \t]*["\'][A-Za-z0-9+/]{40,}={0,2}["\'])|'
|
|
40
|
-
r'[\u200B-\u200D\uFEFF\u200E\u200F\u202A-\u202E]', # Invisible Unicode
|
|
41
|
-
re.I
|
|
42
|
-
),
|
|
43
|
-
|
|
44
|
-
# ------------------------------------------------------------------
|
|
45
|
-
# 2. THE TROJAN (Identity Masking & Safety Bypasses)
|
|
46
|
-
# Targets cross-algorithm double-decoding and runtime security downgrades.
|
|
47
|
-
# ------------------------------------------------------------------
|
|
48
|
-
"safety_neg": re.compile(
|
|
49
|
-
r'\b(?:atob|btoa|base64_decode|gzinflate|gzuncompress|str_rot13|urldecode)[ \t]*\([ \t]*(?:atob|btoa|base64_decode|gzinflate|gzuncompress|str_rot13|urldecode)\b|'
|
|
50
|
-
r'\b(?:auto_prepend_file|auto_append_file)\b|'
|
|
51
|
-
r'\b(?:ini_set|ini_restore|putenv)[ \t]*\([ \t]*["\'](?:disable_functions|safe_mode|open_basedir|allow_url_fopen)["\'][ \t]*,[ \t]*["\']?(?:0|off|false|)["\']?\)|'
|
|
52
|
-
r'\b(?:disable_functions|safe_mode|open_basedir)\b[ \t]*=[ \t]*(?:off|0|false|""|\'\')|'
|
|
53
|
-
r'process\.env\.NODE_TLS_REJECT_UNAUTHORIZED[ \t]*=[ \t]*["\']?0["\']?|'
|
|
54
|
-
r'\b(?:verify|strictSSL|rejectUnauthorized|CURLOPT_SSL_VERIFYPEER)[ \t]*[=:,][ \t]*(?:False|false|0)\b',
|
|
55
|
-
re.I
|
|
56
|
-
),
|
|
57
|
-
|
|
58
|
-
# ------------------------------------------------------------------
|
|
59
|
-
# 3. EXFILTRATION VECTORS (System Gravity)
|
|
60
|
-
# Targets dynamic outbound connections, tunneling proxies, and DNS exfiltration.
|
|
61
|
-
# ------------------------------------------------------------------
|
|
62
|
-
"io": re.compile(
|
|
63
|
-
r'\b(?:fetch|XMLHttpRequest|WebSocket|http\.request|https\.request|requests\.(?:post|put|get)|urllib\.request\.urlopen)\b\s*\(|'
|
|
64
|
-
r'\b(?:curl_exec|fsockopen|pfsockopen|stream_socket_client|file_get_contents)\b\s*\(|'
|
|
65
|
-
r'\b(?:dns_get_record|gethostbyname|socket\.gethostbyname|resolve(?:4|6|Cname|Txt)?)\b\s*\(|'
|
|
66
|
-
r'(?:https?|ftp|tcp|udp|wss?):\/\/(?:(?:\d{1,3}\.){3}\d{1,3}|\[[0-9a-fA-F:]+\]|.*?\.(?:ngrok\.io|ngrok-free\.app|localtunnel\.me|pastebin\.com|workers\.dev|s3\.amazonaws\.com|requestbin\.net|pipedream\.net))',
|
|
67
|
-
re.I | re.X
|
|
68
|
-
),
|
|
69
|
-
|
|
70
|
-
# ------------------------------------------------------------------
|
|
71
|
-
# 4. THE EXECUTIONER (Dynamic Payloads)
|
|
72
|
-
# HARDENED: Unbounded repetitions clamped to prevent ReDoS on minified code.
|
|
73
|
-
# ------------------------------------------------------------------
|
|
74
|
-
"danger": re.compile(
|
|
75
|
-
r'\b(?:eval|Function|setTimeout|setInterval)\b\s*\(\s*(?:atob|base64|["\']|`)|'
|
|
76
|
-
r'\b(?:document\.write|location\.replace|assert|create_function|passthru|shell_exec|system)\b|'
|
|
77
|
-
r'child_process\.(?:exec|spawn|fork)|'
|
|
78
|
-
# Clamped string concatenation to {1,15} to kill exponential backtracking
|
|
79
|
-
r'(?:window|global|this|globalThis)\[[ \t]*(?:["\'][a-zA-Z]["\'][ \t]*\+[ \t]*){1,15}["\'][a-zA-Z]["\'][ \t]*\][ \t]*\(|'
|
|
80
|
-
r'\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\s*\(\s*\$_(?:POST|GET|COOKIE|REQUEST|HEADERS)|'
|
|
81
|
-
r'getattr\s*\(\s*__import__\s*\(|__builtins__\[|Assembly\.Load\s*\(',
|
|
82
|
-
re.I | re.X
|
|
83
|
-
),
|
|
84
|
-
|
|
85
|
-
# ------------------------------------------------------------------
|
|
86
|
-
# 5. ENVIRONMENT POISONING (State Flux)
|
|
87
|
-
# Targets prototype pollution, native function hooking, and global overrides.
|
|
88
|
-
# ------------------------------------------------------------------
|
|
89
|
-
"flux": re.compile(
|
|
90
|
-
r'\b[A-Za-z0-9_]+\.prototype\.[A-Za-z0-9_]+[ \t]*=|'
|
|
91
|
-
r'\.__proto__[ \t]*=[ \t]*[{a-zA-Z]|'
|
|
92
|
-
r'\b(?:window|global|globalThis|document)\.(?:fetch|eval|setTimeout|setInterval|Promise|console|JSON)[ \t]*=|'
|
|
93
|
-
r'\$(?:GLOBALS|_(?:SERVER|GET|POST|COOKIE|REQUEST|ENV|SESSION))\[[^\]]+\][ \t]*=[ \t]*[^=]|'
|
|
94
|
-
r'\bextract[ \t]*\([ \t]*\$(?:_(?:GET|POST|REQUEST|COOKIE)|GLOBALS)\b|'
|
|
95
|
-
r'\b__builtins__\[[^\]]+\][ \t]*=|'
|
|
96
|
-
r'\bsys\.modules\[[^\]]+\][ \t]*=',
|
|
97
|
-
re.I
|
|
98
|
-
),
|
|
99
|
-
|
|
100
|
-
# ------------------------------------------------------------------
|
|
101
|
-
# 6. SHADOW LOGIC (Necrosis / Graveyard)
|
|
102
|
-
# O(N) SAFE: Fast block scanning bounded to 500 chars to prevent ReDoS.
|
|
103
|
-
# ------------------------------------------------------------------
|
|
104
|
-
"graveyard": re.compile(
|
|
105
|
-
r'(?://|#|--)[^\n]*?\b(?:http|bash|curl|wget|eval|base64|nc\s+-e|/dev/tcp)\b|'
|
|
106
|
-
r'/\*(?:(?!\*/).){0,500}?\b(?:http|bash|curl|wget|eval|base64|nc\s+-e|/dev/tcp)\b',
|
|
107
|
-
re.I
|
|
108
|
-
),
|
|
109
|
-
|
|
110
|
-
# ------------------------------------------------------------------
|
|
111
|
-
# 7. SUB-ATOMIC DECRYPTION (Bitwise Hits)
|
|
112
|
-
# HARDENED: Replaced .*? with bounded character exclusions.
|
|
113
|
-
# ------------------------------------------------------------------
|
|
114
|
-
"bitwise_hits": re.compile(
|
|
115
|
-
# Clamped to {2,20} and {3,20} to prevent infinite runaway loops on data arrays
|
|
116
|
-
r'\b\w+[ \t]*=[ \t]*(?:\w+[ \t]*\^[ \t]*\w+[ \t]*){2,20}|'
|
|
117
|
-
r'(?:\w+\[[^\]\n]{1,50}\][ \t]*\^[ \t]*=?[ \t]*(?:0x[0-9a-fA-F]+|\d+|\w+)[ \t]*;[ \t]*){3,20}',
|
|
118
|
-
re.I
|
|
119
|
-
),
|
|
120
|
-
# ------------------------------------------------------------------
|
|
121
|
-
# 8. SHADOW IMPORTS (The Switcharoo / Steganography)
|
|
122
|
-
# Targets legitimate code attempting to import, require, or execute
|
|
123
|
-
# payloads hidden inside non-executable media or data files.
|
|
124
|
-
# ------------------------------------------------------------------
|
|
125
|
-
"shadow_imports": re.compile(
|
|
126
|
-
r'\b(?:require|include|import|require_once|include_once|source|load|dofile)\b\s*\(?\s*'
|
|
127
|
-
r'["\'][^"\']+\.(?:png|jpg|jpeg|gif|ico|pdf|zip|tar|dat|tmp|log|txt|csv|wav|mp3)["\']',
|
|
128
|
-
re.I
|
|
129
|
-
),
|
|
130
|
-
# ------------------------------------------------------------------
|
|
131
|
-
# 9. UNICODE SMUGGLING (Homoglyphs & Typosquatting)
|
|
132
|
-
# Targets look-alike characters (Cyrillic, Greek, Hangul Filler)
|
|
133
|
-
# used to hijack legitimate imports or disguise network requests.
|
|
134
|
-
# ------------------------------------------------------------------
|
|
135
|
-
"homoglyphs": re.compile(
|
|
136
|
-
r'\b(?:import|from|require|include|require_once|fetch|XMLHttpRequest)\b'
|
|
137
|
-
r'[^\n]*?(?:[\u0400-\u04FF]|' # Cyrillic (e.g., false 'a', 'e', 'o')
|
|
138
|
-
r'[\u0370-\u03FF]|' # Greek
|
|
139
|
-
r'[\u1D400-\u1D7FF]|' # Math Alphanumerics
|
|
140
|
-
r'\u3164)', # Hangul Filler (Invisible whitespace)
|
|
141
|
-
re.I
|
|
142
|
-
),
|
|
143
|
-
# ------------------------------------------------------------------
|
|
144
|
-
# 10. THE VAULT DOOR (Credential & Secret Leaks)
|
|
145
|
-
# Universal RHS-aware secret detection. Demands string literals
|
|
146
|
-
# of at least 16 characters to prevent false positives on booleans/ints.
|
|
147
|
-
# ------------------------------------------------------------------
|
|
148
|
-
"private_info": re.compile(
|
|
149
|
-
r"\b(password|secret|token|api[_-]?key|client[_-]?secret|credentials|private[_-]?key|auth[_-]?token)\b[ \t]*(?:[:=]|=>)[ \t]*[\"'][A-Za-z0-9\-_+/=]{16,}[\"']",
|
|
150
|
-
re.I
|
|
151
|
-
),
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
def arm_lens(self, base_registry: Dict[str, Any], target_languages: list = None) -> Dict[str, Any]:
|
|
155
|
-
"""
|
|
156
|
-
Injects the threat signatures as PASSIVE OBSERVERS into the registry.
|
|
157
|
-
They will be scanned by the Splicer and cached in RAM, but will NOT destroy
|
|
158
|
-
the standard architectural calculations.
|
|
159
|
-
"""
|
|
160
|
-
self.logger.info("Arming Security Lens: Injecting Passive Observers into Registry...")
|
|
161
|
-
|
|
162
|
-
secure_registry = copy.deepcopy(base_registry)
|
|
163
|
-
|
|
164
|
-
if not target_languages:
|
|
165
|
-
target_languages = ['javascript', 'typescript', 'php', 'python', 'ruby', 'shell', 'powershell']
|
|
166
|
-
|
|
167
|
-
for lang in target_languages:
|
|
168
|
-
if lang in secure_registry and 'rules' in secure_registry[lang]:
|
|
169
|
-
rules = secure_registry[lang]['rules']
|
|
170
|
-
|
|
171
|
-
# --- PASSIVE OBSERVER INJECTION ---
|
|
172
|
-
for dimension, threat_regex in self.THREAT_SIGNATURES.items():
|
|
173
|
-
# By prefixing with "sec_", we preserve the original "io" or "danger" rules
|
|
174
|
-
# The Splicer automatically scans any key in this dictionary, meaning
|
|
175
|
-
# these hits will quietly accumulate in the file's 'equations' output in RAM.
|
|
176
|
-
rules[f"sec_{dimension}"] = threat_regex
|
|
177
|
-
|
|
178
|
-
self.logger.debug(f"Passive Security Sensors attached to '{lang}'.")
|
|
179
|
-
|
|
180
|
-
self.logger.info(f"Passive Security Lens active across {len(target_languages)} ecosystems.")
|
|
181
|
-
return secure_registry
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|