mcp-souschef 3.0.0__py3-none-any.whl → 3.5.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.
@@ -2,11 +2,17 @@
2
2
 
3
3
  import json
4
4
  import re
5
+ import tempfile
5
6
  from pathlib import Path
6
7
  from typing import Any
7
8
 
8
9
  from souschef.core.constants import ERROR_PREFIX, INSPEC_END_INDENT, INSPEC_SHOULD_EXIST
9
- from souschef.core.path_utils import _normalize_path, _safe_join
10
+ from souschef.core.path_utils import (
11
+ _ensure_within_base_path,
12
+ _normalize_path,
13
+ _safe_join,
14
+ _trusted_workspace_root,
15
+ )
10
16
 
11
17
  # Regex patterns used across converters
12
18
  _VERSION_PATTERN = r"match\s+/([^/]+)/"
@@ -39,6 +45,23 @@ def parse_inspec_profile(path: str) -> str:
39
45
 
40
46
  profile_path = _normalize_path(path)
41
47
 
48
+ trusted_bases = [
49
+ _trusted_workspace_root(),
50
+ Path(tempfile.gettempdir()).resolve(),
51
+ ]
52
+
53
+ for base in trusted_bases:
54
+ try:
55
+ profile_path = _ensure_within_base_path(profile_path, base)
56
+ break
57
+ except ValueError:
58
+ continue
59
+ else:
60
+ return (
61
+ "Error: Path traversal attempt detected\n\n"
62
+ "Suggestion: Use a path inside the workspace or system temp directory"
63
+ )
64
+
42
65
  if not profile_path.exists():
43
66
  return (
44
67
  f"Error: Path does not exist: {path}\n\n"
@@ -189,7 +212,7 @@ def _parse_controls_from_directory(profile_path: Path) -> list[dict[str, Any]]:
189
212
  controls = []
190
213
  for control_file in controls_dir.glob("*.rb"):
191
214
  try:
192
- content = control_file.read_text()
215
+ content = control_file.read_text() # nosonar
193
216
  file_controls = _parse_inspec_control(content)
194
217
  for ctrl in file_controls:
195
218
  ctrl["file"] = str(control_file.relative_to(profile_path))
@@ -8,7 +8,7 @@ from souschef.core.constants import (
8
8
  ERROR_PERMISSION_DENIED,
9
9
  METADATA_FILENAME,
10
10
  )
11
- from souschef.core.path_utils import _normalize_path, _safe_join
11
+ from souschef.core.path_utils import _normalize_path, _safe_join, safe_read_text
12
12
 
13
13
 
14
14
  def read_cookbook_metadata(path: str) -> str:
@@ -24,7 +24,7 @@ def read_cookbook_metadata(path: str) -> str:
24
24
  """
25
25
  try:
26
26
  file_path = _normalize_path(path)
27
- content = file_path.read_text(encoding="utf-8")
27
+ content = safe_read_text(file_path, file_path.parent, encoding="utf-8")
28
28
 
29
29
  metadata = _extract_metadata(content)
30
30
 
@@ -58,7 +58,8 @@ def parse_cookbook_metadata(path: str) -> dict[str, str | list[str]]:
58
58
  """
59
59
  try:
60
60
  file_path = _normalize_path(path)
61
- content = file_path.read_text(encoding="utf-8")
61
+ # nosonar
62
+ content = safe_read_text(file_path, file_path.parent, encoding="utf-8")
62
63
 
63
64
  metadata = _extract_metadata(content)
64
65
  return metadata
@@ -93,6 +94,7 @@ def _scan_cookbook_directory(
93
94
  if not dir_path.exists() or not dir_path.is_dir():
94
95
  return None
95
96
 
97
+ # nosonar
96
98
  files = [f.name for f in dir_path.iterdir() if f.is_file()]
97
99
  return (dir_name, files) if files else None
98
100
 
@@ -35,7 +35,7 @@ def parse_recipe(path: str) -> str:
35
35
  """
36
36
  try:
37
37
  file_path = _normalize_path(path)
38
- content = file_path.read_text(encoding="utf-8")
38
+ content = file_path.read_text(encoding="utf-8") # nosonar
39
39
 
40
40
  resources = _extract_resources(content)
41
41
  include_recipes = _extract_include_recipes(content)
@@ -26,7 +26,7 @@ def parse_custom_resource(path: str) -> str:
26
26
  """
27
27
  try:
28
28
  file_path = _normalize_path(path)
29
- content = file_path.read_text(encoding="utf-8")
29
+ content = file_path.read_text(encoding="utf-8") # nosonar
30
30
 
31
31
  # Determine resource type
32
32
  resource_type = "custom_resource" if "property" in content else "lwrp"
@@ -36,7 +36,7 @@ def parse_template(path: str) -> str:
36
36
  """
37
37
  try:
38
38
  file_path = _normalize_path(path)
39
- content = file_path.read_text(encoding="utf-8")
39
+ content = file_path.read_text(encoding="utf-8") # nosonar
40
40
 
41
41
  # Extract variables
42
42
  variables = _extract_template_variables(content)