| Retrieved context is data, never permission |
Prompt-injection text is stored and displayed, never executed |
| Repository-controlled data never auto-enables executables |
Explicit local consent required for hooks, plugins, adapters |
| Transcript imports are confined to the repository root |
source import and agent import-session canonicalize and symlink-resolve the supplied path, require a regular file within the 32 MiB bound, and reject any path outside the registered repository root (invalid_argument, exit 2, transcript path must be within the repository root). import-session parses a private staged copy but records and confines the caller's path. Provider export directories (for example ~/.claude/projects) are outside every repository, so exports must be copied into the working tree first |
| Hooks are chained, never silently overwritten |
An existing hook is moved to <hook>.across-orig and run by the Across wrapper; hooks that read stdin (pre-receive, post-receive, pre-push, …) run the original first with the same input and reject if it rejects. Ownership is a marker line; upgrades are staged and renamed with rollback and keep the original; across hook uninstall restores it. Symlinked hook files and hook directories are refused |
| Checkpoint restore never mutates the user's checkout |
New git worktree created; original left untouched |
| Runner is not a sandbox |
Documented prominently; not exposed via default MCP |
| Plugins are not sandboxed |
Execution time and output bounded; SHA-256 verified where supplied |
| Backups are validated before they are used |
Archive members must be regular, listed in the manifest, unique, and match size, SHA-256 and (when recorded) mode; traversal, absolute, drive-letter, control-character and linked names are rejected; the SQLite snapshot must pass PRAGMA integrity_check |
| Restore never destroys an unrelated directory |
Restore is staged beside the target and committed by rename. A missing or empty target is used directly; a non-empty directory without across.db is refused (conflict, exit 4) even with --force; an existing Across home is replaced only with --force and kept as <target>.across-old-<UTC timestamp> |
| Across-managed directories are real directories |
Symbolic links in the ACROSS_HOME / --home / --target-home path you choose are resolved once; the directories Across manages inside a home (repositories/, mirrors/, workspaces/, plugins/, backups/, tmp/) must not be symlinks |
| HTTP auth is not an OS boundary |
Same-OS-user file access is out of scope; not tenant isolation |
| Served console requests are same-origin |
serve binds to loopback, validates Host and Origin, and requires the bearer token except for /health. The across_token cookie (HttpOnly, SameSite=Strict) set from /?token= is honoured only when Sec-Fetch-Site is absent, same-origin or none and any Origin equals the served host and port, so pages on other localhost ports cannot use it |
| Stored text is untrusted |
The console assets are embedded in the binary from web/, render records with textContent only, and are served with a CSP that includes frame-ancestors 'none' |
| Deletion is durable |
source delete removes events and index entries in one transaction and writes a tombstone; importing the same native id again, or the same kind and origin without a native id, is refused (conflict, exit 4) |