251e509ee0
Unit tests: - test_security_boundaries.py: vault block, vault lock sentinel - test_security_injection.py: all 4 injection categories, case-insensitive - test_vault_rw.py: roundtrip, file permissions (chmod 400), no key in config - test_config.py: schema roundtrip, no api_key field, chmod 600 on config.yaml - test_memory_reader.py: list, read, sandboxing, context loading - test_memory_writer.py: write, append, index update, traversal blocked, chmod 600 - test_providers.py: required fields, unique IDs, litellm prefix format - test_renderer.py: key redaction for sk-ant-, sk-, AIza patterns Security tests: - test_vault_ai_isolation.py: 7 traversal patterns blocked via memory read/write - test_path_traversal.py: 20+ traversal patterns — all rejected for read and write - test_prompt_injection.py: 21-item corpus + 5 clean texts (no false positives) Integration tests: - test_lmstudio.py: live call to localhost:1234, streaming, full stack session, injection scan on real output (skips if LM Studio not running) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
60 lines
2.1 KiB
Python
60 lines
2.1 KiB
Python
import pytest
|
|
from pyra.security.boundaries import VaultAccessError
|
|
|
|
|
|
def test_write_creates_file(tmp_pyra_home):
|
|
from pyra.memory.writer import write_memory
|
|
path = write_memory("knowledge/test.md", "# Knowledge\n\nSome facts.")
|
|
assert path.exists()
|
|
assert path.read_text() == "# Knowledge\n\nSome facts."
|
|
|
|
|
|
def test_write_updates_index(tmp_pyra_home):
|
|
from pyra.memory.writer import write_memory
|
|
write_memory("user/notes.md", "Notes here.")
|
|
index = (tmp_pyra_home / "memory" / "MEMORY_INDEX.md").read_text()
|
|
assert "notes" in index.lower()
|
|
|
|
|
|
def test_append_to_existing(tmp_pyra_home):
|
|
from pyra.memory.writer import write_memory, append_memory
|
|
write_memory("context/ongoing.md", "First line.")
|
|
append_memory("context/ongoing.md", "Second line.")
|
|
from pyra.memory.reader import read_memory
|
|
content = read_memory("context/ongoing.md")
|
|
assert "First line." in content
|
|
assert "Second line." in content
|
|
|
|
|
|
def test_append_creates_file_if_missing(tmp_pyra_home):
|
|
from pyra.memory.writer import append_memory
|
|
path = append_memory("context/new_file.md", "Created by append.")
|
|
assert path.exists()
|
|
|
|
|
|
def test_write_absolute_path_blocked(tmp_pyra_home):
|
|
from pyra.memory.writer import write_memory
|
|
with pytest.raises((ValueError, PermissionError, VaultAccessError)):
|
|
write_memory("/etc/passwd", "evil")
|
|
|
|
|
|
def test_write_home_relative_blocked(tmp_pyra_home):
|
|
from pyra.memory.writer import write_memory
|
|
with pytest.raises((ValueError, PermissionError, VaultAccessError)):
|
|
write_memory("~/secret_file.md", "evil")
|
|
|
|
|
|
def test_write_traversal_blocked(tmp_pyra_home):
|
|
from pyra.memory.writer import write_memory
|
|
with pytest.raises((VaultAccessError, PermissionError, ValueError)):
|
|
write_memory("../../vault/secrets/api_keys.json", "evil")
|
|
|
|
|
|
def test_file_permissions(tmp_pyra_home):
|
|
import os
|
|
from pyra.memory.writer import write_memory
|
|
path = write_memory("user/perm_test.md", "content")
|
|
if os.name != "nt":
|
|
mode = oct(path.stat().st_mode)[-3:]
|
|
assert mode == "600"
|