beforeReadFile hook debug log persists full file content to disk, even when the hook denies the read

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

When a user-defined beforeReadFile hook (hooks.json) denies a file
read, Cursor still writes the full file content to its own local
debug log (%APPDATA%\Roaming\Cursor\logs\...\cursor.hooks.workspaceId-*.log,
Windows path) via the “content” field of the hook’s input payload —
before the hook’s decision is even applied.

This means that even a correctly-configured security hook that blocks
reading a sensitive file (e.g. a real .env with production secrets)
does not prevent the secret from being persisted in plaintext on disk,
in a log file outside the project directory, outside version control,
and with no documented retention/rotation policy.

Steps to Reproduce

  1. Configure a beforeReadFile hook in ~/.cursor/hooks.json that
    returns {"permission": "deny"} for any file matching .env
    patterns.
  2. In an Agent chat, ask the agent to read a real .env file (e.g.
    containing KEY=some-real-secret-value).
  3. Confirm the read is correctly denied in the chat/UI.
  4. Open Cursor Settings > Hooks (or the “Hooks” Output channel) and
    inspect the log for that beforeReadFile invocation.
  5. Observe: the “content” field of the logged INPUT payload contains
    the full, real file content — including the secret — in plaintext,
    regardless of the hook’s “deny” decision.

Expected Behavior

One of:

  • The “content” field should not be included in the persisted debug
    log at all (only in the live payload passed to the hook process via
    stdin), or
  • It should be redacted/truncated in the log by default, with an
    explicit opt-in setting to show full content for debugging, or
  • There should be a documented setting to control retention (e.g.
    auto-purge after N days) and/or verbosity of this specific log
    channel, so users who intentionally deny a read are not left with
    the same secret persisted elsewhere on disk.

Operating System

Windows 10/11

Version Information

  • Cursor version: 3.14.7 (internal), DisplayVersion 3.21.16
  • Hook type affected: beforeReadFile (native hooks.json)

Does this stop you from using Cursor

No - Cursor works, but with this issue

Hey @Igor_Fonseca, I was able to repro this. The deny still does its main job (the content never reaches the model); the gap is that the Hooks debug log writes the hook’s full input, including the file content, to disk regardless of the deny. We’ve let the team know and it’s an issue we’re tracking.

Two things that help right now:

  • For files the agent should never touch (like a real .env), add them to .cursorignore - that blocks the read before the hook ever sees the content, so nothing lands in the log. It’s a convenience control rather than an OS-level boundary, so keep genuinely sensitive secrets protected at the OS level too.
  • Since a real secret was already written, rotate it, then clear older logs via the Command Palette (Ctrl+Shift+P) → “Open Logs Folder”.

I’ll post back here when there’s an update.