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.
Files changed (27) hide show
  1. {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/PKG-INFO +1 -1
  2. {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/galaxyscope.py +71 -10
  3. {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/gitgalaxy_standards_v1.py +74 -0
  4. {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/llm_recorder.py +1 -1
  5. gitgalaxy-1.1.2/gitgalaxy/security_lens.py +174 -0
  6. {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/signal_processor.py +70 -5
  7. {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy.egg-info/PKG-INFO +1 -1
  8. {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/pyproject.toml +1 -1
  9. gitgalaxy-1.1.1/gitgalaxy/security_lens.py +0 -181
  10. {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/LICENSE +0 -0
  11. {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/README.md +0 -0
  12. {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/__init__.py +0 -0
  13. {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/aperture.py +0 -0
  14. {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/audit_recorder.py +0 -0
  15. {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/chronometer.py +0 -0
  16. {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/detector.py +0 -0
  17. {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/gpu_recorder.py +0 -0
  18. {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/guidestar_lens.py +0 -0
  19. {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/language_lens.py +0 -0
  20. {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/prism.py +0 -0
  21. {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/record_keeper.py +0 -0
  22. {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy/spectral_auditor.py +0 -0
  23. {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy.egg-info/SOURCES.txt +0 -0
  24. {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy.egg-info/dependency_links.txt +0 -0
  25. {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy.egg-info/entry_points.txt +0 -0
  26. {gitgalaxy-1.1.1 → gitgalaxy-1.1.2}/gitgalaxy.egg-info/top_level.txt +0 -0
  27. {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.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
- # --- NEW: SECURITY LENS INTEGRATION ---
1084
- # =========================================================
1085
- logging.info("🛡️ SECURITY LENS ACTIVE: Passively monitoring for Threat Signatures.")
1086
- lens = SecurityLens(parent_logger=logging.getLogger())
1087
-
1088
- # Unconditionally inject the 'sec_' prefixed observers into the registry
1089
- merged_langs = lens.arm_lens(merged_langs)
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
- self.logger.info(f"Signal Processor Online | 13-Point Risk Schema loaded.")
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.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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "gitgalaxy"
7
- version = "1.1.1"
7
+ version = "1.1.2"
8
8
  authors = [
9
9
  { name="Joe Esquibel" },
10
10
  ]
@@ -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