Security Pipeline¶
Every tool call in Vector Companion passes through RealToolHost, a capability-gated execution boundary. No tool runs directly — the pipeline enforces validation, authorization, isolation, and audit logging before any code executes.
Why Security Matters¶
Agents can invoke tools that read files, write data, search the web, and execute code. Without guardrails, a mistaken model output could delete files, exfiltrate data, or run arbitrary commands. The security pipeline ensures every tool invocation is validated, authorized, isolated, and audited.
The Pipeline¶
Every tool call passes through these steps in order:
- Manifest Validation — The tool must have a registered
ToolManifest. Unknown tools are rejected immediately. - Autonomy Policy — The current autonomy tier determines whether the tool's side-effect level is allowed, requires approval, or is denied.
- Persistent Denial — Previously denied tools are blocked without prompting.
- Persistent Grant — Previously granted tools skip the approval step entirely (grants survive restarts via SQLite).
- Approval Workflow — Tools requiring confirmation trigger a human-in-the-loop prompt with a timeout.
- SSE Event Publishing — After all checks pass,
TOOL_CALL_REQUESTandUI_TOOL_CALL_BADGEevents are published via EventBus for real-time frontend badges (consumed by Tauri'suseEvents.ts). These events wrap in try/except and never break tool execution. - Tool Execution — The tool runs with a timeout and optional process isolation for risky operations.
- Output Size Limit — Results exceeding
max_output_bytesare truncated to prevent context flooding. - Event Publishing + Audit Log — Every execution is recorded as a structured event in the EventBus and SQLite audit table.
TOOL_CALL_RESULTis published after successful execution (consumed byuseEvents.tsto update live tool messages with actual output). Errors publishTOOL_CALL_ERROR/TOOL_CALL_TIMEOUT.
Error Handling
All exceptions and timeouts are caught and returned as success=False. The pipeline never raises to the caller — agent generation continues normally with an error result.
Tool Manifests¶
A ToolManifest is a frozen dataclass that defines the security properties of a tool:
| Field | Type | Description |
|---|---|---|
name |
str |
Unique tool identifier (e.g., "web_search") |
description |
str |
Human-readable description |
side_effect_level |
SideEffectLevel |
READ, WRITE, or DESTRUCTIVE |
confirmation_policy |
ConfirmationPolicy |
When user approval is required |
max_output_bytes |
int |
Maximum response size before truncation |
timeout_seconds |
float |
Maximum execution time |
The function create_builtin_manifests() returns manifests for all 4 built-in tools. Custom tools require a manifest entry.
Autonomy Tiers¶
Four tiers control how much autonomy the agent has:
| Side Effect | Companion | Assistant | Operator | Automation |
|---|---|---|---|---|
READ |
Allowed | Allowed | Allowed | Allowed |
WRITE |
Denied | Approval | Allowed | Allowed |
DESTRUCTIVE |
Denied | Denied | Approval | Allowed |
The default production tier is Operator — read operations run freely, writes are auto-approved, and destructive actions require human confirmation.
Approval Workflow¶
When a tool requires approval, the system:
- Creates a pending approval request via
ApprovalWorkflow.create() - Waits asynchronously for user response (
wait_for_resolution()) - Resolves with
grant()ordeny() - Stores the decision persistently (survives restarts)
Sync Wrappers
The sync wrappers (create_sync, grant_sync, etc.) must not be called from within an async event loop — they will deadlock. Use the async methods in production code.
Process Isolation¶
Risky tool executions (WRITE and DESTRUCTIVE side effects) can be routed through sandboxed subprocesses:
- Decision Engine:
IsolationManager.should_isolate()checks the side-effect level againstSandboxConfig - Argument Validation:
ArgumentScannerblocks path traversal attempts and non-whitelisted domains - Execution:
SubprocessExecutoruses Windows job objects for containment; falls back toInProcessExecutorwhen isolation is not configured
The exception hierarchy: IsolationError → PathTraversalError, DomainDeniedError, SandboxTimeoutError, SandboxExecutionError.
Audit Logging¶
Every tool execution generates structured events:
| Event Type | When |
|---|---|
execution_start |
Tool invocation begins |
execution_success |
Tool completed successfully |
execution_error |
Tool raised an exception or timed out |
denied |
Tool was denied by policy or user |
granted |
User approved a tool invocation |
timeout |
Tool exceeded its time budget |
isolation_sandboxed |
Tool ran in a sandboxed subprocess |
In production, audit events are stored in SQLite via SQLiteStoreAuditAdapter. Audit events can be queried directly from the audit_events table in the SQLite store.
Content Guards¶
Injection detection for untrusted content:
- ContentCategory — classifies potentially malicious content types
- InjectionFinding — structured scan result with severity and location
- UntrustedContent — wrapper for external data (web pages, file contents)
- ContentGuard — regex-based scanner that flags suspicious patterns before processing
Loop Guards¶
Resource budget enforcement prevents runaway generation:
- BudgetExceededError — raised when token or time budget is exhausted
- LoopBudget — configurable limits (max tokens, max time, max iterations)
- LoopState — tracks current consumption during generation
- RateLimiter — per-tool or per-agent rate limiting to prevent abuse
Permission Boundaries¶
Path and network access controls:
- PermissionLevel (0–5):
NONE→RESTRICTED→STANDARD→ELEVATED→FULL - SensitiveLocation: platform-specific blocked paths (
/etc/passwd,System32,.env) - PathBoundary: workspace containment, symlink control, maximum directory depth
- PermissionManager:
check_path(),check_network(),grant(),revoke()
Provenance Tracking¶
Model and dependency provenance:
- ProvenanceKind:
MODEL,PLUGIN,NATIVE_LIB - SourceManifest: trusted source registry with wildcard pattern matching
- Checksum Verification: SHA-256 verification via
verify_checksum()/compute_checksum() - Consent Recording: user must consent before downloading new models
Production Wiring¶
The security pipeline is wired in main.py:
tool_host = ToolHostAdapter.build_tool_host(
manifests=create_builtin_manifests(),
autonomy_policy=AutonomyPolicy(tier=AutonomyTier.OPERATOR),
approval_workflow=ApprovalWorkflow(),
event_bus=event_bus,
audit_log=SQLiteStoreAuditAdapter(_store),
isolation_manager=isolation_manager, # optional
)
build_agents(config, tool_host=tool_host) # ValueError if tool_host=None
ToolHostAdapter.register_handlers(tool_host) # All tool handlers
See Also¶
- Agent System — how agents invoke tools through the pipeline
- Orchestrator — background tasks and worker delegation
- API Reference: Security — class and function reference