Skip to content

Security: probelabs/visor

Security

docs/security.md

Security

This document covers security considerations and best practices for Visor deployments. Security is a critical aspect of any CI/CD tool that interacts with source code, AI providers, and external services.

Overview

Visor operates in sensitive environments where it has access to:

  • Source code and pull request data
  • AI provider credentials
  • GitHub tokens with repository permissions
  • External service integrations

Understanding and properly configuring security controls is essential for safe operation.


Authentication

GitHub Token vs GitHub App

Visor supports two authentication methods for GitHub integration:

Method Use Case Permissions
GitHub Token Quick setup, personal repos Repository-scoped
GitHub App Organizations, fine-grained control Installation-scoped

GitHub Token (PAT or default token):

- uses: probelabs/visor@v1
  with:
    github-token: ${{ secrets.GITHUB_TOKEN }}

GitHub App (recommended for organizations):

- uses: probelabs/visor@v1
  with:
    app-id: ${{ secrets.VISOR_APP_ID }}
    private-key: ${{ secrets.VISOR_PRIVATE_KEY }}

Best Practice: Prefer GitHub App authentication for:

  • Granular repository permissions
  • Bot identity (separate from user)
  • Organization-wide installations
  • Audit logging and traceability

See GitHub Checks and Action Reference for complete authentication setup.


AI Provider Security

AI providers require careful configuration to prevent unintended actions.

File Editing Control (allowEdit)

By default, AI agents cannot modify files. Enable only when necessary:

steps:
  auto-fix:
    type: ai
    prompt: "Fix the security vulnerabilities"
    ai:
      allowEdit: true  # Disabled by default

When to enable: Automated fix workflows, code refactoring, sandboxed environments.

When to disable: Review-only workflows, production environments, untrusted inputs.

Tool Filtering (allowedTools, disableTools)

Control which tools the AI agent can access:

steps:
  # Whitelist mode - only specified tools
  restricted:
    type: ai
    ai:
      allowedTools: ['Read', 'Grep', 'Glob']

  # Exclusion mode - block specific tools
  safe-review:
    type: ai
    ai:
      allowedTools: ['!Edit', '!Write', '!Delete']

  # Disable all tools (raw AI mode)
  conversational:
    type: ai
    ai:
      disableTools: true

Bash Command Execution (allowBash, bashConfig)

Bash execution is disabled by default. When enabled, comprehensive allow/deny lists apply:

steps:
  # Simple enable with default safe commands
  analysis:
    type: ai
    ai:
      allowBash: true

  # Advanced configuration
  custom-bash:
    type: ai
    ai:
      allowBash: true
      bashConfig:
        allow: ['npm test', 'npm run lint']
        deny: ['npm install', 'rm -rf']
        timeout: 30000
        workingDirectory: './src'

Default security:

  • ~235 safe read-only commands allowed (ls, cat, git status, grep, etc.)
  • ~191 dangerous commands blocked (rm -rf, sudo, curl, npm install, etc.)

See AI Configuration for complete AI security options.


HTTP Security

Authentication Methods

The HTTP server supports multiple authentication types:

http_server:
  auth:
    # Bearer Token
    type: bearer_token
    secret: "${WEBHOOK_SECRET}"

    # HMAC-SHA256 Signature (GitHub-compatible)
    type: hmac
    secret: "${WEBHOOK_SECRET}"

    # Basic Authentication
    type: basic
    username: "${HTTP_USERNAME}"
    password: "${HTTP_PASSWORD}"

HMAC Signature Verification

For hmac authentication:

  • Signature header: x-webhook-signature
  • Format: sha256={hash}
  • Timing-safe comparison prevents timing attacks
  • Compatible with GitHub webhook signatures

DoS Protection

Built-in protections:

  • Request size limit: Maximum 1MB request body
  • Early rejection: Content-Length validation before processing
  • Graceful errors: Returns HTTP 413 for oversized requests

TLS/HTTPS Configuration

http_server:
  tls:
    enabled: true
    cert: "${TLS_CERT}"
    key: "${TLS_KEY}"
    ca: "${TLS_CA}"  # Optional CA certificate
    rejectUnauthorized: true

Sources: Environment variables, file paths, or Let's Encrypt certificates.

See HTTP Integration for complete HTTP security configuration.


Path Traversal Protection

Visor validates all local file paths to prevent directory traversal attacks.

Protection Mechanisms

  1. Project root boundary: Paths must remain within the project root (git root or package.json location)

  2. Sensitive file blocking: Access denied to:

    • /.ssh/ - SSH keys
    • /.aws/ - AWS credentials
    • /.env - Environment files
    • /etc/passwd - System files
    • /etc/shadow - Password hashes
    • /private/ - macOS private directory

Example Blocked Paths

../../../etc/passwd          # Traversal attack
/home/user/.ssh/id_rsa       # SSH key access
config/../../../.env         # Hidden traversal

Error message: Security error: Path traversal detected. Cannot access files outside project root

This protection is implemented in the configuration loader and applies to:

  • Configuration file extends
  • Local file references
  • Template file includes

Command Provider Security

The command provider executes shell commands with security safeguards.

Command Injection Prevention

Never use uncontrolled user input directly in commands:

# DANGEROUS - PR title could contain malicious commands
bad:
  type: command
  exec: "echo '{{ pr.title }}'"  # VULNERABLE!

# SAFE - Properly escaped
safe:
  type: command
  exec: "echo '{{ pr.title | escape }}'"

Escaping Patterns

steps:
  # Use Liquid escape filter
  safe-echo:
    type: command
    exec: "echo '{{ pr.title | escape }}'"

  # Use JSON encoding for complex data
  safe-json:
    type: command
    exec: |
      cat << 'EOF' | jq .
      { "title": {{ pr.title | json }} }
      EOF

  # Avoid user input when possible
  safest:
    type: command
    exec: "echo 'PR #{{ pr.number }}'"  # Numbers are safe

Environment Variable Filtering

Only safe environment variables are exposed in Liquid templates:

  • Allowed prefixes: CI_, GITHUB_, RUNNER_, NODE_, npm_
  • Always available: PATH, HOME, USER, PWD

Note: Shell commands inherit the full process environment, so $VAR expansion has access to all variables.

Execution Limits

  • Timeout: 60 seconds default (configurable)
  • Output limit: 10MB maximum
  • Buffer protection: Prevents memory exhaustion

See Command Provider for complete security documentation.


MCP Provider Security

Command Validation

For stdio transport, commands are validated to prevent shell injection:

steps:
  mcp-check:
    type: mcp
    transport: stdio
    command: npx  # Validated command
    args: ["-y", "@probelabs/probe@latest", "mcp"]

Rejected metacharacters: ;, |, &, `, $, (), {}, []

Sandboxed JavaScript

The transform_js context runs in a secure sandbox:

Available:

  • Standard JavaScript: Array, String, Object, Math, JSON
  • Context variables: output, pr, files, outputs, env

Blocked:

  • eval, Function, require
  • File system access
  • Network access
  • Process control

URL Protocol Validation

For SSE and HTTP transports, only http: and https: protocols are allowed:

steps:
  remote-mcp:
    type: mcp
    transport: http
    url: https://mcp-server.example.com/mcp  # Only HTTPS allowed

See MCP Provider for complete MCP security documentation.


Custom Tools Security

Execution Context

Custom tools execute with the same permissions as the Visor process:

tools:
  my-tool:
    name: my-tool
    exec: 'grep -n "{{ args.pattern }}" src/'

Security implications:

  • Full file system access within process permissions
  • Environment variable access
  • Network access if commands allow

Input Validation

Always define inputSchema to validate tool inputs:

tools:
  search-tool:
    name: search-tool
    inputSchema:
      type: object
      properties:
        pattern:
          type: string
          maxLength: 100
      required: [pattern]
      additionalProperties: false  # Reject unknown properties
    exec: 'grep -n "{{ args.pattern | escape }}" src/'

Best Practices

  1. Use input validation: Reject malformed or oversized inputs
  2. Escape arguments: Use | escape filter for shell commands
  3. Limit scope: Use cwd to restrict working directory
  4. Set timeouts: Prevent runaway commands
  5. Avoid secrets in output: Filter sensitive data from tool responses

See Custom Tools for complete custom tools documentation.


Remote Configuration Security

Default: Remote URLs Blocked

By default, remote configuration URLs are blocked. Use --allowed-remote-patterns to enable:

visor --check all \
  --allowed-remote-patterns "https://github.com/myorg/,https://raw.githubusercontent.com/myorg/"

Configuration

# Only allowed if URL matches an allowed pattern
extends: https://raw.githubusercontent.com/myorg/configs/main/base.yaml

Disable Remote Entirely

visor --check all --no-remote-extends

Security Features

  1. URL allowlist: Empty by default, must explicitly allow patterns
  2. Path traversal protection: Local extends validated against project root
  3. Protocol restriction: Only http: and https: for remote configs

See Configuration for complete extends documentation.


Production Security Checklist

Authentication

  • Use GitHub App authentication for organizations
  • Rotate API keys regularly (AI providers, webhooks)
  • Store secrets in GitHub Secrets, not in code
  • Use environment-specific tokens (dev/staging/prod)

AI Providers

  • Keep allowEdit: false unless explicitly needed
  • Use allowedTools to restrict agent capabilities
  • Keep allowBash: false for review-only workflows
  • Set appropriate timeouts for AI operations

HTTP Endpoints

  • Enable TLS for all HTTP servers
  • Use HMAC or bearer token authentication
  • Implement request size limits
  • Monitor for suspicious request patterns

Configuration

  • Validate configuration files before deployment: visor validate
  • Block remote extends unless explicitly needed
  • Review extended configurations for security implications
  • Use --allowed-remote-patterns with specific URLs only

Commands and Tools

  • Escape all user input in shell commands
  • Use input schemas for custom tools
  • Set appropriate timeouts
  • Avoid executing code from untrusted PRs

Monitoring

  • Enable telemetry for audit trails
  • Review GitHub Checks for unexpected failures
  • Monitor AI provider usage and costs
  • Set up alerts for authentication failures

Related Documentation

There aren’t any published security advisories