crackerjack 0.33.0__py3-none-any.whl → 0.33.1__py3-none-any.whl

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.

Potentially problematic release.


This version of crackerjack might be problematic. Click here for more details.

Files changed (198) hide show
  1. crackerjack/__main__.py +1350 -34
  2. crackerjack/adapters/__init__.py +17 -0
  3. crackerjack/adapters/lsp_client.py +358 -0
  4. crackerjack/adapters/rust_tool_adapter.py +194 -0
  5. crackerjack/adapters/rust_tool_manager.py +193 -0
  6. crackerjack/adapters/skylos_adapter.py +231 -0
  7. crackerjack/adapters/zuban_adapter.py +560 -0
  8. crackerjack/agents/base.py +7 -3
  9. crackerjack/agents/coordinator.py +271 -33
  10. crackerjack/agents/documentation_agent.py +9 -15
  11. crackerjack/agents/dry_agent.py +3 -15
  12. crackerjack/agents/formatting_agent.py +1 -1
  13. crackerjack/agents/import_optimization_agent.py +36 -180
  14. crackerjack/agents/performance_agent.py +17 -98
  15. crackerjack/agents/performance_helpers.py +7 -31
  16. crackerjack/agents/proactive_agent.py +1 -3
  17. crackerjack/agents/refactoring_agent.py +16 -85
  18. crackerjack/agents/refactoring_helpers.py +7 -42
  19. crackerjack/agents/security_agent.py +9 -48
  20. crackerjack/agents/test_creation_agent.py +356 -513
  21. crackerjack/agents/test_specialist_agent.py +0 -4
  22. crackerjack/api.py +6 -25
  23. crackerjack/cli/cache_handlers.py +204 -0
  24. crackerjack/cli/cache_handlers_enhanced.py +683 -0
  25. crackerjack/cli/facade.py +100 -0
  26. crackerjack/cli/handlers.py +224 -9
  27. crackerjack/cli/interactive.py +6 -4
  28. crackerjack/cli/options.py +642 -55
  29. crackerjack/cli/utils.py +2 -1
  30. crackerjack/code_cleaner.py +58 -117
  31. crackerjack/config/global_lock_config.py +8 -48
  32. crackerjack/config/hooks.py +53 -62
  33. crackerjack/core/async_workflow_orchestrator.py +24 -34
  34. crackerjack/core/autofix_coordinator.py +3 -17
  35. crackerjack/core/enhanced_container.py +4 -13
  36. crackerjack/core/file_lifecycle.py +12 -89
  37. crackerjack/core/performance.py +2 -2
  38. crackerjack/core/performance_monitor.py +15 -55
  39. crackerjack/core/phase_coordinator.py +104 -204
  40. crackerjack/core/resource_manager.py +14 -90
  41. crackerjack/core/service_watchdog.py +62 -95
  42. crackerjack/core/session_coordinator.py +149 -0
  43. crackerjack/core/timeout_manager.py +14 -72
  44. crackerjack/core/websocket_lifecycle.py +13 -78
  45. crackerjack/core/workflow_orchestrator.py +171 -174
  46. crackerjack/docs/INDEX.md +11 -0
  47. crackerjack/docs/generated/api/API_REFERENCE.md +10895 -0
  48. crackerjack/docs/generated/api/CLI_REFERENCE.md +109 -0
  49. crackerjack/docs/generated/api/CROSS_REFERENCES.md +1755 -0
  50. crackerjack/docs/generated/api/PROTOCOLS.md +3 -0
  51. crackerjack/docs/generated/api/SERVICES.md +1252 -0
  52. crackerjack/documentation/__init__.py +31 -0
  53. crackerjack/documentation/ai_templates.py +756 -0
  54. crackerjack/documentation/dual_output_generator.py +765 -0
  55. crackerjack/documentation/mkdocs_integration.py +518 -0
  56. crackerjack/documentation/reference_generator.py +977 -0
  57. crackerjack/dynamic_config.py +55 -50
  58. crackerjack/executors/async_hook_executor.py +10 -15
  59. crackerjack/executors/cached_hook_executor.py +117 -43
  60. crackerjack/executors/hook_executor.py +8 -34
  61. crackerjack/executors/hook_lock_manager.py +26 -183
  62. crackerjack/executors/individual_hook_executor.py +13 -11
  63. crackerjack/executors/lsp_aware_hook_executor.py +270 -0
  64. crackerjack/executors/tool_proxy.py +417 -0
  65. crackerjack/hooks/lsp_hook.py +79 -0
  66. crackerjack/intelligence/adaptive_learning.py +25 -10
  67. crackerjack/intelligence/agent_orchestrator.py +2 -5
  68. crackerjack/intelligence/agent_registry.py +34 -24
  69. crackerjack/intelligence/agent_selector.py +5 -7
  70. crackerjack/interactive.py +17 -6
  71. crackerjack/managers/async_hook_manager.py +0 -1
  72. crackerjack/managers/hook_manager.py +79 -1
  73. crackerjack/managers/publish_manager.py +44 -8
  74. crackerjack/managers/test_command_builder.py +1 -15
  75. crackerjack/managers/test_executor.py +1 -3
  76. crackerjack/managers/test_manager.py +98 -7
  77. crackerjack/managers/test_manager_backup.py +10 -9
  78. crackerjack/mcp/cache.py +2 -2
  79. crackerjack/mcp/client_runner.py +1 -1
  80. crackerjack/mcp/context.py +191 -68
  81. crackerjack/mcp/dashboard.py +7 -5
  82. crackerjack/mcp/enhanced_progress_monitor.py +31 -28
  83. crackerjack/mcp/file_monitor.py +30 -23
  84. crackerjack/mcp/progress_components.py +31 -21
  85. crackerjack/mcp/progress_monitor.py +50 -53
  86. crackerjack/mcp/rate_limiter.py +6 -6
  87. crackerjack/mcp/server_core.py +17 -16
  88. crackerjack/mcp/service_watchdog.py +2 -1
  89. crackerjack/mcp/state.py +4 -7
  90. crackerjack/mcp/task_manager.py +11 -9
  91. crackerjack/mcp/tools/core_tools.py +173 -32
  92. crackerjack/mcp/tools/error_analyzer.py +3 -2
  93. crackerjack/mcp/tools/execution_tools.py +8 -10
  94. crackerjack/mcp/tools/execution_tools_backup.py +42 -30
  95. crackerjack/mcp/tools/intelligence_tool_registry.py +7 -5
  96. crackerjack/mcp/tools/intelligence_tools.py +5 -2
  97. crackerjack/mcp/tools/monitoring_tools.py +33 -70
  98. crackerjack/mcp/tools/proactive_tools.py +24 -11
  99. crackerjack/mcp/tools/progress_tools.py +5 -8
  100. crackerjack/mcp/tools/utility_tools.py +20 -14
  101. crackerjack/mcp/tools/workflow_executor.py +62 -40
  102. crackerjack/mcp/websocket/app.py +8 -0
  103. crackerjack/mcp/websocket/endpoints.py +352 -357
  104. crackerjack/mcp/websocket/jobs.py +40 -57
  105. crackerjack/mcp/websocket/monitoring_endpoints.py +2935 -0
  106. crackerjack/mcp/websocket/server.py +7 -25
  107. crackerjack/mcp/websocket/websocket_handler.py +6 -17
  108. crackerjack/mixins/__init__.py +0 -2
  109. crackerjack/mixins/error_handling.py +1 -70
  110. crackerjack/models/config.py +12 -1
  111. crackerjack/models/config_adapter.py +49 -1
  112. crackerjack/models/protocols.py +122 -122
  113. crackerjack/models/resource_protocols.py +55 -210
  114. crackerjack/monitoring/ai_agent_watchdog.py +13 -13
  115. crackerjack/monitoring/metrics_collector.py +426 -0
  116. crackerjack/monitoring/regression_prevention.py +8 -8
  117. crackerjack/monitoring/websocket_server.py +643 -0
  118. crackerjack/orchestration/advanced_orchestrator.py +11 -6
  119. crackerjack/orchestration/coverage_improvement.py +3 -3
  120. crackerjack/orchestration/execution_strategies.py +26 -6
  121. crackerjack/orchestration/test_progress_streamer.py +8 -5
  122. crackerjack/plugins/base.py +2 -2
  123. crackerjack/plugins/hooks.py +7 -0
  124. crackerjack/plugins/managers.py +11 -8
  125. crackerjack/security/__init__.py +0 -1
  126. crackerjack/security/audit.py +6 -35
  127. crackerjack/services/anomaly_detector.py +392 -0
  128. crackerjack/services/api_extractor.py +615 -0
  129. crackerjack/services/backup_service.py +2 -2
  130. crackerjack/services/bounded_status_operations.py +15 -152
  131. crackerjack/services/cache.py +127 -1
  132. crackerjack/services/changelog_automation.py +395 -0
  133. crackerjack/services/config.py +15 -9
  134. crackerjack/services/config_merge.py +19 -80
  135. crackerjack/services/config_template.py +506 -0
  136. crackerjack/services/contextual_ai_assistant.py +48 -22
  137. crackerjack/services/coverage_badge_service.py +171 -0
  138. crackerjack/services/coverage_ratchet.py +27 -25
  139. crackerjack/services/debug.py +3 -3
  140. crackerjack/services/dependency_analyzer.py +460 -0
  141. crackerjack/services/dependency_monitor.py +14 -11
  142. crackerjack/services/documentation_generator.py +491 -0
  143. crackerjack/services/documentation_service.py +675 -0
  144. crackerjack/services/enhanced_filesystem.py +6 -5
  145. crackerjack/services/enterprise_optimizer.py +865 -0
  146. crackerjack/services/error_pattern_analyzer.py +676 -0
  147. crackerjack/services/file_hasher.py +1 -1
  148. crackerjack/services/git.py +8 -25
  149. crackerjack/services/health_metrics.py +10 -8
  150. crackerjack/services/heatmap_generator.py +735 -0
  151. crackerjack/services/initialization.py +11 -30
  152. crackerjack/services/input_validator.py +5 -97
  153. crackerjack/services/intelligent_commit.py +327 -0
  154. crackerjack/services/log_manager.py +15 -12
  155. crackerjack/services/logging.py +4 -3
  156. crackerjack/services/lsp_client.py +628 -0
  157. crackerjack/services/memory_optimizer.py +19 -87
  158. crackerjack/services/metrics.py +42 -33
  159. crackerjack/services/parallel_executor.py +9 -67
  160. crackerjack/services/pattern_cache.py +1 -1
  161. crackerjack/services/pattern_detector.py +6 -6
  162. crackerjack/services/performance_benchmarks.py +18 -59
  163. crackerjack/services/performance_cache.py +20 -81
  164. crackerjack/services/performance_monitor.py +27 -95
  165. crackerjack/services/predictive_analytics.py +510 -0
  166. crackerjack/services/quality_baseline.py +234 -0
  167. crackerjack/services/quality_baseline_enhanced.py +646 -0
  168. crackerjack/services/quality_intelligence.py +785 -0
  169. crackerjack/services/regex_patterns.py +605 -524
  170. crackerjack/services/regex_utils.py +43 -123
  171. crackerjack/services/secure_path_utils.py +5 -164
  172. crackerjack/services/secure_status_formatter.py +30 -141
  173. crackerjack/services/secure_subprocess.py +11 -92
  174. crackerjack/services/security.py +9 -41
  175. crackerjack/services/security_logger.py +12 -24
  176. crackerjack/services/server_manager.py +124 -16
  177. crackerjack/services/status_authentication.py +16 -159
  178. crackerjack/services/status_security_manager.py +4 -131
  179. crackerjack/services/thread_safe_status_collector.py +19 -125
  180. crackerjack/services/unified_config.py +21 -13
  181. crackerjack/services/validation_rate_limiter.py +5 -54
  182. crackerjack/services/version_analyzer.py +459 -0
  183. crackerjack/services/version_checker.py +1 -1
  184. crackerjack/services/websocket_resource_limiter.py +10 -144
  185. crackerjack/services/zuban_lsp_service.py +390 -0
  186. crackerjack/slash_commands/__init__.py +2 -7
  187. crackerjack/slash_commands/run.md +2 -2
  188. crackerjack/tools/validate_input_validator_patterns.py +14 -40
  189. crackerjack/tools/validate_regex_patterns.py +19 -48
  190. {crackerjack-0.33.0.dist-info → crackerjack-0.33.1.dist-info}/METADATA +196 -25
  191. crackerjack-0.33.1.dist-info/RECORD +229 -0
  192. crackerjack/CLAUDE.md +0 -207
  193. crackerjack/RULES.md +0 -380
  194. crackerjack/py313.py +0 -234
  195. crackerjack-0.33.0.dist-info/RECORD +0 -187
  196. {crackerjack-0.33.0.dist-info → crackerjack-0.33.1.dist-info}/WHEEL +0 -0
  197. {crackerjack-0.33.0.dist-info → crackerjack-0.33.1.dist-info}/entry_points.txt +0 -0
  198. {crackerjack-0.33.0.dist-info → crackerjack-0.33.1.dist-info}/licenses/LICENSE +0 -0
@@ -10,12 +10,9 @@ from .security_logger import SecurityEventLevel, SecurityEventType, get_security
10
10
 
11
11
 
12
12
  class SecurePathValidator:
13
- """Comprehensive path security validation to prevent directory traversal attacks."""
14
-
15
13
  MAX_FILE_SIZE = 100 * 1024 * 1024
16
14
  MAX_PATH_LENGTH = 4096
17
15
 
18
- # Enhanced dangerous components including encoded variations
19
16
  DANGEROUS_COMPONENTS = {
20
17
  "..",
21
18
  ".",
@@ -51,32 +48,14 @@ class SecurePathValidator:
51
48
  "LPT9",
52
49
  }
53
50
 
54
- # Pattern constants removed - now using centralized SAFE_PATTERNS for security validation
55
-
56
51
  @classmethod
57
52
  def validate_safe_path(
58
53
  cls, path: str | Path, base_directory: Path | None = None
59
54
  ) -> Path:
60
- """
61
- Comprehensive path validation to prevent directory traversal attacks.
62
-
63
- Args:
64
- path: Path to validate (string or Path object)
65
- base_directory: Optional base directory to constrain path within
66
-
67
- Returns:
68
- Validated and normalized Path object
69
-
70
- Raises:
71
- ExecutionError: If path contains malicious patterns or is invalid
72
- """
73
- # Convert to string for pattern checking
74
55
  path_str = str(path)
75
56
 
76
- # Check for null bytes and dangerous patterns
77
57
  cls._check_malicious_patterns(path_str)
78
58
 
79
- # Convert to Path and normalize
80
59
  try:
81
60
  path_obj = Path(path_str)
82
61
  normalized = cls.normalize_path(path_obj)
@@ -86,17 +65,14 @@ class SecurePathValidator:
86
65
  error_code=ErrorCode.VALIDATION_ERROR,
87
66
  ) from e
88
67
 
89
- # Validate path length
90
68
  if len(str(normalized)) > cls.MAX_PATH_LENGTH:
91
69
  raise ExecutionError(
92
70
  message=f"Path too long: {len(str(normalized))} > {cls.MAX_PATH_LENGTH}",
93
71
  error_code=ErrorCode.VALIDATION_ERROR,
94
72
  )
95
73
 
96
- # Check dangerous components
97
74
  cls._check_dangerous_components(normalized)
98
75
 
99
- # Validate within base directory if specified
100
76
  if base_directory:
101
77
  if not cls.is_within_directory(normalized, base_directory):
102
78
  raise ExecutionError(
@@ -110,41 +86,23 @@ class SecurePathValidator:
110
86
  def validate_file_path(
111
87
  cls, file_path: Path, base_directory: Path | None = None
112
88
  ) -> Path:
113
- """Legacy method - redirects to validate_safe_path for consistency."""
114
89
  return cls.validate_safe_path(file_path, base_directory)
115
90
 
116
91
  @classmethod
117
92
  def secure_path_join(cls, base: Path, *parts: str) -> Path:
118
- """
119
- Safe alternative to Path.joinpath() that prevents directory traversal.
120
-
121
- Args:
122
- base: Base directory path
123
- *parts: Path components to join
124
-
125
- Returns:
126
- Safely joined path
127
-
128
- Raises:
129
- ExecutionError: If any part contains malicious patterns
130
- """
131
- # Validate base path
132
93
  validated_base = cls.validate_safe_path(base)
133
94
 
134
- # Validate each part for malicious patterns
135
95
  for part in parts:
136
96
  cls._check_malicious_patterns(part)
137
- # Don't allow absolute paths or parent directory references
97
+
138
98
  if Path(part).is_absolute():
139
99
  raise ExecutionError(
140
100
  message=f"Absolute path not allowed in join: {part}",
141
101
  error_code=ErrorCode.VALIDATION_ERROR,
142
102
  )
143
103
 
144
- # Join paths safely
145
104
  result = validated_base.joinpath(*parts)
146
105
 
147
- # Ensure result is still within base directory
148
106
  if not cls.is_within_directory(result, validated_base):
149
107
  raise ExecutionError(
150
108
  message=f"Joined path escapes base directory: {result} not within {validated_base}",
@@ -155,23 +113,9 @@ class SecurePathValidator:
155
113
 
156
114
  @classmethod
157
115
  def normalize_path(cls, path: Path) -> Path:
158
- """
159
- Canonical path resolution with security checks.
160
-
161
- Args:
162
- path: Path to normalize
163
-
164
- Returns:
165
- Normalized path with symlinks resolved
166
-
167
- Raises:
168
- ExecutionError: If path resolution fails or contains malicious patterns
169
- """
170
116
  try:
171
- # Resolve symlinks and normalize
172
117
  resolved = path.resolve()
173
118
 
174
- # Additional validation after resolution
175
119
  cls._validate_resolved_path(resolved)
176
120
 
177
121
  return resolved
@@ -184,22 +128,10 @@ class SecurePathValidator:
184
128
 
185
129
  @classmethod
186
130
  def is_within_directory(cls, path: Path, directory: Path) -> bool:
187
- """
188
- Verify that a path is contained within a directory.
189
-
190
- Args:
191
- path: Path to check
192
- directory: Directory that should contain the path
193
-
194
- Returns:
195
- True if path is within directory, False otherwise
196
- """
197
131
  try:
198
- # Resolve both paths to handle symlinks
199
132
  resolved_path = path.resolve()
200
133
  resolved_directory = directory.resolve()
201
134
 
202
- # Check if path is relative to directory
203
135
  resolved_path.relative_to(resolved_directory)
204
136
  return True
205
137
 
@@ -208,26 +140,10 @@ class SecurePathValidator:
208
140
 
209
141
  @classmethod
210
142
  def safe_resolve(cls, path: Path, base_directory: Path | None = None) -> Path:
211
- """
212
- Secure path resolution preventing symlink attacks.
213
-
214
- Args:
215
- path: Path to resolve
216
- base_directory: Optional base directory constraint
217
-
218
- Returns:
219
- Safely resolved path
220
-
221
- Raises:
222
- ExecutionError: If resolution fails or path escapes constraints
223
- """
224
- # First validate the input path
225
143
  validated_path = cls.validate_safe_path(path, base_directory)
226
144
 
227
- # Resolve with additional symlink attack prevention
228
145
  resolved = cls.normalize_path(validated_path)
229
146
 
230
- # Re-validate after resolution
231
147
  if base_directory and not cls.is_within_directory(resolved, base_directory):
232
148
  raise ExecutionError(
233
149
  message=f"Resolved path escapes base directory: {resolved} not within {base_directory}",
@@ -238,25 +154,18 @@ class SecurePathValidator:
238
154
 
239
155
  @classmethod
240
156
  def _check_malicious_patterns(cls, path_str: str) -> None:
241
- """Check for directory traversal and null byte patterns using safe patterns."""
242
157
  security_logger = get_security_logger()
243
158
 
244
- # URL decode the path to catch encoded attacks
245
159
  try:
246
160
  decoded = urllib.parse.unquote(path_str, errors="strict")
247
161
  except UnicodeDecodeError:
248
- # If decoding fails, use original string but still check patterns
249
162
  decoded = path_str
250
163
 
251
- # Check both original and decoded versions using safe patterns
252
164
  for check_str in (path_str, decoded):
253
165
  validation_results = validate_path_security(check_str)
254
166
 
255
- # Check for null byte patterns
256
167
  if validation_results["null_bytes"]:
257
- detected_pattern = validation_results["null_bytes"][
258
- 0
259
- ] # First detected pattern
168
+ detected_pattern = validation_results["null_bytes"][0]
260
169
  security_logger.log_security_event(
261
170
  SecurityEventType.PATH_TRAVERSAL_ATTEMPT,
262
171
  SecurityEventLevel.CRITICAL,
@@ -270,11 +179,8 @@ class SecurePathValidator:
270
179
  error_code=ErrorCode.VALIDATION_ERROR,
271
180
  )
272
181
 
273
- # Check for directory traversal patterns
274
182
  if validation_results["traversal_patterns"]:
275
- detected_pattern = validation_results["traversal_patterns"][
276
- 0
277
- ] # First detected pattern
183
+ detected_pattern = validation_results["traversal_patterns"][0]
278
184
  security_logger.log_path_traversal_attempt(
279
185
  attempted_path=path_str,
280
186
  pattern_type="directory_traversal",
@@ -287,13 +193,10 @@ class SecurePathValidator:
287
193
 
288
194
  @classmethod
289
195
  def _validate_resolved_path(cls, path: Path) -> None:
290
- """Additional validation for resolved paths using safe patterns."""
291
196
  path_str = str(path)
292
197
 
293
- # Check for dangerous patterns that might appear after resolution using safe patterns
294
198
  validation_results = validate_path_security(path_str)
295
199
 
296
- # Check for parent directory references
297
200
  if validation_results["suspicious_patterns"]:
298
201
  if (
299
202
  "detect_parent_directory_in_path"
@@ -304,7 +207,6 @@ class SecurePathValidator:
304
207
  error_code=ErrorCode.VALIDATION_ERROR,
305
208
  )
306
209
 
307
- # Check for suspicious traversal patterns in system directories
308
210
  suspicious_detected = [
309
211
  pattern
310
212
  for pattern in validation_results["suspicious_patterns"]
@@ -380,24 +282,8 @@ class SecurePathValidator:
380
282
  directory: Path | None = None,
381
283
  purpose: str = "general",
382
284
  ) -> t.Any:
383
- """
384
- Create a secure temporary file with proper permissions.
385
-
386
- Args:
387
- suffix: File suffix
388
- prefix: File prefix
389
- directory: Directory to create temp file in (validated if provided)
390
- purpose: Purpose description for security logging
391
-
392
- Returns:
393
- Secure temporary file handle
394
-
395
- Raises:
396
- ExecutionError: If temp file creation fails
397
- """
398
285
  security_logger = get_security_logger()
399
286
 
400
- # Validate directory if provided
401
287
  if directory:
402
288
  directory = cls.validate_safe_path(directory)
403
289
 
@@ -406,10 +292,8 @@ class SecurePathValidator:
406
292
  mode="w+b", suffix=suffix, prefix=prefix, dir=directory, delete=False
407
293
  )
408
294
 
409
- # Set restrictive permissions (owner read/write only)
410
295
  os.chmod(temp_file.name, 0o600)
411
296
 
412
- # Log secure temp file creation
413
297
  security_logger.log_temp_file_created(
414
298
  temp_path=temp_file.name,
415
299
  purpose=purpose,
@@ -455,7 +339,6 @@ class AtomicFileOperations:
455
339
  temp_path = Path(temp_file.name)
456
340
  temp_path.replace(validated_path)
457
341
 
458
- # Log successful atomic operation
459
342
  security_logger.log_atomic_operation(
460
343
  operation="write",
461
344
  file_path=str(validated_path),
@@ -468,7 +351,6 @@ class AtomicFileOperations:
468
351
  if temp_path.exists():
469
352
  temp_path.unlink()
470
353
 
471
- # Log failed atomic operation
472
354
  security_logger.log_atomic_operation(
473
355
  operation="write",
474
356
  file_path=str(validated_path),
@@ -514,7 +396,6 @@ class AtomicFileOperations:
514
396
  validated_path, new_content, base_directory
515
397
  )
516
398
 
517
- # Log successful backup creation
518
399
  security_logger.log_backup_created(
519
400
  original_path=str(validated_path),
520
401
  backup_path=str(backup_path),
@@ -526,7 +407,6 @@ class AtomicFileOperations:
526
407
  if backup_path.exists():
527
408
  backup_path.unlink()
528
409
 
529
- # Log failed backup operation
530
410
  security_logger.log_atomic_operation(
531
411
  operation="backup_and_write",
532
412
  file_path=str(validated_path),
@@ -541,9 +421,6 @@ class AtomicFileOperations:
541
421
 
542
422
 
543
423
  class SubprocessPathValidator:
544
- """Specialized path validation for subprocess execution contexts."""
545
-
546
- # Paths that should never be accessible via subprocess
547
424
  FORBIDDEN_SUBPROCESS_PATHS = {
548
425
  "/etc/passwd",
549
426
  "/etc/shadow",
@@ -563,32 +440,15 @@ class SubprocessPathValidator:
563
440
  "/var/spool/cron",
564
441
  }
565
442
 
566
- # Directory patterns removed - now using centralized SAFE_PATTERNS for security validation
567
-
568
443
  @classmethod
569
444
  def validate_subprocess_cwd(cls, cwd: Path | str | None) -> Path | None:
570
- """
571
- Validate working directory for subprocess execution.
572
-
573
- Args:
574
- cwd: Working directory path
575
-
576
- Returns:
577
- Validated Path object or None
578
-
579
- Raises:
580
- ExecutionError: If path is dangerous for subprocess execution
581
- """
582
445
  if cwd is None:
583
446
  return None
584
447
 
585
- # Use base path validation first
586
448
  validated_cwd = SecurePathValidator.validate_safe_path(cwd)
587
449
 
588
- # Additional subprocess-specific checks
589
450
  cwd_str = str(validated_cwd)
590
451
 
591
- # Check against forbidden paths
592
452
  if cwd_str in cls.FORBIDDEN_SUBPROCESS_PATHS:
593
453
  security_logger = get_security_logger()
594
454
  security_logger.log_dangerous_path_detected(
@@ -601,17 +461,14 @@ class SubprocessPathValidator:
601
461
  error_code=ErrorCode.VALIDATION_ERROR,
602
462
  )
603
463
 
604
- # Check against dangerous directory patterns using safe patterns
605
464
  validation_results = validate_path_security(cwd_str)
606
465
 
607
466
  if validation_results["dangerous_directories"]:
608
- detected_pattern = validation_results["dangerous_directories"][
609
- 0
610
- ] # First detected pattern
467
+ detected_pattern = validation_results["dangerous_directories"][0]
611
468
  security_logger = get_security_logger()
612
469
  security_logger.log_dangerous_path_detected(
613
470
  path=cwd_str,
614
- dangerous_component=f"pattern:{detected_pattern}",
471
+ dangerous_component=f"pattern: {detected_pattern}",
615
472
  context="subprocess_cwd_validation",
616
473
  )
617
474
  raise ExecutionError(
@@ -623,31 +480,15 @@ class SubprocessPathValidator:
623
480
 
624
481
  @classmethod
625
482
  def validate_executable_path(cls, executable: str | Path) -> Path:
626
- """
627
- Validate executable path for subprocess execution.
628
-
629
- Args:
630
- executable: Executable path or name
631
-
632
- Returns:
633
- Validated Path object
634
-
635
- Raises:
636
- ExecutionError: If executable is dangerous or invalid
637
- """
638
483
  exec_path = Path(executable)
639
484
 
640
- # If it's just a command name, don't validate as full path
641
485
  if not str(executable).startswith(("/", "./", "../")):
642
486
  return exec_path
643
487
 
644
- # For full paths, apply full validation
645
488
  validated_exec = SecurePathValidator.validate_safe_path(exec_path)
646
489
 
647
- # Additional checks for executable paths
648
490
  exec_str = str(validated_exec)
649
491
 
650
- # Check if trying to execute system-critical files
651
492
  dangerous_executables = {
652
493
  "/usr/bin/sudo",
653
494
  "/bin/sudo",