gitlab-api 25.36.0__tar.gz → 25.37.0__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 (80) hide show
  1. {gitlab_api-25.36.0/gitlab_api.egg-info → gitlab_api-25.37.0}/PKG-INFO +5 -5
  2. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/README.md +1 -1
  3. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/agent_server.py +1 -1
  4. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp_server.py +1 -1
  5. {gitlab_api-25.36.0 → gitlab_api-25.37.0/gitlab_api.egg-info}/PKG-INFO +5 -5
  6. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api.egg-info/SOURCES.txt +1 -0
  7. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api.egg-info/requires.txt +3 -3
  8. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/pyproject.toml +4 -4
  9. gitlab_api-25.37.0/scripts/security_sanitizer.py +160 -0
  10. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/LICENSE +0 -0
  11. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/MANIFEST.in +0 -0
  12. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/__init__.py +0 -0
  13. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/__main__.py +0 -0
  14. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/api/__init__.py +0 -0
  15. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/api/api_client_base.py +0 -0
  16. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/api/api_client_environments.py +0 -0
  17. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/api/api_client_issues.py +0 -0
  18. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/api/api_client_merge_requests.py +0 -0
  19. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/api/api_client_other.py +0 -0
  20. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/api/api_client_pipelines.py +0 -0
  21. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/api/api_client_projects.py +0 -0
  22. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/api/api_client_repositories.py +0 -0
  23. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/api/api_client_system.py +0 -0
  24. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/api/api_client_users_groups.py +0 -0
  25. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/api_client.py +0 -0
  26. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/auth.py +0 -0
  27. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/gitlab_gql.py +0 -0
  28. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/gitlab_input_models.py +0 -0
  29. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/gitlab_response_models.py +0 -0
  30. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp/__init__.py +0 -0
  31. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp/mcp_branches.py +0 -0
  32. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp/mcp_commits.py +0 -0
  33. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp/mcp_custom_api.py +0 -0
  34. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp/mcp_deploy_tokens.py +0 -0
  35. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp/mcp_environments.py +0 -0
  36. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp/mcp_epics.py +0 -0
  37. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp/mcp_graphql.py +0 -0
  38. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp/mcp_groups.py +0 -0
  39. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp/mcp_issues.py +0 -0
  40. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp/mcp_jobs.py +0 -0
  41. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp/mcp_labels.py +0 -0
  42. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp/mcp_members.py +0 -0
  43. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp/mcp_merge_requests.py +0 -0
  44. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp/mcp_merge_rules.py +0 -0
  45. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp/mcp_milestones.py +0 -0
  46. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp/mcp_misc.py +0 -0
  47. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp/mcp_notes.py +0 -0
  48. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp/mcp_packages.py +0 -0
  49. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp/mcp_pipeline_schedules.py +0 -0
  50. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp/mcp_pipelines.py +0 -0
  51. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp/mcp_projects.py +0 -0
  52. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp/mcp_protected_branches.py +0 -0
  53. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp/mcp_releases.py +0 -0
  54. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp/mcp_runners.py +0 -0
  55. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp/mcp_snippets.py +0 -0
  56. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp/mcp_tags.py +0 -0
  57. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api/mcp_config.json +0 -0
  58. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api.egg-info/dependency_links.txt +0 -0
  59. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api.egg-info/entry_points.txt +0 -0
  60. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/gitlab_api.egg-info/top_level.txt +0 -0
  61. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/requirements.txt +0 -0
  62. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/scripts/validate_a2a_agent.py +0 -0
  63. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/scripts/validate_agent.py +0 -0
  64. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/scripts/verify_api_integration.py +0 -0
  65. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/setup.cfg +0 -0
  66. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/tests/__init__.py +0 -0
  67. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/tests/conftest.py +0 -0
  68. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/tests/test_api_wrapper.py +0 -0
  69. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/tests/test_auth.py +0 -0
  70. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/tests/test_concept_parity.py +0 -0
  71. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/tests/test_gitlab_a2a_validation.py +0 -0
  72. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/tests/test_gitlab_api_brute_force_coverage.py +0 -0
  73. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/tests/test_gitlab_gql.py +0 -0
  74. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/tests/test_gitlab_mcp_validation.py +0 -0
  75. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/tests/test_gitlab_models.py +0 -0
  76. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/tests/test_init_dynamics.py +0 -0
  77. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/tests/test_mock_coverage.py +0 -0
  78. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/tests/test_startup.py +0 -0
  79. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/tests/test_verify_agent.py +0 -0
  80. {gitlab_api-25.36.0 → gitlab_api-25.37.0}/tests/verify_a2a_queries.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitlab-api
3
- Version: 25.36.0
3
+ Version: 25.37.0
4
4
  Summary: GitLab API + MCP Server + A2A Server
5
5
  Author-email: Audel Rouhi <knucklessg1@gmail.com>
6
6
  License: MIT
@@ -12,13 +12,13 @@ Classifier: Programming Language :: Python :: 3
12
12
  Requires-Python: <3.14,>=3.11
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
- Requires-Dist: agent-utilities>=0.34.0
15
+ Requires-Dist: agent-utilities>=0.38.0
16
16
  Requires-Dist: python-dotenv>=1.0.0
17
17
  Requires-Dist: gql>=4.0.0
18
18
  Provides-Extra: mcp
19
- Requires-Dist: agent-utilities[mcp]>=0.34.0; extra == "mcp"
19
+ Requires-Dist: agent-utilities[mcp]>=0.38.0; extra == "mcp"
20
20
  Provides-Extra: agent
21
- Requires-Dist: agent-utilities[agent,logfire]>=0.34.0; extra == "agent"
21
+ Requires-Dist: agent-utilities[agent,logfire]>=0.38.0; extra == "agent"
22
22
  Provides-Extra: gql
23
23
  Requires-Dist: gql>=4.0.0; extra == "gql"
24
24
  Provides-Extra: all
@@ -52,7 +52,7 @@ Dynamic: license-file
52
52
  ![PyPI - Wheel](https://img.shields.io/pypi/wheel/gitlab-api)
53
53
  ![PyPI - Implementation](https://img.shields.io/pypi/implementation/gitlab-api)
54
54
 
55
- *Version: 25.36.0*
55
+ *Version: 25.37.0*
56
56
 
57
57
  ---
58
58
 
@@ -20,7 +20,7 @@
20
20
  ![PyPI - Wheel](https://img.shields.io/pypi/wheel/gitlab-api)
21
21
  ![PyPI - Implementation](https://img.shields.io/pypi/implementation/gitlab-api)
22
22
 
23
- *Version: 25.36.0*
23
+ *Version: 25.37.0*
24
24
 
25
25
  ---
26
26
 
@@ -4,7 +4,7 @@ import os
4
4
  import sys
5
5
  import warnings
6
6
 
7
- __version__ = "25.36.0"
7
+ __version__ = "25.37.0"
8
8
 
9
9
  logging.basicConfig(
10
10
  level=logging.INFO,
@@ -33,7 +33,7 @@ from dotenv import find_dotenv, load_dotenv
33
33
 
34
34
  from gitlab_api.auth import get_client
35
35
 
36
- __version__ = "25.36.0"
36
+ __version__ = "25.37.0"
37
37
  print(f"Gitlab MCP v{__version__}", file=sys.stderr)
38
38
 
39
39
  logger = get_logger(name="mcp_server")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitlab-api
3
- Version: 25.36.0
3
+ Version: 25.37.0
4
4
  Summary: GitLab API + MCP Server + A2A Server
5
5
  Author-email: Audel Rouhi <knucklessg1@gmail.com>
6
6
  License: MIT
@@ -12,13 +12,13 @@ Classifier: Programming Language :: Python :: 3
12
12
  Requires-Python: <3.14,>=3.11
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
- Requires-Dist: agent-utilities>=0.34.0
15
+ Requires-Dist: agent-utilities>=0.38.0
16
16
  Requires-Dist: python-dotenv>=1.0.0
17
17
  Requires-Dist: gql>=4.0.0
18
18
  Provides-Extra: mcp
19
- Requires-Dist: agent-utilities[mcp]>=0.34.0; extra == "mcp"
19
+ Requires-Dist: agent-utilities[mcp]>=0.38.0; extra == "mcp"
20
20
  Provides-Extra: agent
21
- Requires-Dist: agent-utilities[agent,logfire]>=0.34.0; extra == "agent"
21
+ Requires-Dist: agent-utilities[agent,logfire]>=0.38.0; extra == "agent"
22
22
  Provides-Extra: gql
23
23
  Requires-Dist: gql>=4.0.0; extra == "gql"
24
24
  Provides-Extra: all
@@ -52,7 +52,7 @@ Dynamic: license-file
52
52
  ![PyPI - Wheel](https://img.shields.io/pypi/wheel/gitlab-api)
53
53
  ![PyPI - Implementation](https://img.shields.io/pypi/implementation/gitlab-api)
54
54
 
55
- *Version: 25.36.0*
55
+ *Version: 25.37.0*
56
56
 
57
57
  ---
58
58
 
@@ -57,6 +57,7 @@ gitlab_api/mcp/mcp_releases.py
57
57
  gitlab_api/mcp/mcp_runners.py
58
58
  gitlab_api/mcp/mcp_snippets.py
59
59
  gitlab_api/mcp/mcp_tags.py
60
+ scripts/security_sanitizer.py
60
61
  scripts/validate_a2a_agent.py
61
62
  scripts/validate_agent.py
62
63
  scripts/verify_api_integration.py
@@ -1,9 +1,9 @@
1
- agent-utilities>=0.34.0
1
+ agent-utilities>=0.38.0
2
2
  python-dotenv>=1.0.0
3
3
  gql>=4.0.0
4
4
 
5
5
  [agent]
6
- agent-utilities[agent,logfire]>=0.34.0
6
+ agent-utilities[agent,logfire]>=0.38.0
7
7
 
8
8
  [all]
9
9
  gitlab-api[agent,gql,logfire,mcp]>=25.36.0
@@ -12,7 +12,7 @@ gitlab-api[agent,gql,logfire,mcp]>=25.36.0
12
12
  gql>=4.0.0
13
13
 
14
14
  [mcp]
15
- agent-utilities[mcp]>=0.34.0
15
+ agent-utilities[mcp]>=0.38.0
16
16
 
17
17
  [test]
18
18
  pytest-xdist>=3.6.0
@@ -4,12 +4,12 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "gitlab-api"
7
- version = "25.36.0"
7
+ version = "25.37.0"
8
8
  description = "GitLab API + MCP Server + A2A Server"
9
9
  readme = "README.md"
10
10
  classifiers = [ "Development Status :: 5 - Production/Stable", "License :: Public Domain", "Environment :: Console", "Operating System :: POSIX :: Linux", "Programming Language :: Python :: 3",]
11
11
  requires-python = ">=3.11, <3.14"
12
- dependencies = [ "agent-utilities>=0.34.0", "python-dotenv>=1.0.0", "gql>=4.0.0",]
12
+ dependencies = [ "agent-utilities>=0.38.0", "python-dotenv>=1.0.0", "gql>=4.0.0",]
13
13
  [[project.authors]]
14
14
  name = "Audel Rouhi"
15
15
  email = "knucklessg1@gmail.com"
@@ -18,8 +18,8 @@ email = "knucklessg1@gmail.com"
18
18
  text = "MIT"
19
19
 
20
20
  [project.optional-dependencies]
21
- mcp = [ "agent-utilities[mcp]>=0.34.0",]
22
- agent = [ "agent-utilities[agent,logfire]>=0.34.0",]
21
+ mcp = [ "agent-utilities[mcp]>=0.38.0",]
22
+ agent = [ "agent-utilities[agent,logfire]>=0.38.0",]
23
23
  gql = [ "gql>=4.0.0",]
24
24
  all = [ "gitlab-api[mcp,agent,gql,logfire]>=25.36.0",]
25
25
  test = [
@@ -0,0 +1,160 @@
1
+ #!/usr/bin/env python3
2
+ import os
3
+ import re
4
+ import sys
5
+ import subprocess
6
+ from pathlib import Path
7
+
8
+ # Config
9
+ ALLOWED_TXT_NAMES = {"requirements.txt", "requirements-dev.txt"}
10
+ TRANSIENT_PY_PATTERNS = [
11
+ re.compile(r"^test_.*\.py$"),
12
+ re.compile(r"^fix_.*\.py$"),
13
+ re.compile(r"^debug_.*\.py$"),
14
+ re.compile(r"^scratch_.*\.py$"),
15
+ re.compile(r"^temp_.*\.py$"),
16
+ ]
17
+
18
+ SECRET_PATTERNS = [
19
+ ("GitHub PAT", re.compile(r"ghp_[A-Za-z0-9_]{36,255}")),
20
+ ("GitHub Fine-grained PAT", re.compile(r"github_pat_[A-Za-z0-9_]{82,255}")),
21
+ ("GitLab PAT", re.compile(r"glpat-[A-Za-z0-9\-]{20,255}")),
22
+ ("Generic Secret Assignment", re.compile(r"secret[A-Za-z0-9_]*\s*[:=]\s*['\"][A-Za-z0-9_\-\.\~\*]{16,255}['\"]", re.IGNORECASE)),
23
+ ("Generic Token Assignment", re.compile(r"token\s*[:=]\s*['\"][A-Za-z0-9_\-\.\~\*]{16,255}['\"]", re.IGNORECASE))
24
+ ]
25
+
26
+ EXCLUDED_DIRS = {".git", ".venv", "venv", "node_modules", "build", "dist", "__pycache__", ".tox", ".specify"}
27
+ EXCLUDED_EXTENSIONS = {
28
+ ".png", ".jpg", ".jpeg", ".gif", ".webp", ".ico", ".pyc", ".db", ".kuzu",
29
+ ".sqlite", ".sqlite3", ".zip", ".tar.gz", ".tgz", ".bz2", ".xz", ".pdf",
30
+ ".bin", ".exe", ".dll", ".so", ".dylib", ".woff", ".woff2", ".eot", ".ttf",
31
+ ".mp4", ".mp3", ".wav", ".lock", ".svg"
32
+ }
33
+
34
+ # Placeholder / Mock indicators
35
+ PLACEHOLDER_SUBSTRINGS = [
36
+ "1234567890", "abcdef12345", "abc123youandme", "askdfalskdvjas", "your_", "YOUR_", "your-",
37
+ "dummy", "DUMMY", "example", "EXAMPLE", "mock", "MOCK", "test_token", "test_secret",
38
+ "glpat-askdfalskdvjas", "github_pat_12345", "glpat-abc123youandme", "github_pat_...",
39
+ "glpat-*************", "ghp_*************", "github_pat_*************", "token_*************",
40
+ "secret_*************", "glpat-abc", "ghp_abc", "github_pat_abc", "${env:"
41
+ ]
42
+
43
+ def is_placeholder(match_str: str) -> bool:
44
+ match_lower = match_str.lower()
45
+ for placeholder in PLACEHOLDER_SUBSTRINGS:
46
+ if placeholder in match_lower:
47
+ return True
48
+
49
+ # Check if match is mostly asterisks or single repeated char
50
+ cleaned = match_str.replace("'", "").replace('"', "").strip()
51
+ if not cleaned:
52
+ return True
53
+
54
+ # Check if there are sequences of asterisks indicating masked values
55
+ if "*" in cleaned:
56
+ # e.g., glpat-*************
57
+ return True
58
+
59
+ return False
60
+
61
+ def get_repo_files(repo_path: Path):
62
+ try:
63
+ result = subprocess.run(
64
+ ["git", "ls-files", "--cached", "--others", "--exclude-standard"],
65
+ cwd=str(repo_path),
66
+ capture_output=True,
67
+ text=True,
68
+ check=True
69
+ )
70
+ files = []
71
+ for line in result.stdout.splitlines():
72
+ if line.strip():
73
+ # Avoid files inside excluded directories
74
+ parts = Path(line.strip()).parts
75
+ if not any(part in EXCLUDED_DIRS for part in parts):
76
+ files.append(repo_path / line.strip())
77
+ return files
78
+ except Exception as e:
79
+ # Fallback to manual recursive scan
80
+ files = []
81
+ for root, dirs, walk_files in os.walk(str(repo_path)):
82
+ dirs[:] = [d for d in dirs if d not in EXCLUDED_DIRS and not d.startswith('.')]
83
+ for file in walk_files:
84
+ files.append(Path(root) / file)
85
+ return files
86
+
87
+ def scan_repository(repo_path: Path):
88
+ violations = []
89
+ files_to_scan = get_repo_files(repo_path)
90
+
91
+ for file_path in files_to_scan:
92
+ if not file_path.is_file():
93
+ continue
94
+
95
+ # 1. Check root level naming constraints
96
+ if file_path.parent == repo_path:
97
+ # Check txt files
98
+ if file_path.suffix == ".txt":
99
+ if file_path.name.lower() not in ALLOWED_TXT_NAMES:
100
+ violations.append(
101
+ f"Non-standard root-level text file detected: '{file_path.name}'. Only 'requirements.txt' and 'requirements-dev.txt' are allowed."
102
+ )
103
+ # Check transient py files
104
+ elif file_path.suffix == ".py":
105
+ for pattern in TRANSIENT_PY_PATTERNS:
106
+ if pattern.match(file_path.name):
107
+ violations.append(
108
+ f"Transient/temporary script detected in root: '{file_path.name}'. Please move it to a subfolder or delete it."
109
+ )
110
+ break
111
+
112
+ # 2. Check for secrets
113
+ if file_path.suffix.lower() in EXCLUDED_EXTENSIONS:
114
+ continue
115
+
116
+ if file_path.name == "security_sanitizer.py":
117
+ continue
118
+
119
+ try:
120
+ content = file_path.read_text(encoding="utf-8", errors="ignore")
121
+ lines = content.splitlines()
122
+
123
+ for idx, line in enumerate(lines, 1):
124
+ if any(bypass in line for bypass in ["# sanitizer:ignore", "# sanitizer-ignore", "# nosec"]):
125
+ continue
126
+
127
+ for label, pattern in SECRET_PATTERNS:
128
+ for match in pattern.findall(line):
129
+ match_str = match[0] if isinstance(match, tuple) else match
130
+ if not is_placeholder(match_str):
131
+ rel_path = file_path.relative_to(repo_path)
132
+ violations.append(
133
+ f"Potential unmasked secret ({label}) detected in {rel_path}:{idx}\n"
134
+ f" Line: {line.strip()}"
135
+
136
+ )
137
+ except Exception:
138
+ pass
139
+
140
+ return violations
141
+
142
+ def main():
143
+ repo_path = Path.cwd()
144
+
145
+ print("🔒 Running Security and Garbage Sanitizer...")
146
+ violations = scan_repository(repo_path)
147
+
148
+ if violations:
149
+ print("\n❌ SECURITY AND GARBAGE VALIDATION FAILED!")
150
+ print("Please correct the following issues before committing:")
151
+ for idx, violation in enumerate(violations, 1):
152
+ print(f"\n[{idx}] {violation}")
153
+ print("\nNote: To bypass secret checks on specific lines, append '# sanitizer:ignore' to the end of the line.")
154
+ sys.exit(1)
155
+
156
+ print("✅ All checks passed! No root garbage or unmasked secrets detected.")
157
+ sys.exit(0)
158
+
159
+ if __name__ == "__main__":
160
+ main()
File without changes
File without changes
File without changes