Agent RulesAgent Rules
Builder
Options
Browse all rules by language and framework
Templates
Pre-built rule sets ready to use
Popular Rules
Top community-ranked rules leaderboard
GuidesAnalyzePricingContact
Builder
OptionsTemplatesPopular Rules
GuidesAnalyzePricingContact

Product

  • Builder
  • Templates
  • Browse Rules
  • My Library

Learn

  • What are AI Agent Rules?
  • Guides
  • FAQ
  • About

Resources

  • Terms
  • Privacy Policy
  • Pricing
  • Contact
  • DMCA Policy

Support

Help keep this project free.

Agent RulesAgent Rules Builder
© 2026 Aurora Algorithm Inc.
Back to Guides
security
claude-code
cursor
copilot
file-protection

How to Protect Sensitive Files From AI Coding Agents

Learn how to prevent AI coding assistants from reading or editing .env files, API keys, and secrets. Covers Claude Code, Cursor, GitHub Copilot, Windsurf, and Cline.

Agent Rules Team3/8/20268 min read

AI coding assistants like Claude Code, Cursor, and GitHub Copilot can read, modify, and index every file in your project — including .env files, API keys, credentials, and other secrets. This guide shows you how to restrict file access for every major AI coding tool.

Why File Protection Matters

When an AI assistant reads your .env file, several things can go wrong:

  • Secrets in context — API keys, database passwords, and tokens are sent to the AI provider's servers as part of the prompt
  • Accidental edits — the AI might modify or overwrite credential files
  • Leaking into suggestions — secrets seen in context can appear in code completions or chat responses
  • Compliance violations — sending credentials to third-party APIs may violate SOC 2, HIPAA, or PCI DSS requirements

The solution: tell each tool which files it must never touch.


Claude Code: Permission Deny Rules and Hooks

Claude Code uses permission deny rules in settings JSON files to restrict file access. There is no .claudeignore file — all restrictions are configured through permissions.deny arrays.

Setting Up Deny Rules

Add deny rules to .claude/settings.json (shared with team) or .claude/settings.local.json (personal, gitignored):

json
{
  "permissions": {
    "deny": [
      "Read(.env)",
      "Read(.env.*)",
      "Edit(.env)",
      "Edit(.env.*)",
      "Read(secrets/**)",
      "Edit(secrets/**)",
      "Read(*.pem)",
      "Read(*.key)",
      "Edit(*.pem)",
      "Edit(*.key)",
      "Read(serviceAccountKey.json)",
      "Edit(credentials/**)"
    ]
  }
}

Path Pattern Types

PatternMeaningExample
pathRelative to current directoryRead(.env)
/pathRelative to project rootEdit(/config/secrets.json)
//pathAbsolute filesystem pathRead(//Users/alice/secrets/**)
~/pathRelative to home directoryRead(~/Documents/*.pdf)

Global Deny Rules

For rules that apply across all projects, add them to ~/.claude/settings.json:

json
{
  "permissions": {
    "deny": [
      "Read(**/.env)",
      "Read(**/.env.*)",
      "Edit(**/.env)",
      "Edit(**/.env.*)",
      "Read(**/*.pem)",
      "Read(**/*.key)"
    ]
  }
}

PreToolUse Hook: Block Edits to Protected Files

For an additional layer, add a hook that blocks Claude from writing to sensitive files. This runs before every Edit or Write tool call.

Save as .claude/hooks/protect-files.sh:

bash
#!/bin/bash
INPUT=$(cat)
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty')

if [ "$TOOL" != "Edit" ] && [ "$TOOL" != "Write" ]; then
  exit 0
fi

FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

PROTECTED_PATTERNS=(
  "*.env"
  "*.env.*"
  "*.pem"
  "*.key"
  "*/secrets/*"
  "*/credentials/*"
)

for pattern in "${PROTECTED_PATTERNS[@]}"; do
  if [[ "$FILE_PATH" == $pattern ]]; then
    echo "BLOCKED: Cannot edit protected file $FILE_PATH" >&2
    exit 2
  fi
done

exit 0

Make it executable and register in .claude/settings.json:

bash
chmod +x .claude/hooks/protect-files.sh
json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/protect-files.sh"
          }
        ]
      }
    ]
  }
}

Limitations

  • Read deny rules are best-effort for Grep and Glob tools — not guaranteed enforcement
  • Bash commands can still access files via cat or less unless you also add Bash deny rules
  • Deny rules always win over allow rules (evaluation order: deny > ask > allow)

Cursor: .cursorignore

Cursor provides .cursorignore to exclude files from AI context, and .cursorindexingignore to block indexing only.

.cursorignore

Create a .cursorignore file in your project root:

text
# Environment and secrets
.env
.env.*
*.pem
*.key

# Cloud credentials
credentials/
secrets/
serviceAccountKey.json

# Build artifacts with potential embedded secrets
.next/
dist/

Files matching these patterns are excluded from:

  • Codebase indexing and semantic search
  • Tab completions, Agent, and Inline Edit features
  • @codebase mentions in chat

.cursorindexingignore

If you only want to block indexing but still allow direct reads:

text
# Block indexing of large generated files
dist/
*.min.js

Global Ignore Patterns

Set global patterns in Cursor Settings that apply to all projects:

text
**/.env
**/.env.*
**/credentials.json
**/*.key
**/*.pem

Cursor Rules Reinforcement

Add explicit instructions in .cursor/rules/security.mdc:

markdown
---
description: Security rules for file access
globs: *
alwaysApply: true
---

NEVER read, reference, or modify .env files.
Use .env.example for variable names. Never hardcode secret values.

Limitations

  • .cursorignore is best-effort — Cursor's docs explicitly state "complete protection isn't guaranteed due to LLM unpredictability"
  • Terminal commands executed by Agent are not blocked
  • MCP server tool calls are not blocked
  • Negation patterns cannot re-include files when a parent directory is excluded

GitHub Copilot: Content Exclusion

GitHub Copilot supports content exclusion configured through the GitHub web interface — not through a file in your repository.

Organization-Level Settings

Admins configure content exclusion at github.com > Organization > Settings > Copilot > Content exclusion:

yaml
# Exclude .env files across all repos
"*":
  - "**/.env"
  - "**/.env.*"
  - "**/*.pem"
  - "**/*.key"

# Exclude secrets directory in a specific repo
my-app:
  - "/secrets/**"
  - "credentials.json"

Repository-Level Settings

Repository admins can also set exclusions at Settings > Copilot > Content exclusion with simpler path-per-line syntax:

text
"/secrets/**"
"*.key"
"*.pem"
".env*"

.github/copilot-instructions.md

Add explicit instructions as a supplementary layer:

markdown
## Security

- Never reference or include values from .env files
- Use environment variables (process.env.X) instead of hardcoded values
- Reference .env.example for variable names, never .env

Requirements and Limitations

  • Content exclusion requires Copilot Business or Enterprise plan — individual plans cannot configure it
  • Changes take up to 30 minutes to propagate to IDEs
  • Does not block Copilot coding agent, agent mode in chat, or edit mode
  • Type information from IDE semantics may still leak through hover definitions

Windsurf: .codeiumignore

Windsurf uses .codeiumignore (not .windsurfignore) to exclude files from AI context. It also respects .gitignore patterns automatically.

.codeiumignore

Create in your project root:

text
# Secrets
.env
.env.*
*.pem
*.key
secrets/
credentials/

Global Rules

Place a .codeiumignore file in ~/.codeium/ for rules that apply to all projects.

What It Blocks

  • Cascade viewing, editing, and creating files in matched paths
  • Embedding and indexing of matched files

Windsurf Rules Reinforcement

In .windsurf/rules/security.md:

markdown
Never read or modify .env files.
Use .env.example for variable names.
Never hardcode secret values in generated code.

Limitations

  • Negation patterns (!pattern) do not reliably override .gitignore rules
  • No detailed official documentation with comprehensive syntax examples exists

Cline: .clineignore

Cline uses .clineignore to block both reading and writing of matched files.

.clineignore

Create in your project root:

text
.env
.env.*
*.pem
*.key
secrets/
credentials/
serviceAccountKey.json

What It Blocks

  • read_file — cannot read content
  • write_to_file — cannot write
  • apply_diff / replace_in_file — cannot modify
  • Automatic context gathering

What It Does Not Block

  • list_files — ignored files still appear in directory listings (marked with a lock icon)
  • Explicit @ mentions can still reference ignored files

Limitations

  • Introduced in Cline v3.3.0
  • .clineignore is monitored for changes and updates dynamically

The .env.example Pattern (Works Everywhere)

Across all tools, the most reliable practice is maintaining a .env.example that documents variables without values:

bash
# .env.example — safe to commit
DATABASE_URL=postgresql://user:password@localhost:5432/mydb
AI_GATEWAY_API_KEY=your-api-key-here
STRIPE_SECRET_KEY=sk_test_...
GITHUB_TOKEN=ghp_...

Then in your agent rules (any format):

markdown
When you need environment variable names, read .env.example — never .env.
Never hardcode secret values. Always use process.env.VARIABLE_NAME.

This works for every AI tool regardless of whether ignore files are configured.


Quick Reference: File Protection by Tool

ToolConfig LocationSyntaxBlocks ReadingBlocks WritingEnforcement
Claude Code.claude/settings.jsonJSON deny rulesYes (best-effort for Grep/Glob)YesDeny rules + hooks
Cursor.cursorignore file.gitignore syntaxBest-effortBest-effortLLM-dependent
GitHub CopilotGitHub Settings UIfnmatch YAMLContext onlyN/ABusiness/Enterprise only
Windsurf.codeiumignore file.gitignore syntaxYesYesBest-effort
Cline.clineignore file.gitignore syntaxYesYesPre-execution enforcement

Important: No AI coding tool provides guaranteed security enforcement for file access. All restrictions should be treated as defense-in-depth, not security boundaries. Keep secrets outside the project directory or use environment variable injection from secret managers.


Recommended Setup for Any Project

  1. Configure tool-specific restrictions for every AI tool your team uses
  2. Create a .env.example with variable names but no values
  3. Add security rules to your agent rules file
  4. Add a pre-commit hook to prevent accidental secret commits:
bash
#!/bin/bash
# .git/hooks/pre-commit
if git diff --cached --name-only | grep -qE '\.env$|\.env\.|\.pem$|\.key$'; then
  echo "ERROR: Attempting to commit sensitive files."
  echo "Remove them from staging: git reset HEAD <file>"
  exit 1
fi
  1. Add to .gitignore as the last line of defense:
text
.env
.env.*
*.pem
*.key
secrets/

Defense in depth: even if one layer fails, the others catch it.

Previous
How to Set Up Claude Code Hooks: Tutorial With Ready-to-Use Scripts

Explore Rules by Language

TypeScript Agent RulesPython Agent RulesGo Agent RulesRust Agent RulesJavaScript Agent RulesJava Agent Rules→ All Languages