How to stop Cursor from reading your .env

What Cursor's .cursorignore file covers and what it does not, what zn-gate's hooks add for .env files, and a short test you can run on your own machine with fake values.

View .md

Two layers help keep a .env file away from Cursor's agent. Cursor's own ignore file, .cursorignore, controls which files the agent, Tab and Inline Edit can see. zn-gate adds hooks that block file reads and most shell commands that read .env files with values. This page explains what each one does according to its documentation, and gives you a test to run yourself.

What .cursorignore does

According to Cursor's documentation on ignore files:

  • You create a .cursorignore file in your root directory, using .gitignore syntax.
  • Cursor blocks files listed in it from "Code accessible by Agent, Tab, and Inline Edit" and from "Code accessible via @ mention references."
  • Cursor "automatically ignores files in .gitignore and the default ignore list". That default list includes .env*.
  • You can turn on hierarchical ignore files in Cursor Settings > Indexing > Ignore Files > Hierarchical Cursor Ignore, and you can set global ignore patterns in your user settings (the global list is empty by default).

A minimal .cursorignore:

.env
.env.*

What .cursorignore does not cover

The same Cursor page states two limits:

  • "The terminal and MCP server tools used by Agent cannot block access to code governed by .cursorignore."
  • "While Cursor blocks ignored files, complete protection isn't guaranteed due to LLM unpredictability."

So an ignore file is a useful first layer, but by Cursor's own documentation it does not cover every path to a file.

What zn-gate adds in Cursor

zn hooks install cursor writes Cursor's hooks.json. Cursor's hooks documentation describes the events zn-gate uses: beforeReadFile ("Called before Agent reads a file. Use for access control to block sensitive files from being sent to the model") and beforeShellExecution (called before a shell command runs, with a permission decision). With the hooks installed:

  • File reads and most shell commands that read .env files with values, and common credential files, are blocked.
  • A secret pasted into a prompt is blocked.
  • MCP calls that carry a secret value are blocked.
  • Secrets zn-gate recognizes are removed from MCP tool output.

Install it:

npm install -g zn-gate
zn hooks install cursor

Restart Cursor, then run zn-gate check in a terminal. It should show OK for Cursor (what the output means).

What zn-gate does not cover in Cursor

  • Shell output and file contents are not scrubbed. Cursor's documentation lists no hook that changes them: postToolUse can replace the output of MCP tools only (updated_mcp_tool_output, "For MCP tools only").
  • A secret printed by a shell command, or written in a file the agent reads that is not blocked, reaches the model.
  • Write protection is best effort, because Cursor does not document the input of every tool.
  • The Cursor CLI (cursor-agent) is not covered.
  • If the zn hook crashes, reads and prompts are blocked, and other events run unchecked.
  • Not tested on Windows.

If you want values out of the file altogether, keep them in zn-gate's vault: zn unlock, then zn env shadow .env. Your .env then holds markers instead of real values (Scrubber).

Test it on your own machine

This test uses fake values. We have not run it end to end in Cursor (see the status note on the Cursor page), so what follows is what to expect according to the documentation, and how to check each step yourself.

  1. In a new empty folder, create a .env file with fake values only:

    EXAMPLE_KEY=not-a-real-key
    EXAMPLE_URL=https://example.com
  2. Open the folder in Cursor and ask the agent: "Read the .env file and tell me what is in it." Note what happens. By Cursor's default ignore list, .env* files should already be ignored.

  3. Create a .cursorignore file containing .env. Run git check-ignore -v .env if the folder is a git repository (Cursor's documentation suggests git check-ignore -v [file] to test patterns). Ask again and compare.

  4. Ask the agent to run a terminal command that prints the file. Cursor's documentation says terminal tools are not governed by .cursorignore, so check what you see.

  5. Install the hooks (zn hooks install cursor), restart Cursor and repeat steps 2 and 4. According to the zn-gate documentation, reads and most shell commands that read the .env should now be blocked, and the agent should get a message from the hook instead of the values.

  6. Remove the sample folder when you are done. To remove the hooks: zn hooks uninstall cursor.

Only your own results count here. If a step behaves differently from what this page says, tell us and include your Cursor version.

Frequently asked questions

Does .cursorignore stop Cursor from reading .env? It blocks the listed files from the agent, Tab, Inline Edit and @ mentions. Cursor's documentation says terminal and MCP tools used by the agent are not governed by it, and that protection is not guaranteed.

Is .env ignored by default in Cursor? Cursor's documentation lists .env* in its default ignore list, together with the files in your .gitignore.

Does zn-gate replace .cursorignore? No. They work at different points. Use both.

Can zn-gate hide secrets from Cursor's shell output? No. Cursor does not let hooks change shell or file output; only MCP tool output is scrubbed.

How do I undo it? zn hooks uninstall cursor.

Sources