Skip to content

Latest commit

 

History

History
100 lines (70 loc) · 4.27 KB

File metadata and controls

100 lines (70 loc) · 4.27 KB

Security Model

This document explains the security design of cortex-code-action and the rationale behind its restrictions.

Why SQL execution is blocked

Cortex Code has the ability to execute SQL against live Snowflake accounts. In a CI/CD context this creates unacceptable risks:

  1. Data leakage: A prompt injection attack via a PR body or @cortex comment could trigger SELECT * FROM sensitive_table, with results posted as a public PR comment.
  2. Uncontrolled access: CI runners process untrusted input -- PRs from external contributors, comments from anyone with repo access. Allowing SQL means any commenter could potentially query production data.
  3. Blast radius: Unlike local development where you see results privately, GitHub Actions output is logged and publicly visible on open-source repositories.

This action is a code review tool. It never connects to Snowflake to run queries.

Hardcoded blocklist

The following tools are permanently blocked via the Cortex Code Agent SDK's canUseTool callback. They cannot be re-enabled by action inputs, custom prompts, or AGENTS.md configuration.

SQL tools

Tool Reason
SQL Core SQL execution tool
snowflake_sql_execute Snowflake SQL execution
Bash(snow sql:*) SQL via Snowflake CLI
Bash(snow query:*) Query via Snowflake CLI
Bash(snowsql:*) SnowSQL client
Bash(psql:*) PostgreSQL client
Bash(mysql:*) MySQL client
Bash(sqlite3:*) SQLite client
Any tool with "sql" in the name Catch-all for unknown SQL variants

Sensitive file paths

The following path patterns are blocked from being read:

Pattern Reason
~/.ssh/**, /**/.ssh/** SSH private keys
~/.snowflake/**, /**/.snowflake/** Snowflake connection configs and keys
.env, .env.* Environment variable files with secrets
*.p8, *.pem Private key files
*credentials*, *secrets* Generic credential files
id_rsa, id_ed25519, id_ecdsa SSH key files by name
*private_key*, *private-key* Private key files by name

How the canUseTool gate works

The action uses the canUseTool callback from the Cortex Code Agent SDK. This callback is invoked before every tool execution, regardless of what the model was prompted to do.

const securityGate = createSecurityGate(permissions);

for await (const event of query({
  prompt,
  options: {
    canUseTool: securityGate,
    permissionMode: "default",  // Never "bypassPermissions"
  },
}));

The gate has three layers:

  1. SQL block: Exact name match + fuzzy match on any tool containing "sql"
  2. Sensitive path block: Regex patterns on all path-like input fields
  3. Permission mode: In read-only mode, also blocks Write, Edit, and git write commands

If the callback itself throws an error, it denies the tool call by default (fail-closed, not fail-open).

Permission modes

Mode Read code Modify code Push commits SQL Sensitive paths
read-only (default) Yes No No Never Never
read-write Yes Yes Yes Never Never

Even in read-write mode, SQL and sensitive path restrictions remain active.

Prompt injection resistance

Because the security gate operates at the SDK level (not the prompt level), prompt injection attacks that instruct the model to "ignore previous instructions and run SELECT..." are blocked before the tool is called. The model cannot bypass a programmatic gate by changing its reasoning.

Snowflake connection

A Snowflake connection is required to run Cortex Code. The connection provides access to the AI models (LLMs) that power the review -- not data access. Use a minimal-privilege service user:

CREATE USER cortex_ci_user
  RSA_PUBLIC_KEY = '<your_public_key>'
  DEFAULT_ROLE = PUBLIC;

-- SNOWFLAKE.CORTEX_USER is sufficient for model access
GRANT DATABASE ROLE SNOWFLAKE.CORTEX_USER TO USER cortex_ci_user;

Do not use ACCOUNTADMIN or any data-access role for CI.

Responsible disclosure

If you discover a security vulnerability, please report it by opening a GitHub Security Advisory on this repository. Do not open a public issue for security vulnerabilities.