Agent Deny Path Lists — Secrets, Vendor, Bypass Detection

Opening a whole repo to an agent makes secrets, vendor trees, and local credentials easy to leak into context or tool paths. A chat note (“don’t read those”) is weaker than locking the same patterns into .gitignore and .cursorignore (or an equivalent agent deny-path list).

This post covers only three axes: secrets? · vendor? · detecting bypass? No pricing, plans, tokens, affiliates, or invented reviews.

Grounded in Git — gitignore, Cursor Ignore file (.cursorignore uses .gitignore syntax; blocks Agent/Tab/Inline/@; defaults include .env* and node_modules/), and Ignore files (help). Terminal and MCP boundaries differ from built-in file tools—design deny lists with that gap in mind.

How do you handle secrets?

One-line answer: Stack commit deny (.gitignore) + agent access deny (.cursorignore / deny list) and name filenames, extensions, and directories explicitly. A “be careful” line is not a deny list.

Common secret axes (public docs/practice; not product pricing):

AxisExample patternsRole
Env files.env, .env.*, **/.env, **/.env.*Local/CI secrets. Cursor defaults already include .env*
Keys / certs**/*.pem, **/*.key, **/id_rsa, **/*.p12TLS/SSH private key families
Credential JSON**/credentials.json, **/secrets.json, **/service-account*.jsonCloud/OAuth client files
Secret dirssecrets/, .secrets/, private/Team key bundles
Token dumps*.token, *token*.txt (per team rules)Accidentally saved token text

.gitignore alone leaves already-tracked files and does not fully replace agent/index deny. Cursor says it respects .gitignore, and still recommends .cursorignore for secrets, bulk noise, and third-party trees.

Suggested deny fragment (conceptual; repo root):

# secrets — keep out of git AND agent file tools
.env
.env.*
!.env.example
secrets/
**/*.pem
**/*.key
**/credentials.json
**/secrets.json

One Rule / AGENTS.md line:

Deny paths (do not read, @-mention, or paste contents):
  .env*, secrets/, **/*.pem, **/credentials.json
If a task needs a secret: stop and ask a human — never invent or echo values.

Do not:

  • Ignore .env.example with the real env files → keep !.env.example.
  • Paste secrets into a non-ignored path like docs/notes.md → that bypasses deny.
  • Ask the agent to “just read and summarize” a secret file → values can survive in the summary.

What about vendor?

One-line answer: Drop third-party and generated trees—node_modules/, vendor/, lockfiles, build outputs—via default/extra ignore to cut context noise and bad edits. “Patch vendor for release” is a separate ticket from deny policy.

Path axisTypical patternsWhy deny
JS depsnode_modules/In Cursor defaults; index/search noise
PHP etc.vendor/Composer vendor tree; easy to confuse with app code
Other vendorthird_party/ (if unmodified), .venv/, __pycache__/Generated / external
Locks / outputs*.lock (policy-dependent), dist/, build/, .next/Bulk/generated; many appear in defaults

.cursorignore example (comment sections separately from secrets):

# vendor / generated — noise for agent context
node_modules/
vendor/
.venv/
dist/
build/
.next/

Caveats:

  1. If the app forks and patches vendor, blanket vendor/ deny blocks the job. Allow only vendor/acme-fork/ (!) or narrow cwd to that package (monorepo-agent-root).
  2. Negation limits: if a parent dir is ignored with *, nested ! re-includes can fail—Cursor documents the same gitignore behavior. Open directories one level at a time when you need nested exceptions.
  3. Lockfiles are often default-ignored; if the agent must align versions, you may need an explicit !package-lock.json.

Rule of thumb: keep first-party source in the agent’s default scope; treat vendor and secrets as deny defaults.

How do you detect bypass?

One-line answer: Deny is a file-tool boundary, not a full security perimeter. Check terminal, MCP, copies, ! mistakes, and non-git workspaces on a checklist.

Public-doc gaps and responses:

HoleSymptomDetect / respond
Terminal cat/grepFile Read blocked, shell still readsCursor: terminal/MCP do not always honor .cursorignore. Confirm sandbox + git-backed workspace for shell limits
MCP toolsExternal servers read the same pathsKeep MCP allowlists/resources off secret paths
Path copy.env pasted into tmp/debug.mdPR diff / git status for new credential-like files
@ mention / dragUI tries to load ignored filesVerify ignore blocks; Rule: refuse bypass requests
Negation mistakes! re-exposes secretsgit check-ignore -v path (also in Cursor troubleshooting)
Already tracked secretsOld committed .envIgnore is not enough → human history/rotation process

Copy-paste checklist:

[ ] .gitignore has secrets + vendor patterns
[ ] .cursorignore mirrors secrets (and extra vendor noise)
[ ] .env.example allowed with ! if needed; real .env denied
[ ] git check-ignore -v .env secrets/foo.pem
[ ] Agent file read on denied path → permission denied / blocked
[ ] No “cat the secret file” in Auto-run allowlist
[ ] MCP resources do not point at secrets/
[ ] PR checklist: new credential-like filenames

Warning: A deny list shrinks exposure; Cursor docs do not claim complete protection (LLM unpredictability). Keep production keys outside the agent workspace; inject via humans when needed.

One-line wrap-up: Stack secrets/vendor patterns in gitignore and cursorignore → detect terminal/MCP/copy bypasses with a checklist. Do not replace deny lists with chat reminders alone.

FAQ

Is .gitignore enough?

It is required to stop commit leaks. To constrain agents/indexing, add .cursorignore (or the product’s deny-path setting). Cursor respects .gitignore and still recommends explicit ignore for secrets and vendor noise.

What about .env.example?

Deny real .env; re-include placeholders with !.env.example. Never put live tokens in the example file.

What if the task must edit vendor?

Do not lift the whole deny. Allow only the subtree you patch, or narrow cwd to that package. Re-check deny defaults when the task ends.

git check-ignore prints nothing?

Pattern mismatch, already-tracked file, or wrong path. Use -v, then confirm .cursorignore carries the same patterns.

Sources

  • Git — gitignore — pattern syntax, ! negation, non-traversal of excluded dirs
  • Cursor — Ignore file — .cursorignore, Agent/Tab/Inline/@ blocks, defaults, terminal/MCP limits, git check-ignore -v
  • Cursor — Ignore files (help) — auto .gitignore, why secrets/vendor/generated
  • Adjacent: monorepo-agent-root (work root), agent-eval-checklist (pre-merge secrets axis)