From 587be5b5b49340c560258b136dd98b03904649da Mon Sep 17 00:00:00 2001 From: dsad Date: Fri, 3 Jul 2026 14:57:05 +0300 Subject: [PATCH] fix(image-gen): guard local provider inputs against credential reads --- plugins/image_gen/openai/__init__.py | 10 ++++++++++ plugins/image_gen/openrouter/__init__.py | 10 ++++++++++ tests/plugins/image_gen/test_openai_provider.py | 12 ++++++++++++ .../image_gen/test_openrouter_compat_provider.py | 12 ++++++++++++ 4 files changed, 44 insertions(+) diff --git a/plugins/image_gen/openai/__init__.py b/plugins/image_gen/openai/__init__.py index e214271bcd9..cecdac206b7 100644 --- a/plugins/image_gen/openai/__init__.py +++ b/plugins/image_gen/openai/__init__.py @@ -147,6 +147,16 @@ def _load_image_bytes(ref: str) -> Tuple[bytes, str]: ext = header.split("image/", 1)[1].split(";", 1)[0] or "png" return base64.b64decode(b64), f"image.{ext}" # Local file path. + try: + from agent.file_safety import get_read_block_error + + blocked = get_read_block_error(ref) + if blocked: + raise ValueError(blocked) + except ValueError: + raise + except Exception as exc: # noqa: BLE001 - preserve existing local-file behavior + logger.debug("OpenAI image input read guard unavailable: %s", exc) with open(ref, "rb") as fh: data = fh.read() name = os.path.basename(ref) or "image.png" diff --git a/plugins/image_gen/openrouter/__init__.py b/plugins/image_gen/openrouter/__init__.py index a3cc348ccf7..a08bae61454 100644 --- a/plugins/image_gen/openrouter/__init__.py +++ b/plugins/image_gen/openrouter/__init__.py @@ -97,6 +97,16 @@ def _to_image_url_part(ref: str) -> Optional[str]: if ref.startswith(("http://", "https://", "data:")): return ref path = Path(ref) + try: + from agent.file_safety import get_read_block_error + + blocked = get_read_block_error(ref) + if blocked: + raise ValueError(blocked) + except ValueError: + raise + except Exception as exc: # noqa: BLE001 - keep local image refs best-effort + logger.debug("OpenRouter image input read guard unavailable: %s", exc) try: raw = path.read_bytes() except OSError as exc: diff --git a/tests/plugins/image_gen/test_openai_provider.py b/tests/plugins/image_gen/test_openai_provider.py index 8a6a4985014..abd867823af 100644 --- a/tests/plugins/image_gen/test_openai_provider.py +++ b/tests/plugins/image_gen/test_openai_provider.py @@ -124,6 +124,18 @@ class TestModelResolution: # ── Generate ──────────────────────────────────────────────────────────────── +class TestSourceImageLoading: + def test_load_image_bytes_blocks_credential_store(self, tmp_path, monkeypatch): + hermes_home = tmp_path / ".hermes" + hermes_home.mkdir() + auth_json = hermes_home / "auth.json" + auth_json.write_text('{"api_key":"sk-secret"}', encoding="utf-8") + monkeypatch.setenv("HERMES_HOME", str(hermes_home)) + + with pytest.raises(ValueError, match="credential store"): + openai_plugin._load_image_bytes(str(auth_json)) + + class TestGenerate: def test_empty_prompt_rejected(self, provider): result = provider.generate("", aspect_ratio="square") diff --git a/tests/plugins/image_gen/test_openrouter_compat_provider.py b/tests/plugins/image_gen/test_openrouter_compat_provider.py index cef2f43941c..149fbc89126 100644 --- a/tests/plugins/image_gen/test_openrouter_compat_provider.py +++ b/tests/plugins/image_gen/test_openrouter_compat_provider.py @@ -169,6 +169,18 @@ class TestHelpers: assert _to_image_url_part("/no/such/file.png") is None + def test_to_image_url_part_blocks_credential_store(self, tmp_path, monkeypatch): + from plugins.image_gen.openrouter import _to_image_url_part + + hermes_home = tmp_path / ".hermes" + hermes_home.mkdir() + auth_json = hermes_home / "auth.json" + auth_json.write_text('{"api_key":"sk-secret"}', encoding="utf-8") + monkeypatch.setenv("HERMES_HOME", str(hermes_home)) + + with pytest.raises(ValueError, match="credential store"): + _to_image_url_part(str(auth_json)) + def test_extract_images(self): from plugins.image_gen.openrouter import _extract_images