Agent IDE prioritizes user control and data safety. The Agent is visible, auditable, and requires user approval before applying changes. All filesystem, Git, terminal, and Agent operations are bounded by the workspace root.
All filesystem operations (read/write/delete) are scoped to the open workspace root. The centralized workspace service enforces this boundary:
workspace::resolve_existing— resolves read paths after canonicalization and rejects any path outside the workspace root. Also rejects relative traversal (../../etc/passwd) by canonicalizing the candidate and checking the prefix.workspace::resolve_for_write— resolves write paths, including new files that do not yet exist, by validating the nearest existing ancestor is within the workspace. Rejects writes outside the workspace boundary.workspace::ensure_within_workspace— lower-level guard used by both resolve functions. Compares the canonical path prefix against the workspace root.workspace::shell_compatible_path— normalizes Windows verbatim\\?\D:\...and\\?\UNC\...prefixes into shell-compatible paths, preventing canonicalization mismatches on Windows.
Surfaces that enforce the workspace boundary:
- Filesystem commands (
read_file_content,write_file_content, file tree operations) - Agent-generated diffs (
apply_pending_diffsresolves each target throughresolve_for_write) - Git operations (status, diff, commit, branch, fetch, pull, push — all resolve through workspace service)
- Terminal cwd (spawned PTY sessions start in the workspace root; Windows
\\?\prefixes are stripped before passing tocmd.exe) - Project task cwd (non-interactive command runner inherits workspace-scoped cwd)
- Agent CLI (shared workspace resolution and boundary checks)
Path traversal protection:
- Absolute paths are checked against the workspace root after canonicalization.
- Relative paths are joined against the workspace root first, then canonicalized and checked.
- Windows verbatim path prefixes (
\\?\) are normalized centrally to prevent canonicalization bypasses.
Known gap: symlink traversal is not explicitly checked. Symlinks pointing outside the workspace would pass the canonical-path prefix check if the symlink target resolves inside the workspace, and would be rejected if it resolves outside. This has not been runtime-validated across all platforms.
The Tauri WebView enforces a CSP:
default-src 'self' ipc: http://ipc.localhost;
script-src 'self';
style-src 'self' 'unsafe-inline';
img-src 'self' asset: https://asset.localhost data:;
connect-src 'self' ipc: http://ipc.localhost http://localhost:* https://*
- Script loading is restricted to
self— no inline scripts or external script sources. connect-srcallows HTTPS connections (required for LLM API streaming) andlocalhost(required for Tauri IPC and Vite dev server).- The CSP was restored after an earlier period where it was set to
null; it is now enforced.
LLM API keys and Git HTTPS credentials are stored via the OS credential store using the keyring crate:
- Windows: Credential Manager
- macOS: Keychain
- Linux: Secret Service (libsecret)
Implementation details:
- Service name:
agent-ide - LLM credential references:
llm-profile:<profile_id> - Git credential references:
git-remote:<remote_url> - Local profile configuration JSON (
~/.agent-ide/llm-profiles.json) storescredentialRefstrings, not plaintext API keys. - The
api_keyfield inLlmProfileis markedskip_serializingso it is never written to disk through the profile config. - Frontend responses use
api_key_masked(e.g.,sk-...abc) to avoid exposing keys in IPC responses. - No keys are transmitted to any service other than the configured LLM provider endpoint.
delete_secretsilently succeeds even if the credential is missing, to support cleanup flows.
Known limitations:
- Cross-OS runtime validation is pending. The
keyringcrate behavior has not been verified on all supported platforms. - Recovery UX for inaccessible or missing credentials is minimal — the error message indicates the credential store is unavailable, but there is no guided recovery flow yet.
The Agent operates in a "suggest-then-apply" pattern with three modes:
| Mode | Behavior |
|---|---|
suggest |
Produces reviewable diffs only. User must explicitly apply. |
edit |
Produces reviewable diffs. User must explicitly apply. |
auto |
Applies pending diffs automatically after the pipeline run completes. |
Diff review controls:
- Batch: Apply All / Reject All
- Per-file: Apply or reject individual file diffs
- Per-hunk: Apply or reject individual hunks within a file diff
Safety mechanisms during diff application:
- Outside-workspace paths are rejected.
- Missing original content (empty hunks on edit diffs) is rejected.
- Ambiguous original matches (hunk text appears more than once) are rejected — the file is not modified.
- New-file hunks that would overwrite an existing file are rejected.
- Mixed new-file and edit hunks in the same diff are rejected.
- Optional
baseHashvalidation rejects stale edit diffs if the file content hash no longer matches the hash recorded when the diff was generated. - Partial-apply failures are reported structurally:
ApplyDiffsResult { applied, failed }— each failed diff includes the diff ID, file path, and error message. The failed file content is not modified. - Failed hunks within a multi-hunk diff prevent the entire file from being written (atomic per file).
Diff provenance tracks:
- Protocol (
agent-changesor legacy markdown diff) - Operation (edit or create)
- Schema version
- Change index within the model output
- Rationale for the change
- Source role and source stage (e.g.,
coder/Coder) - Regeneration chain (
regeneratedFromDiffId,regeneratedFromHunkIndex)
- Agent context includes only workspace files, user-selected sources, and local IDE state (open files, Problems, terminal output, logs, git diff, project tree summary).
- No telemetry or data collection is performed.
- Agent-generated HTML is never rendered directly:
ReactMarkdown skipHtmlis used inChatView, and markdown rendering skips HTML tags. - The
sanitizeMarkdownfunction is applied before rendering Agent output. - Action logs capture provenance (prompt, context summary, stage outputs, diff summaries, apply results) but do not leak credentials.
- LLM API key masking ensures keys never appear in IPC responses, action logs, or the UI.
- Context source choices are explicit per run: users can toggle active file, selection, open files, Problems, failed runs, terminal output, logs, git diff, and project tree independently.
- Backend context enrichment respects the user's per-run source toggles.
- Terminal cwd is scoped to the workspace root.
- Commands run with the user's local permissions (no elevation or privilege escalation).
- PTY lifecycle is managed by the Rust backend:
spawn_terminal,write_to_terminal,resize_terminal,kill_terminal. - Kill terminates the PTY cleanly by signaling the reader loop.
- Windows
\\?\verbatim path prefixes are stripped before passing cwd tocmd.exe(which rejects UNC paths). - Multi-session UI supports session tabs, new/close/restart, but all sessions are bounded by the workspace root.
- Browser preview mode shows a disabled-state message instead of attempting PTY access.
- All Git operations resolve paths through the workspace service and use
git2::Repository::discoverto locate the repository from the workspace path. - Available operations: status, staged/worktree/all diff, stage/unstage/discard, commit, branch checkout/create, remote branch checkout/tracking, fetch, fast-forward-only pull, push, upstream/ahead/behind display, conflict detection, and conflict resolution (accept current/incoming/both).
- One-shot HTTPS credential inputs for remote actions: credentials are prompted once per operation and are not persisted by default.
- Optional OS-stored HTTPS credentials via
credentials::git_credential_refandcredentials::store_secret— when the user opts in, the remote token is stored in the OS credential store and reused for future remote operations. - Force-push and destructive operations (discard, revert, reset) are available but should require explicit confirmation (confirmation UX for destructive actions is still being improved).
- Conflict resolution is presented in the UI before any auto-resolution is applied.
The Agent CLI (agent_cli) is scoped as a headless automation runner. Security controls:
- Workspace boundary: shared
workspace::resolve_existingandworkspace::resolve_for_writechecks. --allow-runauthorization: repair loops require explicit--allow-run <pattern>for each command that will be re-executed. Patterns support:- Exact match:
npm test - Prefix wildcard:
cargo * - Trusted all:
*
- Exact match:
--max-iterations: bounds the number of repair loop iterations.--timeout-seconds: bounds how long a single command or the overall run can take.--max-output-bytes: limits captured command output size.--max-diff-files: limits the number of files in a single Agent diff proposal.- Stable exit codes:
0success,1internal error,2invalid input,3changes proposed,4checks failed,5apply failed,6provider failed,7precondition failed,8cancelled.
Known gaps:
- The deny-path model (explicit path exclusions) is not yet implemented.
- Operation-level restrictions (e.g., "allow edits but not file creation") are partially implemented.
- CLI permission model should be broadened only if the CLI scope is intentionally widened beyond headless automation.
- Cancellation is cooperative —
stop_agentsets a sharedAtomicBoolflag checked in the LLM request and streaming read path viatokio::select!. There is no explicit provider-side cancellation API or transport-level abort. - Symlink traversal — symlink targets are not explicitly validated. The canonical-path prefix check provides implicit protection, but this has not been runtime-validated across platforms.
- Secret storage cross-OS validation — the
keyringcrate behavior has not been verified on all supported OS credential backends. Recovery UX for inaccessible credentials is minimal. - Workspace boundary enforcement — requires ongoing review as new command surfaces are added. All current entry points (FS, Agent diffs, Git, terminal cwd, task cwd, CLI) are guarded.
- CLI permission model — deny-path exclusions and granular operation restrictions are partially implemented.
- Capabilities configuration — the current
default.jsongrantsfs:allow-read,fs:allow-write,fs:allow-mkdir,shell:allow-spawn, andshell:allow-executebroadly. Fine-grained scope restrictions would limit the impact of any WebView compromise. - Diff hunk text matching — hunk application depends on exact or trimmed textual matching. Ambiguous matches are rejected, but there is no structural/AST-aware matching yet. Mixed applied/rejected hunk state within a single file needs clearer partial-status semantics.
- Tauri capabilities —
shell:allow-executeandshell:allow-spawnare broadly permitted in the capabilities config. Restricting these to specific commands would reduce the attack surface.
If you discover a security vulnerability, please report it by opening a private issue or contacting the maintainers directly. Do not disclose vulnerabilities publicly before a fix is available.
Include as much of the following as possible:
- Description of the vulnerability and its impact
- Steps to reproduce
- Affected versions
- Any proposed mitigations
Security-related issues will be prioritized for review and resolution.