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.
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.
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 providers require careful configuration to prevent unintended actions.
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 defaultWhen to enable: Automated fix workflows, code refactoring, sandboxed environments.
When to disable: Review-only workflows, production environments, untrusted inputs.
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: trueBash 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.
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}"For hmac authentication:
- Signature header:
x-webhook-signature - Format:
sha256={hash} - Timing-safe comparison prevents timing attacks
- Compatible with GitHub webhook signatures
Built-in protections:
- Request size limit: Maximum 1MB request body
- Early rejection:
Content-Lengthvalidation before processing - Graceful errors: Returns HTTP 413 for oversized requests
http_server:
tls:
enabled: true
cert: "${TLS_CERT}"
key: "${TLS_KEY}"
ca: "${TLS_CA}" # Optional CA certificate
rejectUnauthorized: trueSources: Environment variables, file paths, or Let's Encrypt certificates.
See HTTP Integration for complete HTTP security configuration.
Visor validates all local file paths to prevent directory traversal attacks.
-
Project root boundary: Paths must remain within the project root (git root or package.json location)
-
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
../../../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
The command provider executes shell commands with security safeguards.
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 }}'"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 safeOnly 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.
- Timeout: 60 seconds default (configurable)
- Output limit: 10MB maximum
- Buffer protection: Prevents memory exhaustion
See Command Provider for complete security documentation.
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: ;, |, &, `, $, (), {}, []
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
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 allowedSee MCP Provider for complete MCP security documentation.
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
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/'- Use input validation: Reject malformed or oversized inputs
- Escape arguments: Use
| escapefilter for shell commands - Limit scope: Use
cwdto restrict working directory - Set timeouts: Prevent runaway commands
- Avoid secrets in output: Filter sensitive data from tool responses
See Custom Tools for complete custom tools documentation.
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/"# Only allowed if URL matches an allowed pattern
extends: https://raw.githubusercontent.com/myorg/configs/main/base.yamlvisor --check all --no-remote-extends- URL allowlist: Empty by default, must explicitly allow patterns
- Path traversal protection: Local extends validated against project root
- Protocol restriction: Only
http:andhttps:for remote configs
See Configuration for complete extends documentation.
- 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)
- Keep
allowEdit: falseunless explicitly needed - Use
allowedToolsto restrict agent capabilities - Keep
allowBash: falsefor review-only workflows - Set appropriate timeouts for AI operations
- Enable TLS for all HTTP servers
- Use HMAC or bearer token authentication
- Implement request size limits
- Monitor for suspicious request patterns
- Validate configuration files before deployment:
visor validate - Block remote extends unless explicitly needed
- Review extended configurations for security implications
- Use
--allowed-remote-patternswith specific URLs only
- Escape all user input in shell commands
- Use input schemas for custom tools
- Set appropriate timeouts
- Avoid executing code from untrusted PRs
- Enable telemetry for audit trails
- Review GitHub Checks for unexpected failures
- Monitor AI provider usage and costs
- Set up alerts for authentication failures
- AI Configuration - AI provider security options
- HTTP Integration - HTTP authentication and TLS
- Command Provider - Command injection prevention
- MCP Provider - MCP security features
- Custom Tools - Tool execution security
- Configuration - Remote configuration controls
- GitHub Checks - GitHub authentication
- Action Reference - GitHub Action inputs