From 5bbffb27ba10127b016372c9ecedc632ba7fb95f Mon Sep 17 00:00:00 2001 From: ikrispin Date: Tue, 5 May 2026 11:20:51 +0300 Subject: [PATCH] fix(ocp-admin): replace anti-inspection directives with auditable script usage rules --- ocp-admin/scripts/cluster-report/assemble.py | 4 ++++ ocp-admin/scripts/cluster-report/test_assemble.py | 13 +++++++++---- ocp-admin/skills/cluster-report/SKILL.md | 10 +++++----- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/ocp-admin/scripts/cluster-report/assemble.py b/ocp-admin/scripts/cluster-report/assemble.py index ee0f9f67..98ea0451 100644 --- a/ocp-admin/scripts/cluster-report/assemble.py +++ b/ocp-admin/scripts/cluster-report/assemble.py @@ -28,6 +28,10 @@ def unwrap_persisted_output(raw_content): def resolve_file_ref(file_path): + abs_path = os.path.realpath(file_path) + if not abs_path.startswith("/tmp/"): + return None, f"Path outside allowed directory: {file_path}" + if not os.path.exists(file_path): return None, f"File not found: {file_path}" diff --git a/ocp-admin/scripts/cluster-report/test_assemble.py b/ocp-admin/scripts/cluster-report/test_assemble.py index 0cd3e9f8..0fa0e34f 100644 --- a/ocp-admin/scripts/cluster-report/test_assemble.py +++ b/ocp-admin/scripts/cluster-report/test_assemble.py @@ -117,10 +117,15 @@ def test_valid_plain_json_file(self): os.unlink(path) def test_missing_file(self): - result, error = assemble.resolve_file_ref("/nonexistent/path/file.json") + result, error = assemble.resolve_file_ref("/tmp/nonexistent-file.json") self.assertIsNone(result) self.assertIn("not found", error.lower()) + def test_path_outside_allowed_directory(self): + result, error = assemble.resolve_file_ref("/etc/passwd") + self.assertIsNone(result) + self.assertIn("outside allowed directory", error.lower()) + def test_empty_file(self): with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f: path = f.name @@ -223,7 +228,7 @@ def test_file_ref_resolved(self): def test_failed_file_ref_adds_error(self): cluster = { - "pods": {"$file": "/nonexistent/file.json"}, + "pods": {"$file": "/tmp/nonexistent-file.json"}, "nodes_top": None, "nodes_list": None, "projects": None, @@ -237,7 +242,7 @@ def test_failed_file_ref_adds_error(self): def test_preserves_existing_errors(self): cluster = { - "pods": {"$file": "/nonexistent/file.json"}, + "pods": {"$file": "/tmp/nonexistent-file.json"}, "nodes_top": None, "nodes_list": None, "projects": None, @@ -400,7 +405,7 @@ def test_file_ref_error_in_pipeline(self): "nodes_list": None, "projects": None, "namespaces": None, - "pods": {"$file": "/nonexistent/file.json"}, + "pods": {"$file": "/tmp/nonexistent-file.json"}, "errors": [], } }, diff --git a/ocp-admin/skills/cluster-report/SKILL.md b/ocp-admin/skills/cluster-report/SKILL.md index 704953bc..2eb82b8e 100644 --- a/ocp-admin/skills/cluster-report/SKILL.md +++ b/ocp-admin/skills/cluster-report/SKILL.md @@ -60,14 +60,14 @@ This skill uses `openshift-administration` MCP server exclusively. This server p **Multi-Cluster Setup**: For large-scale deployments using service account tokens instead of interactive `oc login`, see [multi-cluster-auth.md](../../docs/multi-cluster-auth.md) and the [build-kubeconfig.py](../../scripts/cluster-report/build-kubeconfig.py) helper script. -**Helper Scripts** (Python 3, stdlib only — treat as black boxes): +**Helper Scripts** (Python 3, stdlib only — auditable, do not reimplement): - [`assemble.py`](../../scripts/cluster-report/assemble.py) — resolves `$file` references into complete raw data JSON - [`aggregate.py`](../../scripts/cluster-report/aggregate.py) — aggregates raw data into structured report JSON -**CRITICAL Script Rules**: -- **NEVER** read the source code of `aggregate.py` or `assemble.py` -- **NEVER** write ad-hoc Python to parse or transform MCP output -- **NEVER** manually reconstruct data already available in MCP output +**Script Usage Rules**: +- Invoke scripts via the documented pipeline (Step 3) — do NOT reimplement their logic inline +- Do NOT write ad-hoc Python to parse or transform MCP output — the scripts handle all parsing +- You MAY read the scripts for debugging if the pipeline returns errors **Verification**: 1. Check `openshift-administration` in `mcps.json`