This repository was archived by the owner on Jun 8, 2026. It is now read-only.
FEA-1407: Add sandbox scoping and transcript sanitization to agent session sync - #245
Merged
Conversation
…ssion sync - Pass SANDBOX_BASE_DIRECTORY env var to agent-monitor sidecar at spawn - Restart sidecar on sandbox directory change in settings - Patch hooks route (build script) to reject hook events outside sandbox - Patch import-history (build script) to skip sessions outside sandbox - Add defense-in-depth sandbox filter in sync service before cloud upload - Strip user content (event summary/data, agent task/metadata, session name/metadata) from sessions before cloud sync — preserves structural fields (eventType, toolName, timestamps, tokenUsage, attribution) - Add hard-gate assertions for both sandbox patches in build script - Add getSandboxBaseDirectory to AgentSessionSyncServiceOptions Testing: - 12 new unit tests for isSessionInSandbox edge cases and sanitization - 3 new static assertions for sidecar env var and build script patches - Updated existing tests to provide sandbox directory (getSandboxBaseDirectory) - Updated oversized-session tests to use tool_name padding (survives sanitization) Risks: - Empty sandbox (setup incomplete) now blocks all session sync — intentional fail-closed behavior matching the gateway's deny-all-without-sandbox posture - Sessions already in DB from before this change are filtered at sync time (defense-in-depth) but not retroactively purged from local DB
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c8dd4b1517
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
thadeusb
commented
May 27, 2026
thadeusb
left a comment
Contributor
Author
There was a problem hiding this comment.
Clean layered design, the three filter points are consistent and the sanitizer is correct. Ship it.
wongk
reviewed
May 28, 2026
wongk
reviewed
May 28, 2026
wongk
reviewed
May 28, 2026
wongk
approved these changes
May 28, 2026
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Feature
FEA-1407 — Agent Session Sync: Sandbox Scoping & Transcript Sanitization
WRK-177 — HIGH priority
Summary
cwdoutside the configured sandbox are rejected at both ingestion chokepoints (hooks route + import-history) and never enter the local DBprompt,content,stdout,stderr) from event data before cloud sync while preserving all structural metadata (tool_name,tool_input,filePath,type,interrupted,isImage,durationMs,numFiles, etc.). Also stripsagents[].task(user prompt text). Session metadata, summaries, tool args, attribution, and token usage are all preserved.SANDBOX_BASE_DIRECTORYenv varArchitecture
flowchart TD subgraph "Layer 1: Ingestion Filter" H["Claude Code Hook Event"] -->|"POST /event"| HC{"data.cwd in sandbox?"} HC -->|No| HR["Return 200 OK — skip"] HC -->|Yes / no cwd| HE["enqueueHookEvent → DB"] I["File Watcher / Cold Import"] -->|"importSession"| IC{"session.cwd in sandbox?"} IC -->|No| IR["Return skipped"] IC -->|Yes| IE["Insert/Update → DB"] end subgraph "Layer 2: Sync Service Filter" HE --> DB["dashboard.db"] IE --> DB DB -->|"syncOnce"| SF{"cwd in current sandbox?"} SF -->|No| SD["Skip — dequeue silently"] SF -->|Yes| SN["Include in batch"] end subgraph "Layer 3: Sanitization" SN --> SAN["Recursive strip:\ncontent, stdout, stderr,\nprompt, agent.task"] SAN --> CLOUD["Cloud Upload —\nstructure + metadata only"] endSanitization: What's Stripped vs Kept
prompt(user message text)content(file contents, at any depth)stdout/stderr(command output)Example — a Read tool PostToolUse event before/after:
Plan
PLN-739 — plan challenge passed (Sonnet PASS, Opus PASS)
Key Decisions
isSessionInSandbox()usespath.resolve()notfs.realpathSync()— matches existing pragmatic behavior, avoids filesystem access in generated codecontent,stdout,stderr,promptat any nesting depth insidedata, preserving all structural/metadata keysIS_SESSION_IN_SANDBOX_CJSconstant to avoid duplicationDecision Table
Verified at
.closedloop-ai/decision-tables/fea-1407.md— all delta checklist items implemented, all acceptance criteria verified.Review Summary
3 parallel reviewers (correctness/Opus, security/Sonnet, conventions/Opus). Findings:
Downstream Updates
None — no sibling features linked.
Feature Flags
None — security fix restoring intended sandbox enforcement.
Database/Migration Safety
No schema/migration changes.
Test Plan
isSessionInSandboxreturns true for cwd inside sandboxisSessionInSandboxreturns false for cwd outside sandboxisSessionInSandboxreturns false for null/empty cwdisSessionInSandboxreturns false for null/empty sandboxisSessionInSandboxwith sandbox "/" allows all pathsisSessionInSandboxrejects prefix-match without path separatorisSessionInSandboxhandles trailing slashessanitizeSessionForSyncstrips agent.tasksanitizeSessionForSyncstrips content/stdout/stderr recursively inside tool_responsesanitizeSessionForSyncpreserves structural metadata (tool_name, filePath, type, interrupted, isImage)sanitizeSessionForSyncpreserves data without stripped keyssanitizeSessionForSyncdoes not mutate original session