fix: reject secrets from caches and database parameters#162
Conversation
Greptile SummaryThis PR hardens secret-value boundaries across the HTTP cache, SQLite, and PostgreSQL integrations by rejecting
Confidence Score: 5/5Safe to merge. All three secret-rejection guards fire before any sensitive data reaches a cache, database parameter, or serialized task boundary, and the recursive contains_secret() implementation ensures nested secrets at any depth are caught. The logic change is narrow and well-contained: two helpers become fallible, three call sites per module are updated with collect::<Result<_>>()?, and an upfront guard is added in cache_fetch(). The contains_secret() implementation is recursive and covers Array, Map, Struct, and EnumValue, so no nesting depth bypasses the check. Each new code path has a focused test that also verifies the canary string does not surface in the error message. No existing behaviour is altered for non-secret values. No files require special attention. The PostgreSQL Value::Array arm still uses format!() for non-String elements, but the upfront guard guarantees no secret ever reaches that branch. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Intent Value as parameter] --> B{contains_secret recursive check}
B -- Yes --> C[IntentError type_error returned\ncanary never in message]
B -- No --> D[Proceed to call site]
D --> E[cache_fetch http.rs]
D --> F[value_to_sql_param postgres.rs]
D --> G[value_to_sqlite sqlite.rs]
D --> H[SerializedValue concurrent.rs]
E --> E2[Cache lookup then network fetch then store]
F --> F1[pg_query pg_query_one pg_execute\ncollect Result propagates error]
G --> G1[sqlite_query sqlite_query_one sqlite_execute\ncollect Result propagates error]
H --> H1[Task or Channel boundary crossing]
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[Intent Value as parameter] --> B{contains_secret recursive check}
B -- Yes --> C[IntentError type_error returned\ncanary never in message]
B -- No --> D[Proceed to call site]
D --> E[cache_fetch http.rs]
D --> F[value_to_sql_param postgres.rs]
D --> G[value_to_sqlite sqlite.rs]
D --> H[SerializedValue concurrent.rs]
E --> E2[Cache lookup then network fetch then store]
F --> F1[pg_query pg_query_one pg_execute\ncollect Result propagates error]
G --> G1[sqlite_query sqlite_query_one sqlite_execute\ncollect Result propagates error]
H --> H1[Task or Channel boundary crossing]
Reviews (1): Last reviewed commit: "fix: reject secrets from caches and data..." | Re-trigger Greptile |
Summary
Follow-up to #161 from a late architecture-review result that arrived after the original PR merged.
cache_fetch()options before URL-only cache lookup or storageSecretrather than persisting the redaction markerVerification
cargo test --all-targetscargo test --lib secret -- --nocapturecargo run --quiet -- docs --generatecargo run --quiet -- docs --validatecargo build --profile dev-release