Files
Pyra/tests/unit/test_security_boundaries.py
T
curo1305 251e509ee0 test: comprehensive test suite
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>
2026-05-17 12:55:06 +02:00

41 lines
1.3 KiB
Python

import pytest
from pyra.security.boundaries import VaultAccessError, PyraSecurityError, assert_safe_path
def test_vault_path_blocked(tmp_pyra_home):
from pyra.security.boundaries import VAULT_PATH
with pytest.raises(VaultAccessError):
assert_safe_path(VAULT_PATH / "secrets" / "api_keys.json")
def test_vault_root_blocked(tmp_pyra_home):
from pyra.security.boundaries import VAULT_PATH
with pytest.raises(VaultAccessError):
assert_safe_path(VAULT_PATH)
def test_memory_path_allowed(tmp_pyra_home):
memory_path = tmp_pyra_home / "memory" / "user" / "profile.md"
memory_path.parent.mkdir(parents=True, exist_ok=True)
memory_path.touch()
assert_safe_path(memory_path) # must not raise
def test_config_path_allowed(tmp_pyra_home):
config = tmp_pyra_home / "config.yaml"
config.touch()
assert_safe_path(config) # must not raise
def test_check_vault_lock_passes(tmp_pyra_home):
from pyra.security.boundaries import check_vault_lock
check_vault_lock() # sentinel exists, must not raise
def test_check_vault_lock_fails_when_missing(tmp_pyra_home):
from pyra.security.boundaries import check_vault_lock
lock = tmp_pyra_home / "vault" / ".vault_lock"
lock.unlink()
with pytest.raises(PyraSecurityError):
check_vault_lock()