gitgalaxy 1.0.9__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.0.9 → gitgalaxy-1.1.2}/PKG-INFO +1 -1
- {gitgalaxy-1.0.9 → gitgalaxy-1.1.2}/gitgalaxy/audit_recorder.py +4 -6
- {gitgalaxy-1.0.9 → gitgalaxy-1.1.2}/gitgalaxy/chronometer.py +1 -1
- {gitgalaxy-1.0.9 → gitgalaxy-1.1.2}/gitgalaxy/detector.py +1 -1
- {gitgalaxy-1.0.9 → gitgalaxy-1.1.2}/gitgalaxy/galaxyscope.py +91 -11
- gitgalaxy-1.0.9/gitgalaxy/gitgalaxy_standards_v011.py → gitgalaxy-1.1.2/gitgalaxy/gitgalaxy_standards_v1.py +74 -0
- {gitgalaxy-1.0.9 → gitgalaxy-1.1.2}/gitgalaxy/gpu_recorder.py +9 -13
- {gitgalaxy-1.0.9 → gitgalaxy-1.1.2}/gitgalaxy/guidestar_lens.py +1 -1
- {gitgalaxy-1.0.9 → gitgalaxy-1.1.2}/gitgalaxy/language_lens.py +1 -1
- {gitgalaxy-1.0.9 → gitgalaxy-1.1.2}/gitgalaxy/llm_recorder.py +7 -7
- {gitgalaxy-1.0.9 → gitgalaxy-1.1.2}/gitgalaxy/prism.py +1 -1
- gitgalaxy-1.1.2/gitgalaxy/security_lens.py +174 -0
- {gitgalaxy-1.0.9 → gitgalaxy-1.1.2}/gitgalaxy/signal_processor.py +71 -6
- {gitgalaxy-1.0.9 → gitgalaxy-1.1.2}/gitgalaxy.egg-info/PKG-INFO +1 -1
- {gitgalaxy-1.0.9 → gitgalaxy-1.1.2}/gitgalaxy.egg-info/SOURCES.txt +1 -1
- {gitgalaxy-1.0.9 → gitgalaxy-1.1.2}/pyproject.toml +1 -1
- gitgalaxy-1.0.9/gitgalaxy/security_lens.py +0 -181
- {gitgalaxy-1.0.9 → gitgalaxy-1.1.2}/LICENSE +0 -0
- {gitgalaxy-1.0.9 → gitgalaxy-1.1.2}/README.md +0 -0
- {gitgalaxy-1.0.9 → gitgalaxy-1.1.2}/gitgalaxy/__init__.py +0 -0
- {gitgalaxy-1.0.9 → gitgalaxy-1.1.2}/gitgalaxy/aperture.py +0 -0
- {gitgalaxy-1.0.9 → gitgalaxy-1.1.2}/gitgalaxy/record_keeper.py +0 -0
- {gitgalaxy-1.0.9 → gitgalaxy-1.1.2}/gitgalaxy/spectral_auditor.py +0 -0
- {gitgalaxy-1.0.9 → gitgalaxy-1.1.2}/gitgalaxy.egg-info/dependency_links.txt +0 -0
- {gitgalaxy-1.0.9 → gitgalaxy-1.1.2}/gitgalaxy.egg-info/entry_points.txt +0 -0
- {gitgalaxy-1.0.9 → gitgalaxy-1.1.2}/gitgalaxy.egg-info/top_level.txt +0 -0
- {gitgalaxy-1.0.9 → 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.
|
|
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
|
|
@@ -14,7 +14,7 @@ import re
|
|
|
14
14
|
from datetime import datetime
|
|
15
15
|
from pathlib import Path
|
|
16
16
|
from typing import Any
|
|
17
|
-
from . import
|
|
17
|
+
from . import gitgalaxy_standards_v1 as config
|
|
18
18
|
|
|
19
19
|
# ==============================================================================
|
|
20
20
|
# GitGalaxy Phase 8 & 9: Astrograph Auditor (The Forensic Record)
|
|
@@ -365,11 +365,9 @@ class AuditRecorder:
|
|
|
365
365
|
"6. Visible Matter (Scanned Artifacts)": pretty_constellations
|
|
366
366
|
}
|
|
367
367
|
|
|
368
|
-
# ---
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
safe_filename = Path(output_path).name
|
|
372
|
-
target_path = base_dir / safe_filename
|
|
368
|
+
# --- THE FIX ---
|
|
369
|
+
# Convert the output_path handed to us by the orchestrator into a Path object
|
|
370
|
+
target_path = Path(output_path)
|
|
373
371
|
|
|
374
372
|
try:
|
|
375
373
|
with open(target_path, 'w', encoding='utf-8') as f:
|
|
@@ -13,7 +13,7 @@ import logging
|
|
|
13
13
|
import time
|
|
14
14
|
from pathlib import Path
|
|
15
15
|
from typing import Dict, Any, Optional, List, Tuple
|
|
16
|
-
from . import
|
|
16
|
+
from . import gitgalaxy_standards_v1 as config
|
|
17
17
|
|
|
18
18
|
# ==============================================================================
|
|
19
19
|
# GitGalaxy Phase 3: Chronometer (Temporal Sensor)
|
|
@@ -13,7 +13,7 @@ import hashlib
|
|
|
13
13
|
import logging
|
|
14
14
|
import time
|
|
15
15
|
from typing import Dict, List, Any, TypedDict, Optional, Tuple
|
|
16
|
-
from . import
|
|
16
|
+
from . import gitgalaxy_standards_v1 as config
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
# ==============================================================================
|
|
@@ -36,7 +36,7 @@ from .audit_recorder import AuditRecorder
|
|
|
36
36
|
from .llm_recorder import LLMRecorder
|
|
37
37
|
from .security_lens import SecurityLens
|
|
38
38
|
# Load Universal Laws from config
|
|
39
|
-
from . import
|
|
39
|
+
from . import gitgalaxy_standards_v1 as scanning_config
|
|
40
40
|
|
|
41
41
|
logger = logging.getLogger("GalaxyScope")
|
|
42
42
|
|
|
@@ -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,10 +109,30 @@ 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()
|
|
122
|
+
|
|
123
|
+
def resolve_mission_control(target_name: str) -> Path:
|
|
124
|
+
"""Routes reports to a .env path, or defaults to the current directory."""
|
|
125
|
+
env_path = os.environ.get("GITGALAXY_DATA_DIR")
|
|
126
|
+
|
|
127
|
+
if env_path:
|
|
128
|
+
# If the environment variable is set, drop the files EXACTLY there
|
|
129
|
+
mission_dir = Path(env_path)
|
|
130
|
+
else:
|
|
131
|
+
# If no variable (like on a user's machine), make a safe subfolder so we don't make a mess
|
|
132
|
+
mission_dir = Path.cwd() / "galaxy_reports" / target_name
|
|
133
|
+
|
|
134
|
+
mission_dir.mkdir(parents=True, exist_ok=True)
|
|
135
|
+
return mission_dir
|
|
110
136
|
|
|
111
137
|
def _process_file_worker(rel_path: str) -> Dict[str, Any]:
|
|
112
138
|
"""Processes a single file path using the worker's cached hardware modules."""
|
|
@@ -139,6 +165,12 @@ def _process_file_worker(rel_path: str) -> Dict[str, Any]:
|
|
|
139
165
|
splicer_cache = _worker_state['splicer_cache']
|
|
140
166
|
tokenizer = _worker_state['word_tokenizer']
|
|
141
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
|
+
|
|
142
174
|
has_prior, intent_vector = guidestar.get_intent_status(full_path_str)
|
|
143
175
|
observation = {"rel_path": rel_path, "status": "filtered", "reason": "Aperture block", "data": {}}
|
|
144
176
|
|
|
@@ -298,6 +330,16 @@ class Orchestrator:
|
|
|
298
330
|
self.audit_recorder = AuditRecorder(parent_logger=logger)
|
|
299
331
|
self.llm_recorder = LLMRecorder(parent_logger=logger)
|
|
300
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
|
+
|
|
301
343
|
# State Arrays
|
|
302
344
|
self.census: Set[str] = set()
|
|
303
345
|
self.stem_map: Dict[str, str] = {}
|
|
@@ -360,6 +402,11 @@ class Orchestrator:
|
|
|
360
402
|
# Pass the array into the function, and merge the results directly
|
|
361
403
|
summary["singularity"].update(self._summarize_anomalies(total_singularity))
|
|
362
404
|
|
|
405
|
+
# --- THE NEW ROUTER ---
|
|
406
|
+
mission_dir = resolve_mission_control(self.root.name)
|
|
407
|
+
output_file = str(mission_dir / Path(output_file).name)
|
|
408
|
+
# ----------------------
|
|
409
|
+
|
|
363
410
|
# ==========================================================
|
|
364
411
|
# PHASE 8: AUDIT RECORDER (Non-Destructive Forensic Fork)
|
|
365
412
|
# ==========================================================
|
|
@@ -712,6 +759,25 @@ class Orchestrator:
|
|
|
712
759
|
"""Pass 2: Universal Exposure Framework & Signal Processing."""
|
|
713
760
|
logger.info("PASS_2: Calculating structural physics and Tiered Normalization.")
|
|
714
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
|
+
|
|
715
781
|
# --- NEW: CALCULATE THE GLOBAL TEST UMBRELLA ---
|
|
716
782
|
total_loc = 0
|
|
717
783
|
test_loc = 0
|
|
@@ -732,6 +798,15 @@ class Orchestrator:
|
|
|
732
798
|
|
|
733
799
|
for rel_path, meta in self.cryolink.items():
|
|
734
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
|
+
|
|
735
810
|
meta["temporal_telemetry"] = self.chronometer.get_temporal_signals(rel_path)
|
|
736
811
|
meta["authors"] = meta["temporal_telemetry"].get("authors", {})
|
|
737
812
|
stem = Path(rel_path).stem.lower()
|
|
@@ -1060,15 +1135,20 @@ def main():
|
|
|
1060
1135
|
merged_langs[lang]['rules'].update(rules_patch)
|
|
1061
1136
|
logging.debug(f" -> Patched '{lang}' geometry rules.")
|
|
1062
1137
|
|
|
1063
|
-
#
|
|
1064
|
-
#
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
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
|
+
# -------------------------------
|
|
1072
1152
|
|
|
1073
1153
|
# ---------------------------------------------------------
|
|
1074
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
|
# ------------------------------------------------------------------------------
|
|
@@ -12,7 +12,7 @@ import logging
|
|
|
12
12
|
import gc
|
|
13
13
|
from pathlib import Path
|
|
14
14
|
from typing import List, Dict, Any, Optional
|
|
15
|
-
from . import
|
|
15
|
+
from . import gitgalaxy_standards_v1 as config
|
|
16
16
|
|
|
17
17
|
# ==============================================================================
|
|
18
18
|
# GitGalaxy Phase 9: GPU Recorder (Formerly RecordKeeper)
|
|
@@ -291,21 +291,17 @@ class GPURecorder:
|
|
|
291
291
|
return registry.index(val)
|
|
292
292
|
|
|
293
293
|
def save_minified(self, payload: Dict[str, Any], filename: str):
|
|
294
|
-
"""Serializes with maximum JSON compression to
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
# 2. Ensure the directory exists (creates parent folders if needed)
|
|
300
|
-
base_dir.mkdir(parents=True, exist_ok=True)
|
|
294
|
+
"""Serializes with maximum JSON compression to the provided output path."""
|
|
295
|
+
from pathlib import Path
|
|
296
|
+
|
|
297
|
+
# Convert the path handed to us by the orchestrator into a Path object
|
|
298
|
+
target_path = Path(filename)
|
|
301
299
|
|
|
302
|
-
#
|
|
303
|
-
|
|
304
|
-
safe_filename = Path(filename).name
|
|
305
|
-
target_path = base_dir / safe_filename
|
|
300
|
+
# Ensure the parent directory exists just to be safe
|
|
301
|
+
target_path.parent.mkdir(parents=True, exist_ok=True)
|
|
306
302
|
|
|
307
303
|
try:
|
|
308
|
-
#
|
|
304
|
+
# Save using the safe target_path
|
|
309
305
|
with open(target_path, 'w', encoding='utf-8') as f:
|
|
310
306
|
json.dump(payload, f, indent=None, separators=(',', ':'), ensure_ascii=False)
|
|
311
307
|
self.logger.info(f"GPU Manifest Sealed -> {target_path}")
|
|
@@ -13,7 +13,7 @@ import logging
|
|
|
13
13
|
import fnmatch
|
|
14
14
|
from pathlib import Path
|
|
15
15
|
from typing import Dict, Any, Optional, List, Tuple, Union
|
|
16
|
-
from . import
|
|
16
|
+
from . import gitgalaxy_standards_v1 as config
|
|
17
17
|
|
|
18
18
|
# ==============================================================================
|
|
19
19
|
# GitGalaxy Phase 0.5: Sector Intelligence (The GuideStar Lens)
|
|
@@ -13,7 +13,7 @@ import time
|
|
|
13
13
|
import logging
|
|
14
14
|
from pathlib import Path
|
|
15
15
|
from typing import Tuple, Optional, Dict, List, Any, TypedDict, Union
|
|
16
|
-
from .
|
|
16
|
+
from .gitgalaxy_standards_v1 import EXACT_FILE_MATCH, LANGUAGE_DEFINITIONS, LENS_CONFIG
|
|
17
17
|
|
|
18
18
|
# ==============================================================================
|
|
19
19
|
# GitGalaxy Phase 1: The Entity Census (The Linguistic Detector Chip)
|
|
@@ -13,7 +13,7 @@ import statistics
|
|
|
13
13
|
from pathlib import Path
|
|
14
14
|
from datetime import datetime
|
|
15
15
|
from typing import List, Dict, Any, Optional
|
|
16
|
-
from . import
|
|
16
|
+
from . import gitgalaxy_standards_v1 as config
|
|
17
17
|
|
|
18
18
|
# ==============================================================================
|
|
19
19
|
# GitGalaxy Phase 10: LLM Recorder (The AI Translation Layer)
|
|
@@ -58,13 +58,13 @@ class LLMRecorder:
|
|
|
58
58
|
if forensic_report is None:
|
|
59
59
|
forensic_report = {}
|
|
60
60
|
|
|
61
|
-
# --- ABSOLUTE ROUTING LOGIC (Matching Audit Recorder) ---
|
|
62
|
-
base_dir = Path("/srv/storage_16tb/projects/gitgalaxy/data")
|
|
63
|
-
base_dir.mkdir(parents=True, exist_ok=True)
|
|
64
61
|
|
|
65
62
|
target_name = session_meta.get("target", "unknown_project")
|
|
66
|
-
|
|
67
|
-
|
|
63
|
+
safe_dir = Path(output_dir)
|
|
64
|
+
|
|
65
|
+
# Use safe_dir instead of base_dir!
|
|
66
|
+
output_path_md = safe_dir / f"{target_name}_galaxy_llm.md"
|
|
67
|
+
output_path_db = safe_dir / f"{target_name}_galaxy_graph.sqlite"
|
|
68
68
|
|
|
69
69
|
self.logger.info(f"Initiating LLM Artifact Generation for '{target_name}'...")
|
|
70
70
|
|
|
@@ -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.")
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import re
|
|
11
11
|
import logging
|
|
12
12
|
from typing import Dict, List, Optional, Tuple, Any, TypedDict
|
|
13
|
-
from .
|
|
13
|
+
from .gitgalaxy_standards_v1 import LENS_CONFIG, PRISM_CONFIG
|
|
14
14
|
|
|
15
15
|
# ==============================================================================
|
|
16
16
|
# GitGalaxy Phase 2: Structural Refractor (The Prism)
|
|
@@ -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
|
|
@@ -12,7 +12,7 @@ import logging
|
|
|
12
12
|
import re
|
|
13
13
|
import statistics
|
|
14
14
|
from typing import Dict, Any, List, Optional, Tuple
|
|
15
|
-
from . import
|
|
15
|
+
from . import gitgalaxy_standards_v1 as config
|
|
16
16
|
|
|
17
17
|
# ==============================================================================
|
|
18
18
|
# GitGalaxy Phase 4: Signal Processor (The Physics Engine)
|
|
@@ -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.
|
|
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
|
|
@@ -7,7 +7,7 @@ gitgalaxy/audit_recorder.py
|
|
|
7
7
|
gitgalaxy/chronometer.py
|
|
8
8
|
gitgalaxy/detector.py
|
|
9
9
|
gitgalaxy/galaxyscope.py
|
|
10
|
-
gitgalaxy/
|
|
10
|
+
gitgalaxy/gitgalaxy_standards_v1.py
|
|
11
11
|
gitgalaxy/gpu_recorder.py
|
|
12
12
|
gitgalaxy/guidestar_lens.py
|
|
13
13
|
gitgalaxy/language_lens.py
|
|
@@ -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
|