Product · Security Directives · DevSecOps

Define Your AI Coding Guardrails in 20 Lines of YAML

.codeslick.ymllets you commit your team's security contract alongside your code. Custom rules, false positive suppressions, severity remaps, and enforcement thresholds — applied consistently across your CLI pre-commit hook, GitHub PR analysis, and MCP Server.

March 21, 20266 min readSecurity Directives

Security tools that can't be configured become noise generators. Every team has context that no static analyzer ships with: legacy patterns that are safe in their codebase, API integrations that require specific authorization patterns, or rules from a compliance audit that don't map to any existing check ID. Security Directives give you a versioned, code-reviewed policy file that every CodeSlick surface reads and enforces.

The problem with tool-level configuration

Most security tools are configured at the account or organization level — a dashboard setting, an environment variable, a CLI flag someone remembers to pass. That configuration lives outside the repository, which means it's not versioned, not code-reviewed, and not reproducible.

When a new team member runs a scan, they get different results than CI does. When someone adds a suppression, no one reviews why. When the policy changes, there's no PR to review and no git blame to explain the decision.

.codeslick.yml is the alternative: a file you commit with your code, review in your PRs, and version with your project. The policy travels with the repository.

What it looks like

Here is a realistic configuration for a Next.js API project:

# .codeslick.yml — committed to your repository root
version: "1"

prohibit:
  # Custom rule: no debug logging in production API code
  - id: NO-CONSOLE-PROD
    pattern: 'console\.(log|debug|info)\('
    message: "Remove debug logging before merging"
    severity: medium
    in:
      - "src/app/api/**/*.ts"

require:
  # Compliance rule: all API routes must validate the session
  - id: API-AUTH
    pattern: "getServerSession|auth\(\)|withAuth"
    message: "All API routes must validate the session"
    severity: high
    in:
      - "src/app/api/**/*.ts"

overrides:
  # Known false positive in our ORM layer
  - rule: CS-JS-001
    suppress: true
    reason: "Parameterized queries used exclusively — confirmed in security review Q1 2026"

thresholds:
  fail_cli_on: [critical, high]   # pre-commit hook exits 1
  block_pr_on: [critical, high]   # GitHub App blocks merge

One file, three surfaces

The same .codeslick.yml is read by every CodeSlick surface. You define the policy once.

CLI Pre-commit

codeslick scan reads the policy file from your repo root. Custom rules run alongside the 306 built-in checks. If fail_cli_on is breached, exit code 1 blocks the commit.

$ git commit -m "feat: add payment"
[CodeSlick] Policy: API-AUTH violation
[CodeSlick] Missing session check
Commit blocked (exit 1)
GitHub App

The GitHub App fetches .codeslick.ymlfrom the PR's head commit via the GitHub API. Policy violations appear in the PR comment alongside security findings. If block_pr_on is breached, the status check blocks merge.

Policy: .codeslick.yml applied
1 custom rule violation (API-AUTH)
1 check suppressed (CS-JS-001)
Status: BLOCKED
MCP Server

In Cursor or Claude Desktop, use the check_security_policy tool to inspect the active policy before scanning. See configured thresholds, suppressed checks, and custom rules at a glance.

> check_security_policy
Status: VALID
fail_cli_on: critical, high
1 rule suppressed (CS-JS-001)
1 prohibit rule active

Four things you can do

1. Prohibit patternsCustom SAST rules for your codebase

Define regex patterns that must not appear in matched files. Scoped to file globs so the rule only fires where it makes sense. One violation per file per rule — no noise from repeated matches.

Rule definition

prohibit:
  - id: NO-SHELL-EXEC
    pattern: 'shell=True'
    message: "shell=True is a command injection risk"
    severity: critical
    in:
      - "**/*.py"

What gets flagged

# This triggers the rule
subprocess.run(
  user_input,
  shell=True  # ← violation
)

# This is clean
subprocess.run(
  ['ls', '-la'],
  shell=False
)
2. Require patternsEnforce compliance baselines

Define patterns that must be present in matched files. Useful for compliance requirements: every API handler must call your auth middleware, every database module must import your audit logger, every payment function must have a rate-limit decorator.

require:
  - id: AUDIT-LOG
    pattern: "auditLogger\.record\|audit_log\("
    message: "All payment handlers must call the audit logger"
    severity: high
    in:
      - "**/payments/**/*.ts"
      - "**/billing/**/*.ts"
3. Override built-in checksSuppress false positives with justification

Suppress specific CodeSlick check IDs that produce known false positives in your codebase, or remap a check to a different severity based on your threat model. Every suppression requires a reason field — so the decision is documented and reviewable in your git history.

Suppress a false positive

overrides:
  - rule: CS-JS-001
    suppress: true
    reason: "Parameterized queries only.
      Reviewed in security audit 2026-Q1."
    in:
      - "src/models/**/*.ts"

Raise severity for your context

overrides:
  - rule: CS-TS-011
    severity: critical
    reason: "Our threat model treats
      type coercion as critical
      in financial calculation code."
4. Set enforcement thresholdsControl when CI blocks

By default, CodeSlick blocks the CLI pre-commit hook on criticals and blocks GitHub PRs on critical and high findings. Thresholds let you tighten or loosen this per-repository.

thresholds:
  # Strict — block everything above low severity in pre-commit
  fail_cli_on: [critical, high, medium]

  # Standard — only block PRs on critical and high
  block_pr_on: [critical, high]

  # Cap total findings — useful during a security hardening sprint
  max_findings: 10

Fail-open by design

A misconfigured policy file never blocks your pipeline. If .codeslick.yml is absent, unreadable, or contains invalid YAML, CodeSlick logs a warning and continues with global defaults. Your existing scan behavior is completely unaffected.

No file

Global defaults. No findings suppressed.

Invalid YAML

Warning logged. Global defaults. Scan completes.

Unknown field

Field ignored. Known fields applied.

One syntax note worth knowing

YAML double-quoted strings process their own escape sequences — and most regex metacharacters (\., \b, \() are not recognized YAML escapes. Use single-quoted strings for patterns that contain backslashes:

Causes a parse error
pattern: "console\.log\("
Correct
pattern: 'console\.log\('

Add .codeslick.yml to your next PR

Start with five lines — one suppression and one threshold override. Review it in your next PR. Build from there.