AI Agent Secret Hygiene: Never Put Keys in Rules

The first rule of AI agent secret hygiene is simple: rules hold policy text only—never literal keys, tokens, or passwords. Project .mdc files under .cursor/rules, root AGENTS.md, and shared “team rules” are versioned, shared, and injected into context. A literal secret there leaks through the repo, transcripts, and PR diffs.

This post covers only what must never go in rules, where local-only values live (.env, keychain, allowlist), and a leak checklist. No real secret values, pricing, plans, personal reviews, or invented product click-paths. Grounded in Cursor Rules, Ignore file, Cloud Agent Secrets & Network, and Cloud Agent setup.

What must never go in rules?

One-line answer: Any reusable credential literal—API keys, tokens, passwords, DB URLs with embedded secrets, private key material, session cookies—and fragments that reconstruct them. Rules state prohibitions, not values.

Project Rules are committed .mdc files. Whether alwaysApply or globs, once content is in context it can follow into chat, tool output, and commit messages. A key inside a rule is not documentation; it is an exfiltration vector.

Do not put (names only—never sample values)

KindWhy it hurtsPut this in rules instead
API keys / Bearer tokensSurvive in index, PRs, logsNEVER literals; reference process.env / Secret names
DB/broker URLs with passwordsOne connection string is enoughRole of the host only; password in env
.pem / private key bodiesOften unrecoverablePath and permission policy (chmod 600)
Internal webhook / bot tokensRe-emitted in chat“Name only; value in Cloud/local Secrets”
Customer PII / real data samplesPolicy and contract riskSynthetic fixtures and masking rules

OK to put

  1. Prohibitions — NEVER write secrets as literals; never commit .env*.
  2. Env var names — e.g. STRIPE_API_KEY (name only).
  3. Where values live — .env.local / OS keychain / Cursor Secrets tab.
  4. Path policy — do not commit or @-mention secrets/, *.pem.
  5. Habits — scan git diff before commit; prefer a secret-scan hook.
---
description: Secret hygiene (no literal credentials)
alwaysApply: true
---

# Secrets

- NEVER paste API keys, tokens, passwords, or private keys into rules, AGENTS.md, code, commits, or chat.
- Read credentials from environment variables or the OS/cloud secret store. Refer by **name** only.
- Do not commit `.env`, `.env.*`, `*.pem`, `credentials.json`, or `secrets/`.
- If a secret appears in a diff or tool output, stop, redact, rotate, and continue without the value.

That block is policy. Do not add fake key-string “examples”—they train the model to emit lookalikes.

User Rules and Team Rules follow the same rule. Team Rules land in every teammate’s context, so a personal token there spreads to every team session.

Where do local-only values live?

One-line answer: Keep values in local .env (gitignored), OS keychain/secret manager, Cloud Agent Secrets, and (for cloud) network allowlists. The repo keeps names and load instructions only. .cursorignore is convenience, not a security boundary.

Local Agent

PlaceRoleCaveat
.env / .env.localValues apps/scripts readMust be gitignored. Default ignore includes .env*—accidental commits are separate
OS keychain / secret managerRuntime lookup by CLI/SDKDo not paste export output into chat
Shell environmentSession-scoped injectionMay appear in history, screenshots, agent terminal logs
.cursorignoreSoftens indexing / Agent file accessDocs: terminal and MCP can still read ignored files

Cursor respects .gitignore and a default list (including .env*) for indexing. Add more sensitive paths in .cursorignore if needed. Per the Ignore file docs, Agent terminal and MCP tools are not guaranteed the same block. Real control is permissions, a secret manager, and never storing values in the repo.

Tell the agent:

  • “Do not read key values—confirm variable names and load paths only.”
  • “.env.example gets placeholders only—never real values.”
  • “If you are about to write a literal into config, stop and switch to env references.”

Cloud Agent

Do not rely on a laptop .env in the cloud. Put values in the dashboard Secrets tab (setup). Types (Secrets & Network):

TypeUse forVisible to the agent?
Environment VariableNon-sensitive flags / public URLsValue visible (still encrypted at rest)
Runtime SecretSensitive API credentialsRedacted as [REDACTED] in tools, transcript, commits
Build SecretImage build step onlyNot in the running agent env

Prefer Runtime Secret for sensitive keys. A human on the agent’s terminal may still see them—ban “print the secret” in rules. After add/change, start a new agent so injection applies.

Prefer short-lived OIDC over long-lived cloud keys when you can. For egress risk, use Cloud Agent network mode + allowlist and only the hosts you need—docs warn against broad *.s3… wildcards that open exfiltration paths.

What stays in the repo / what does not

Keep: .env.example (names only), Secret name list, a short “local = keychain, CI = OIDC” note, NEVER lines in rules.

Do not keep: real values, private keys, production connection strings, screenshots of export KEY=….

What is the leak checklist?

One-line answer: Walk commit/PR → rules/chat → local ignore → cloud secrets → rotate. If a value appeared, revoke and reissue first.

Before commit / PR

  1. git status / git diff has no .env, *.pem, credentials.json, secrets/.
  2. Diff has no live credential-shaped material (do not invent sample strings here).
  3. Commit message, PR body, and screenshots have no tokens.
  4. Pre-commit / secret-scan hook passes if you use one.

Rules and prompts

  1. No literal secrets in .cursor/rules/**, AGENTS.md, User/Team Rules.
  2. No “example key” strings left as teaching aids.
  3. Only names and NEVER policy remain.

Local and ignore

  1. .env* is in .gitignore. If already tracked: git rm --cached, then rotate.
  2. Add sensitive paths to .cursorignore if needed—operate assuming terminal/MCP bypass.
  3. Do not ask the agent to cat .env or “print the key.”

Cloud Agent

  1. Sensitive values are Runtime Secret (or equivalent). If a snapshot baked .env.local, move to the Secrets tab.
  2. After secret changes, start a new run.
  3. If on Allowlist mode, destinations are minimal—no broad *.s3… entries.
  4. Chat/PR shows [REDACTED], not raw values.

If something leaked

  1. Rotate — revoke/reissue beats deleting logs.
  2. List every place it was pasted (gist, issue, Slack).
  3. Add one prevention NEVER line to rules (still no value).

A weekly pass over items 1–7 stops most rules-channel leaks; add 11–14 when you use Cloud Agents.

What should you remember?

Rules = policy; secret stores = values. Keep NEVER lines and env names in .mdc/AGENTS.md; keep values in .env, keychain, Cloud Secrets (Runtime Secret when sensitive), and tight allowlists. .cursorignore helps indexing—it is not a security boundary. Rotate first when a value appears. Skills-vs-Rules and permission modes live elsewhere; this post is only do not put keys in rules.

Sources