← Back to PRs

#21861: fix: selective context gating for OWNER_ONLY privacy tags (#11900)

by Asm3r96 open 2026-02-20 13:27 View on GitHub →
docs agents size: M
## Summary Closes #11900 — **Context Leak: personal workspace files exposed to non-owner senders.** - **Problem:** OpenClaw injected the full personal context (`USER.md`, `MEMORY.md`, etc.) into every session. Any stranger messaging your agent on a public channel could ask for — and receive — your private info (email, phone, home address, API keys, etc.). - **Fix:** Introduced `<!-- OWNER_ONLY -->` / `<!-- /OWNER_ONLY -->` privacy tags. When a non-owner sends a message, `buildBootstrapContextFiles` dynamically replaces tagged regions with `[Content restricted to owner]` before the content reaches the LLM. - **Safety:** Unclosed tags conservatively strip everything from the opening tag to end-of-file, preventing accidental leaks from malformed markup. ### What changed | File | Change | |------|--------| | `src/agents/pi-embedded-helpers/bootstrap.ts` | Core stripping logic in `buildBootstrapContextFiles` — scans for OWNER_ONLY tags and redacts for non-owners | | `src/agents/bootstrap-files.ts` | Threads `senderIsOwner` through to `buildBootstrapContextFiles`; removed redundant double-call to `filterBootstrapFilesForSession` | | `src/agents/workspace.ts` | Cleaned up `filterBootstrapFilesForSession` signature (removed unused `senderIsOwner` param that belonged only in the build step) | | `src/agents/pi-embedded-runner/run/attempt.ts` | Passes `senderIsOwner` from the runner into `resolveBootstrapContextForRun` | | `src/hooks/bundled/bootstrap-extra-files/handler.ts` | Updated call signature to match new `filterBootstrapFilesForSession` params shape | | `src/agents/pi-embedded-helpers/privacy-tags.test.ts` | **New** — 4 test cases: non-owner stripping, owner preservation, unclosed tag safety, multiple tags | | `docs/reference/templates/AGENTS.md` | Added Privacy Gating rule to the Safety section | | `docs/reference/templates/USER.md` | Added empty `<!-- OWNER_ONLY -->` block as a scaffold for users | | `docs/concepts/agent-workspace.md` | Documented the tag usage for `USER.md` and `MEMORY.md` | ### How to use it Just tell your agent: > "Check my USER.md and MEMORY.md. If you see any private info like my email or phone, wrap them in the new `<!-- OWNER_ONLY -->` tags so they don't leak to others." Or manually wrap sensitive sections: ```markdown ## About Me - **Name:** Alice - **Timezone:** PST <!-- OWNER_ONLY --> - **Email:** alice@example.com - **Phone:** +1-555-0123 - **Home Address:** 123 Main St <!-- /OWNER_ONLY --> ## Context Works on the Lobster project... ``` When a non-owner messages your agent, they see the personality and public context, but the tagged sections are replaced with `[Content restricted to owner]`. ## Test plan - [x] Unit tests pass: non-owner stripping, owner preservation, unclosed tag → strip to EOF, multiple tags in one file - [x] Full test suite: 6437 passed (5 pre-existing Windows-only failures unrelated to this PR) - [ ] Manual test: verify agent responds normally to owner with full context - [ ] Manual test: verify non-owner sees redacted placeholders, cannot extract private info ## AI-assisted This PR was developed with AI assistance. The code has been reviewed, tested, and is fully understood. <!-- greptile_comment --> <h3>Greptile Summary</h3> This PR implements privacy gating to prevent personal context leaks when non-owner users interact with agents on public channels. The implementation adds `<!-- OWNER_ONLY -->` HTML comment tags that can wrap sensitive information in workspace files like `USER.md` and `MEMORY.md`. **Key Changes:** - Core stripping logic in `buildBootstrapContextFiles` (`src/agents/pi-embedded-helpers/bootstrap.ts:212-230`) scans for OWNER_ONLY tags and replaces tagged regions with `[Content restricted to owner]` when `senderIsOwner` is false - Unclosed tags conservatively strip content from opening tag to EOF to prevent accidental leaks - `senderIsOwner` parameter threaded through the bootstrap pipeline from runner → bootstrap context resolution → file building - Documentation updated with usage examples and safety guidelines - Test coverage includes: non-owner stripping, owner preservation, unclosed tag handling, and multiple tags **Unrelated Changes:** The PR also includes an MS Teams SSRF security fix (commit `51837482`) that enforces allowlist checks on all redirect hops and prevents auth header forwarding to unauthorized destinations. This is a separate security improvement merged before the main privacy tag commit. <h3>Confidence Score: 4/5</h3> - This PR is safe to merge with minor considerations - the privacy gating logic is sound and well-tested, though careful verification of the default behavior when senderIsOwner is undefined is recommended - The implementation is solid with good test coverage and conservative fail-safe behavior (unclosed tags strip to EOF). The logic correctly handles the three states: owner (true), non-owner (false), and undefined. When undefined, the check `opts?.senderIsOwner === false` evaluates to false, meaning content is NOT stripped - this treats undefined as "owner" by default, which is the safe backward-compatible choice. The threading of senderIsOwner through the pipeline is clean and the MS Teams SSRF fix is a welcome security improvement. Score is 4 (not 5) only because the default undefined behavior should be explicitly verified in production to ensure it aligns with actual sender ownership detection. - Pay close attention to `src/agents/pi-embedded-helpers/bootstrap.ts:204` - verify the default behavior when `senderIsOwner` is undefined aligns with your sender detection logic in production <sub>Last reviewed commit: 810ef27</sub> <!-- greptile_other_comments_section --> <sub>(5/5) You can turn off certain types of comments like style [here](https://app.greptile.com/review/github)!</sub> <!-- /greptile_comment -->

Most Similar PRs