fix(memory): guard local uploads against credential reads

This commit is contained in:
dsad 2026-07-03 19:41:40 +03:00 committed by Teknium
parent d577408f3f
commit e02cef0d0d
4 changed files with 117 additions and 1 deletions

View file

@ -1298,6 +1298,26 @@ def test_tool_add_resource_uploads_file_uri(tmp_path):
assert result["root_uri"] == "viking://resources/sample"
def test_tool_add_resource_rejects_hermes_credential_file_upload(tmp_path, monkeypatch):
import agent.file_safety as fs
hermes_home = tmp_path / "hermes_home"
hermes_home.mkdir()
auth_json = hermes_home / "auth.json"
auth_json.write_text('{"OPENROUTER_API_KEY":"sk-test-secret"}', encoding="utf-8")
monkeypatch.setattr(fs, "_hermes_home_path", lambda: hermes_home)
provider = OpenVikingMemoryProvider()
provider._client = MagicMock()
result = json.loads(provider._tool_add_resource({"url": str(auth_json)}))
assert "error" in result
assert "credential store" in result["error"]
provider._client.upload_temp_file.assert_not_called()
provider._client.post.assert_not_called()
def test_tool_add_resource_uploads_existing_local_directory_and_cleans_zip(tmp_path):
docs = tmp_path / "docs"
docs.mkdir()
@ -1372,6 +1392,44 @@ def test_tool_add_resource_directory_zip_skips_symlink_escape(tmp_path):
assert b"do not upload" not in b"".join(archive_entries["payloads"].values())
def test_tool_add_resource_directory_zip_skips_hermes_credential_files(tmp_path, monkeypatch):
import agent.file_safety as fs
hermes_home = tmp_path / "hermes_home"
hermes_home.mkdir()
(hermes_home / "guide.md").write_text("# Guide\n", encoding="utf-8")
(hermes_home / "auth.json").write_text(
'{"OPENROUTER_API_KEY":"sk-test-secret"}',
encoding="utf-8",
)
monkeypatch.setattr(fs, "_hermes_home_path", lambda: hermes_home)
provider = OpenVikingMemoryProvider()
provider._client = MagicMock()
archive_entries = {}
def inspect_upload(path):
with zipfile.ZipFile(path) as archive:
archive_entries["names"] = archive.namelist()
archive_entries["payloads"] = {
name: archive.read(name)
for name in archive.namelist()
}
return "upload_hermes_home.zip"
provider._client.upload_temp_file.side_effect = inspect_upload
provider._client.post.return_value = {
"status": "ok",
"result": {"root_uri": "viking://resources/hermes_home"},
}
result = json.loads(provider._tool_add_resource({"url": str(hermes_home)}))
assert result["status"] == "added"
assert archive_entries["names"] == ["guide.md"]
assert b"sk-test-secret" not in b"".join(archive_entries["payloads"].values())
def test_tool_add_resource_cleans_local_directory_zip_when_add_fails(tmp_path):
docs = tmp_path / "docs"
docs.mkdir()

View file

@ -0,0 +1,40 @@
from __future__ import annotations
from unittest.mock import MagicMock
import agent.file_safety as fs
from plugins.memory.retaindb import RetainDBMemoryProvider
def test_upload_file_rejects_hermes_credential_store(tmp_path, monkeypatch):
hermes_home = tmp_path / "hermes_home"
hermes_home.mkdir()
auth_json = hermes_home / "auth.json"
auth_json.write_text('{"OPENAI_API_KEY":"sk-test-secret"}', encoding="utf-8")
monkeypatch.setattr(fs, "_hermes_home_path", lambda: hermes_home)
provider = RetainDBMemoryProvider()
provider._client = MagicMock()
result = provider._dispatch("retaindb_upload_file", {"local_path": str(auth_json)})
assert "error" in result
assert "credential store" in result["error"]
provider._client.upload_file.assert_not_called()
def test_upload_file_allows_regular_file(tmp_path):
note = tmp_path / "note.md"
note.write_text("# Note\n", encoding="utf-8")
provider = RetainDBMemoryProvider()
provider._client = MagicMock()
provider._client.upload_file.return_value = {
"file": {"id": "file-1", "name": "note.md"},
}
result = provider._dispatch("retaindb_upload_file", {"local_path": str(note)})
provider._client.upload_file.assert_called_once()
assert provider._client.upload_file.call_args.args[0] == note.read_bytes()
assert result["file"]["id"] == "file-1"