feat(security): tool-call SecretProxy (placeholders + redact) - #94
Conversation
Keep opaque dream_secret_* placeholders in model/transcript context; resolve only inside EngineToolDispatcher execute and redact tool output before it returns to the conversation. Co-authored-by: Cursor <cursoragent@cursor.com>
🤖 CodeAnt AI — Review Status
|
Thanks for using CodeAnt! 🎉We're free for open-source projects. if you're enjoying it, help us grow by sharing. Share on X · |
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
@greptileai please review |
Greptile SummaryThe PR adds a public SecretProxy abstraction and wires placeholder resolution and result redaction through harness construction and tool dispatch.
Confidence Score: 3/5The PR should not merge until final hook replacements are redacted and multi-secret redaction preserves stable placeholders. The new proxy can return raw secrets from POST_TOOL_USE replacement results and can corrupt generated placeholders during sequential multi-secret redaction. Files Needing Attention: src/dream/engine/_tool_dispatch.py, src/dream/security/_secret_proxy.py
|
| Filename | Overview |
|---|---|
| src/dream/security/_secret_proxy.py | Introduces registration, deep placeholder resolution, and redaction; sequential replacement can mutate placeholders inserted earlier in the same pass. |
| src/dream/engine/_tool_dispatch.py | Resolves secrets for execution and redacts results before offload and hooks, but POST_TOOL_USE replacement text bypasses final redaction. |
| src/dream/_factory.py | Threads the optional SecretProxy from the public harness factory into each session engine. |
| src/dream/engine/_engine.py | Threads SecretProxy into the canonical EngineToolDispatcher construction path. |
| tests/test_engine/test_secret_proxy_dispatch.py | Covers resolution, base-result redaction, PRE-hook visibility, permission effects, and structured results but not POST-hook replacements. |
| tests/test_security/test_secret_proxy.py | Covers stable registration, nested transformations, and overlapping raw values but not raw values occurring inside generated placeholders. |
Sequence Diagram
sequenceDiagram
participant M as Model
participant H as PRE hook
participant D as Dispatcher
participant P as SecretProxy
participant T as Tool
participant O as POST hook
M->>D: placeholder-bearing input
D->>H: placeholders
H-->>D: input/replacement
D->>P: resolve input
P-->>D: raw secret values
D->>T: execute with raw values
T-->>D: tool result
D->>P: redact result
P-->>D: placeholder-bearing result
D->>O: redacted summary
O-->>D: optional replacement_result
D-->>M: final result
Comments Outside Diff (2)
-
src/dream/engine/_tool_dispatch.py, line 212-213 (link)Hook replacements bypass redaction
When a
POST_TOOL_USEhook returns a replacement containing a registered raw secret, the dispatcher applies it after the only redaction pass and returns it directly, exposing the secret in the model-facing transcript.How this was verified: The result path goes from
_offload_and_recordredaction through the laterreplacement_resultassignment to the direct return.Prompt To Fix With AI
This is a comment left during a code review. Path: src/dream/engine/_tool_dispatch.py Line: 212-213 Comment: **Hook replacements bypass redaction** When a `POST_TOOL_USE` hook returns a replacement containing a registered raw secret, the dispatcher applies it after the only redaction pass and returns it directly, exposing the secret in the model-facing transcript. **How this was verified:** The result path goes from `_offload_and_record` redaction through the later `replacement_result` assignment to the direct return. --- For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
-
src/dream/security/_secret_proxy.py, line 1637-1639 (link)Sequential redaction corrupts placeholders
When one registered raw value occurs inside another secret's generated
dream_secret_*placeholder, a later replacement rewrites the placeholder inserted by an earlier pass, causing redaction to return a corrupted placeholder instead of the stable value returned byregister.Prompt To Fix With AI
This is a comment left during a code review. Path: src/dream/security/_secret_proxy.py Line: 1637-1639 Comment: **Sequential redaction corrupts placeholders** When one registered raw value occurs inside another secret's generated `dream_secret_*` placeholder, a later replacement rewrites the placeholder inserted by an earlier pass, causing redaction to return a corrupted placeholder instead of the stable value returned by `register`. --- For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
Prompt To Fix All With AI
### Issue 1
src/dream/engine/_tool_dispatch.py:212-213
**Hook replacements bypass redaction**
When a `POST_TOOL_USE` hook returns a replacement containing a registered raw secret, the dispatcher applies it after the only redaction pass and returns it directly, exposing the secret in the model-facing transcript.
**How this was verified:** The result path goes from `_offload_and_record` redaction through the later `replacement_result` assignment to the direct return.
```suggestion
if post.replacement_result is not None:
content = post.replacement_result
if self.secret_proxy is not None:
content = self.secret_proxy.redact_text(content)
```
### Issue 2
src/dream/security/_secret_proxy.py:1637-1639
**Sequential redaction corrupts placeholders**
When one registered raw value occurs inside another secret's generated `dream_secret_*` placeholder, a later replacement rewrites the placeholder inserted by an earlier pass, causing redaction to return a corrupted placeholder instead of the stable value returned by `register`.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Reviews (1): Last reviewed commit: "refactor(security): type structured reda..." | Re-trigger Greptile
…adow checkpoints, prompt surfaces
Thanks for using CodeAnt! 🎉We're free for open-source projects. if you're enjoying it, help us grow by sharing. Share on X · |
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
User description
Summary
dream.security.SecretProxy: register secrets → stabledream_secret_*placeholders, resolve at trusted tool execution, redact resultsEngineToolDispatcher.secret_proxy(PRE hooks still see placeholders; execute gets real values)@pytest.mark.evalproving raw secrets never leak into tool resultsCloses the Hermes/Paperclip gap where stacks only redacted or env-injected secrets rather than proxying them.
Test plan
uv run pytest tests/test_security tests/test_engine/test_secret_proxy_dispatch.py tests/evals/eval_secret_proxy.pyuv run ruff check/uv run mypyon touched modulesMade with Cursor
CodeAnt-AI Description
Keep registered secrets out of model-facing tool calls and results
What Changed
dream_secret_*placeholders in model inputs, transcripts, and pre-tool hooksImpact
✅ Fewer secret leaks in tool results✅ Safer transcripts and tool hooks✅ Secrets remain available to trusted tools💡 Usage Guide
Checking Your Pull Request
Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.
Talking to CodeAnt AI
Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:
This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.
Example
Preserve Org Learnings with CodeAnt
You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:
This helps CodeAnt AI learn and adapt to your team's coding style and standards.
Example
Retrigger review
Ask CodeAnt AI to review the PR again, by typing:
Check Your Repository Health
To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.