Skip to content

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:

  1. Manifest Validation — The tool must have a registered ToolManifest. Unknown tools are rejected immediately.
  2. Autonomy Policy — The current autonomy tier determines whether the tool's side-effect level is allowed, requires approval, or is denied.
  3. Persistent Denial — Previously denied tools are blocked without prompting.
  4. Persistent Grant — Previously granted tools skip the approval step entirely (grants survive restarts via SQLite).
  5. Approval Workflow — Tools requiring confirmation trigger a human-in-the-loop prompt with a timeout.
  6. SSE Event Publishing — After all checks pass, TOOL_CALL_REQUEST and UI_TOOL_CALL_BADGE events are published via EventBus for real-time frontend badges (consumed by Tauri's useEvents.ts). These events wrap in try/except and never break tool execution.
  7. Tool Execution — The tool runs with a timeout and optional process isolation for risky operations.
  8. Output Size Limit — Results exceeding max_output_bytes are truncated to prevent context flooding.
  9. Event Publishing + Audit Log — Every execution is recorded as a structured event in the EventBus and SQLite audit table. TOOL_CALL_RESULT is published after successful execution (consumed by useEvents.ts to update live tool messages with actual output). Errors publish TOOL_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:

Companion → Assistant → Operator → Automation
(minimal)     (standard)   (elevated)   (full)
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:

  1. Creates a pending approval request via ApprovalWorkflow.create()
  2. Waits asynchronously for user response (wait_for_resolution())
  3. Resolves with grant() or deny()
  4. 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 against SandboxConfig
  • Argument Validation: ArgumentScanner blocks path traversal attempts and non-whitelisted domains
  • Execution: SubprocessExecutor uses Windows job objects for containment; falls back to InProcessExecutor when isolation is not configured

The exception hierarchy: IsolationErrorPathTraversalError, 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): NONERESTRICTEDSTANDARDELEVATEDFULL
  • 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