From 7d3f12fee8cd42c7fe6c7e386c60fd1ce7a716d7 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Fri, 3 Jul 2026 21:23:28 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20Sentinel:=20[CRITICAL]?= =?UTF-8?q?=20noema=5Freview=5Fgate.py=EC=9D=98=20SSRF=20=EC=B7=A8?= =?UTF-8?q?=EC=95=BD=EC=A0=90=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `NOEMA_LLM_API_URL` 환경 변수를 사용해 `urllib.request.urlopen` 호출 시 URL 스키마가 `http://` 또는 `https://` 인지 검증하는 로직 추가 - 검증 로직 추가 후 `# nosec B310` 주석을 달아 Bandit 스캐너의 경고 해결 - 관련 단위 테스트 추가하여 100% 테스트 커버리지 유지 --- scripts/ci/noema_review_gate.py | 4 +++- tests/test_noema_review_gate.py | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/scripts/ci/noema_review_gate.py b/scripts/ci/noema_review_gate.py index 1e4661b7..00521ad5 100644 --- a/scripts/ci/noema_review_gate.py +++ b/scripts/ci/noema_review_gate.py @@ -267,6 +267,8 @@ def call_llm(repo: str, number: int, pr: dict[str, Any], diff: str, truncated: b if not api_url or not api_key: print("Noema LLM review unavailable: NOEMA_LLM_API_URL or NOEMA_LLM_API_KEY is not configured.") return None + if not (api_url.startswith("http://") or api_url.startswith("https://")): + raise ValueError(f"Noema LLM review unavailable: NOEMA_LLM_API_URL must start with http:// or https://, got: {api_url}") prompt = { "role": "user", @@ -304,7 +306,7 @@ def call_llm(repo: str, number: int, pr: dict[str, Any], diff: str, truncated: b }, method="POST", ) - with urllib.request.urlopen(request, timeout=120) as response: + with urllib.request.urlopen(request, timeout=120) as response: # nosec B310 raw = response.read().decode("utf-8") data = json.loads(raw) content = (((data.get("choices") or [{}])[0].get("message") or {}).get("content") or "").strip() diff --git a/tests/test_noema_review_gate.py b/tests/test_noema_review_gate.py index 0b333ab3..954dee40 100644 --- a/tests/test_noema_review_gate.py +++ b/tests/test_noema_review_gate.py @@ -222,6 +222,10 @@ def fake_urlopen(request, timeout): with pytest.raises(RuntimeError, match="unsupported decision"): noema.call_llm("owner/repo", 1, pr, "diff", False) + monkeypatch.setenv("NOEMA_LLM_API_URL", "file:///etc/passwd") + with pytest.raises(ValueError, match="NOEMA_LLM_API_URL must start with http:// or https://"): + noema.call_llm("owner/repo", 1, pr, "diff", False) + def test_format_findings_and_submit_review(monkeypatch): findings = noema.format_findings(