feat(memory-security): prevent secret leakage into agent memory with redaction, validation, and diagnostics#1224
Conversation
…h redaction, validation, and diagnostics
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughAdds a new ChangesSecret Detection & Sanitization
Sequence DiagramsequenceDiagram
actor User
participant Tool as MemoryStoreTool
participant Safety as Safety Module
participant Writer as Memory Writer
participant Storage as Persistent Storage
User->>Tool: execute(content, namespace, key, ...)
Tool->>Safety: has_likely_secret(content)?
Safety-->>Tool: true
Tool->>User: error("looks like a secret")
Note over Storage: ✗ not persisted
User->>Tool: execute(safe_content, namespace, key, ...)
Tool->>Safety: has_likely_secret(content)?
Safety-->>Tool: false
Tool->>Writer: request store(...)
Writer->>Safety: sanitize_document_input() / sanitize_json() / sanitize_text()
Safety-->>Writer: Sanitized{ value, report }
Writer->>Storage: persist(sanitized value)
Storage-->>Writer: stored
Writer-->>Tool: success
Tool-->>User: success
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/openhuman/memory/store/unified/fts5.rs (1)
140-143:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAvoid logging the full
session_idafter insert.This still writes every accepted session identifier verbatim to logs. Even with the new secret detector,
session_idis a high-risk correlation field and should be reduced to a count, hash, or other opaque handle.Suggested fix
tracing::debug!( - "[fts5] inserted episodic entry: session={}, role={}", - entry.session_id, - entry.role + "[fts5] inserted episodic entry: session_chars={} role={}", + entry.session_id.chars().count(), + entry.role );As per coding guidelines,
**/*.rs: “never log secrets or full PII”.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/openhuman/memory/store/unified/fts5.rs` around lines 140 - 143, The debug log in fts5.rs is emitting the full session identifier; replace the verbatim session_id usage in the tracing::debug call that references entry.session_id (and still mention entry.role if needed) with an opaque value—e.g., log a truncated/hashed form of entry.session_id or a session counter/handle instead—so that the tracing::debug call no longer writes the full PII; update any code that computes the placeholder (hash/truncate/lookup) next to the existing tracing::debug invocation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/openhuman/memory/safety/mod.rs`:
- Around line 303-323: is_sensitive_key currently only matches exact names and a
few suffixes, so keys like "db_password", "secret_key", or "api_secret" are
missed; update is_sensitive_key to check normalized (lowercased,
alphanumeric-only) keys for contains/ends_with patterns such as "password",
"secret", and "key" as well as the existing "token", "apikey", and
"clientsecret" checks (e.g., use normalized.contains("password") ||
normalized.ends_with("password") || normalized.contains("secret") ||
normalized.ends_with("secret") || normalized.ends_with("key") in addition to
existing matches) so common variants are masked; keep using the same normalized
variable and function name to locate and modify the logic.
- Around line 256-301: sanitize_json_inner currently recurses unbounded; add a
depth guard by changing sanitize_json_inner to accept a depth parameter (e.g.,
fn sanitize_json_inner(value: &Value, depth: usize) -> Sanitized<Value>) and
introduce a constant MAX_SANITIZE_DEPTH; on each recursive call pass depth + 1,
and if depth >= MAX_SANITIZE_DEPTH stop recursing and return a safe replacement
(e.g., Value::String(REDACTED_SECRET.to_string()) or a small sentinel) while
incrementing an appropriate counter on SanitizationReport (e.g.,
truncation/depth_redactions) so callers of sanitize_json_inner (and
sanitize_text if needed) are updated to call the new signature starting with
depth 0.
In `@src/openhuman/tools/impl/memory/store.rs`:
- Around line 95-104: The current safety rejection logs raw namespace and key
values (in the branch calling safety::has_likely_secret(content)), which can
leak secrets; change the branch so it never formats or logs namespace/key
directly—either check namespace and key with safety::has_likely_secret and
reject early, or log only non-sensitive metadata (e.g., content length and
masked identifiers or counts). Update the log::warn! call in the memory_store
safety branch to remove namespace and key from the message (use counts or masked
placeholders), and ensure the function still returns the same ToolResult::error
message without exposing identifiers.
---
Outside diff comments:
In `@src/openhuman/memory/store/unified/fts5.rs`:
- Around line 140-143: The debug log in fts5.rs is emitting the full session
identifier; replace the verbatim session_id usage in the tracing::debug call
that references entry.session_id (and still mention entry.role if needed) with
an opaque value—e.g., log a truncated/hashed form of entry.session_id or a
session counter/handle instead—so that the tracing::debug call no longer writes
the full PII; update any code that computes the placeholder
(hash/truncate/lookup) next to the existing tracing::debug invocation.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: da9491a1-d54e-408f-b38b-d2547f54fc3d
📒 Files selected for processing (9)
src/openhuman/memory/mod.rssrc/openhuman/memory/safety/mod.rssrc/openhuman/memory/store/README.mdsrc/openhuman/memory/store/unified/README.mdsrc/openhuman/memory/store/unified/documents.rssrc/openhuman/memory/store/unified/documents_tests.rssrc/openhuman/memory/store/unified/fts5.rssrc/openhuman/memory/store/unified/kv.rssrc/openhuman/tools/impl/memory/store.rs
…redaction, validation, and diagnostics (tinyhumansai#1224)
Summary
Added centralized memory safety layer to detect and sanitize secret-like values before persistence
Hardened memory persistence boundaries:
memory_docskv_globalkv_namespaceepisodic_logAdded validation in
memory_storetool:Expanded redaction coverage:
Added
[memory:safety]diagnostics:Updated memory-store documentation to reflect new security behavior
Problem
Agent memory may receive sensitive data:
Previous behavior risked:
Protection gaps:
Solution
Introduced shared safety module:
src/openhuman/memory/safety/Capabilities:
Enforcement at Memory Boundaries
Documents
KV Storage
Episodic Memory
Tool-Level Guard
memory_store:Design Tradeoffs
Identifiers
Payloads
Submission Checklist
Tests
docs/TESTING-STRATEGY.mdCoverage
pnpm test:coveragepnpm test:rust.github/workflows/coverage.ymlCoverage Matrix
docs/TEST-COVERAGE-MATRIX.mdFeature IDs
## RelatedNetwork Dependencies
Manual Smoke Checklist
docs/RELEASE-MANUAL-SMOKE.mdLinked Issues
Closes #NNNImpact
Runtime / Platform
Security
Compatibility
Performance
Related
Summary by CodeRabbit
New Features
Tests
Documentation