Skip to content

Security Gate Patterns

Z-M-Huang edited this page Feb 23, 2026 · 6 revisions

Security Gate Patterns

The security gate hook (security-gate.ts) checks code against 21 regex patterns across 9 CWEs. This page documents every pattern.

CWE-798: Hardcoded Secrets

Pattern 1: Hardcoded Passwords and API Keys

Detects assignments of literal strings to variables with secret-related names (password, api_key, secret, token, etc.).

Catches: Variable assignments like pw = "literal_value" where the variable name suggests a credential.

Allows: References to environment variables, empty strings, or function calls.

Pattern 2: AWS Access Keys

Detects AWS access key IDs — 20-character strings starting with AKIA, ASIA, ABIA, ACCA, or ANPA.

Pattern 3: Private Keys

Detects PEM-encoded private key headers (RSA, EC, DSA, OPENSSH, PGP).

Pattern 4: JWT Tokens

Detects JSON Web Tokens — three base64url-encoded segments separated by dots, starting with eyJ.

Pattern 15: Database Connection Strings with Credentials

Detects database connection URIs with embedded username and password (e.g., mongodb://user:pass@host, postgres://user:pass@host). Covers MongoDB, PostgreSQL, MySQL, Redis, and AMQP protocols.

Catches: Connection strings with ://user:password@host format.

Allows: Connection strings without embedded credentials (e.g., mongodb://host:27017/mydb).

Pattern 16: Hardcoded Bearer Tokens

Detects Bearer tokens with 40+ character values hardcoded in strings.

Catches: Literal "Bearer eyJabc..." strings with long token values.

Allows: Short placeholders like "Bearer ${token}".

Pattern 17: Google/GitHub API Key Prefixes

Detects API keys with known provider prefixes: Google (AIza + 35 chars), GitHub PATs (ghp_, gho_, ghs_ + 36 chars), and GitHub fine-grained tokens (github_pat_ + 22+ chars).


CWE-89: SQL Injection

Pattern 5: SQL String Concatenation

Detects SQL queries built by concatenating variables. Triggers when SQL keywords (SELECT, INSERT, UPDATE, DELETE, DROP, ALTER, CREATE, EXEC, UNION, MERGE, GRANT, REVOKE, TRUNCATE) appear with string concatenation operators (+, template literals).

Catches: Building SQL strings by appending user input with + operator.

Allows: Parameterized queries, query builder methods, ORMs.

Pattern 6: SQL Template Literal Injection

Detects SQL queries using template literals with ${} interpolation. Also covers Prisma unsafe methods ($queryRawUnsafe, $executeRawUnsafe) and Knex raw methods (whereRaw, havingRaw, orderByRaw, joinRaw) with concatenation.

Allows: Prisma tagged template syntax ($queryRaw`...`) which is parameterized and safe.


CWE-95: Code Injection

Pattern 7: eval() with User Input (JavaScript/Python)

Detects eval() called with a variable or expression rather than a string literal.

Catches: Passing variables, function return values, or expressions to eval.

Allows: Eval with literal strings (static content).

Pattern 8: Shell eval with Dynamic Input (Bash only)

Only checked for Bash tool calls.

Detects shell eval commands with variable expansion ($var, $(...), backtick substitution).


CWE-79: Cross-Site Scripting

Pattern 9: innerHTML with Variable

Detects .innerHTML being assigned a variable rather than a string literal.

Catches: Assigning variables, function return values, or expressions to innerHTML.

Allows: Assigning empty strings or static HTML string literals. Use of .textContent (which is always safe).


CWE-502: Insecure Deserialization

Pattern 10: Python pickle

Detects use of Python's pickle module for loading/deserializing data. Pickle is fundamentally unsafe with untrusted data — use JSON instead.

Pattern 11: YAML load without safe Loader

Detects YAML load calls that don't specify a safe Loader parameter. The safe alternative is yaml.safe_load() or explicitly passing Loader=yaml.SafeLoader.

Pattern 12: YAML unsafe/full load

Detects explicit use of YAML's unsafe or full loader functions, which can execute arbitrary code.

Pattern 13: node-serialize

Detects use of the node-serialize library's deserialization function, which can lead to remote code execution.


CWE-643: XPath Injection

Pattern 18: XPath String Concatenation

Detects .xpath() calls with string concatenation (f-strings, + operator, template literals). XPath injection allows attackers to manipulate queries to access unauthorized data.

Catches: .xpath(f"/users/user[@name='{name}']") and similar interpolation patterns.

Allows: Static XPath strings, parameterized XPath queries.


CWE-1321: Prototype Pollution

Pattern 19: proto and constructor.prototype Assignment

Detects direct assignment to __proto__ (bracket or dot notation) and constructor.prototype or constructor["prototype"]. Prototype pollution can lead to denial of service, property injection, or remote code execution.

Catches: obj["__proto__"] = ..., obj.__proto__ = ..., obj.constructor.prototype.isAdmin = true, constructor["prototype"] bracket access.

Allows: Defensive checks like if (key === "__proto__") throw.


CWE-1336: Server-Side Template Injection (SSTI)

Pattern 20: Jinja2 Template() / from_string() with Variable

Detects Jinja2 Template() constructor called with a variable argument, or .from_string() called on a Jinja2 environment variable (e.g., env, jinja_env). When user-controlled input reaches the template engine, attackers can inject template directives to achieve remote code execution.

Catches: Template(user_input), env.from_string(user_data), jinja_env.from_string(data) — variable arguments on template constructors or Jinja2 environment objects.

Allows: Template("<h1>Hello</h1>") (string literal), myLib.from_string(data) (non-template library — only Jinja2 environment prefixes trigger).

Pattern 21: Handlebars.compile() with Variable

Detects Handlebars.compile() called with a variable argument instead of a string literal. Dynamic Handlebars compilation with user input enables template injection.

Catches: Handlebars.compile(userTemplate) — variable argument.

Allows: Handlebars.compile("<div>{{name}}</div>") — string literal argument.


CWE-116: Encoded Shell Execution

Only checked for Bash tool calls.

Pattern 14: Decode-to-Execution

Detects encoded data (base64, xxd) being decoded and piped to shell execution. This pattern catches:

  • Base64-decoded content piped to sh/bash/shell
  • xxd-reversed content piped to execution
  • sh -c combined with base64 decode subshells

How Patterns Are Applied

By Tool Type

Tool Patterns Checked
Write All except CWE-95 shell eval and CWE-116
Edit All except CWE-95 shell eval and CWE-116 (checks new_string field)
Bash All patterns including Bash-specific ones (CWE-95 shell eval, CWE-116)

Content Extraction

  • Write: Checks the content field
  • Edit: Checks the new_string field
  • Bash: Checks the command field

Exit Codes

  • 0 — No patterns matched (allow)
  • 2 — One or more patterns matched (block). All matching CWEs are reported.

Ignore Behavior

Patterns can be suppressed by adding CWE entries to the ignore array in .vcp/config.json:

{
  "ignore": ["CWE-798"]
}

This disables all patterns under that CWE. Individual patterns within a CWE cannot be selectively disabled.

When CWE patterns are suppressed, the security gate prints a warning (VCP Security Gate — WARNING: Suppressed ...) to stderr so the user knows a finding was matched but ignored. The tool call is allowed through (exit 0).

Test Coverage

The security gate has 50 tests in security-gate.test.ts covering:

  • Baseline detection for all 21 patterns
  • Bash-specific pattern scoping
  • SSTI detection (Jinja2, Handlebars) with false-positive avoidance
  • CWE ignore behavior (suppression and warnings)
  • Config edge cases (no config, malformed JSON, parent directory isolation)
  • False-positive avoidance (defensive __proto__ checks, safe DB URLs, short Bearer placeholders, string literal templates)

Clone this wiki locally