RagLeap
Blog

How to add tenant scopes, a tamper-evident audit log and secret redaction to a Python AI app (ragleap-security, alpha)

Short answer: ragleap-security gives a Python AI app four small building blocks: tenant Scopes, a tamper-evident AuditLog, secrets that do not print themselves (SecretStr, from_env, redact) and hard limits for untrusted input. It uses only the standard library. This guide follows the README, changelog and threat model of ragleap-security 0.1.0, which is alpha and has had no independent security review.

How do you install it and use all four?

pip install ragleap-security

This is the README example, unchanged:

from ragleap_security import AuditLog, Scope, SecretStr, from_env, redact

scope = Scope("acme", subject="alice")
log = AuditLog("audit.jsonl")
token = from_env("MY_SERVICE_TOKEN")
log.append("login.ok", {"user": "alice", "token": token}, scope)
assert log.verify().ok
print(redact(f"request failed with {token.reveal()}", [token]))

What is a Scope?

An immutable tenant scope made of a tenant, a subject, an agent and a session, with an unambiguous key, plus covers, narrow and require_scope. ragleap-memory builds on it.

What does the audit log protect against?

It is an append-only JSON Lines file with a SHA-256 hash chain, and verify() detects edits, deletions, reordering and inserted records through sequence numbers, chain links and hashes. Appends fail closed on a corrupt or incomplete log. It is tamper-evident, not tamper-proof: someone with write access can still destroy it.

How are secrets kept out of logs?

SecretStr masks str, repr, format and f-strings, refuses pickle and JSON, is unhashable and compares in constant time. from_env reads a secret from the environment by name. redact is a heuristic redactor for logs with a length cap, so it can miss a secret in an unusual shape.

How are hostile inputs limited?

check_size, check_json_shape (iterative, so it does not crash on deep nesting), bounded_read and Deadline (a cooperative deadline, which only works if your code checks it).

What does the threat model say it does not cover?

  • Not in 0.1.0: encryption, an SSRF-safe HTTP helper, a policy engine, output detectors and a red-team harness (issue 899), and prompt-injection defences (the taint rule lives in ragleap-agents).
  • Concurrent writers are protected by an in-process lock and, on POSIX, a file lock. This is covered by a thread test and a process test, and the threat model notes it is not mutation-checked.

What has been verified?

From the 0.1.0 changelog: 101 tests pass on Python 3.10 and 3.12, the CI test job passes on 3.10, 3.11 and 3.12, and all 30 deliberate breaks of a protection are killed by the mutation check.

Sources

ragleap-security on PyPI, the README, the threat model, the changelog, the library page and the tests page.

Back to the blog