Sensitive data element remediation (rule + command)
A Cursor project rule + custom slash command pair for remediating a sensitive-data-element (SDE) finding — hard-coded secrets, PII in logs, credentials in source. The rule locks in the house posture (“rotation first for exposed SDEs, no history rewrites, one finding per PR”); the command is the one-liner an engineer or Cursor Automation invokes.
What this prompt does
When /remediate-sde <finding-id> <class> runs, the Cursor Agent
(interactive or Background) confirms the literal is in the
current working tree, classifies the exposure scope, and — if
pre-exposure — replaces the literal with a reference to the
approved secret store (or a redaction helper for PII), adds a
regression guard, runs tests, and opens a draft PR. For exposed
findings, the rule forces the agent to stop, write a triage note
with a rotation + disclosure checklist, and not touch code.
Inputs: finding id and SDE class (one of secret, token,
pii, pci, phi) as command arguments. Optional file-path
hint in the chat body.
Outputs: a draft PR (pre-exposure path) or a triage branch +
summary in chat (exposed path).
When to use it
- GitHub push protection / GitLeaks / TruffleHog / Wiz fires on a pre-exposure finding and the developer wants to fix it without leaving Cursor.
- Cursor Automations watches an issue label (
security:sde) and needs a consistent command to dispatch. - A PII scanner flags a test fixture containing real user data and the replacement is a Faker-style synthetic value.
Don’t use it for:
- Any SDE already pushed to a shared remote or published log — the rule forces triage + rotation. This is the correct behavior, not a bug.
- Cross-repo sweeps — run once per finding after dedup.
- Binary artifacts — the rule refuses.
The prompt
Two files, checked in to the repo.
.cursor/rules/remediate-sde.mdc
---
description: >
Sensitive-data-element remediation house rules. Applies whenever
the agent is asked to remove a hard-coded secret, PII, or
credential from source.
alwaysApply: true
---
# SDE remediation — house rules
## Exposure scope — always classify first
- PRE-EXPOSURE: literal exists only in the current working tree,
never committed to a shared remote, never printed in CI logs.
- EXPOSED: anything else. If in doubt, it's exposed.
**Exposed SDEs are rotation problems, not code-edit problems.**
For any EXPOSED finding: do NOT edit the offending file. Stop,
create a triage branch, and write TRIAGE.md per the template
below. Rotation happens first; code hygiene second.
## Pre-exposure remediation
- Replace the literal with a reference to the project's approved
secret store (read `docs/security/secrets.md` to identify the
client). For PII, route through the project's redaction
helper (grep for `redact(`, `mask_pii`, `scrubPII`). If the
project has neither, stop and triage — do not invent one.
- For test fixtures containing real user data, replace with
Faker-style synthetic values and comment the finding id.
- Minimal edit only. Never rename files, never reformat unrelated
code.
## Regression guard
- Add a unit test or a scanner-config rule that fails if the
literal reappears. Allowlist the synthetic-fixture path
specifically (never a broad path allowlist).
## What you may NEVER do
- Rewrite git history (`filter-repo`, force-push, commit
amends on anyone else's branch).
- Echo the SDE literal in commit messages, chat output, PR
bodies, or logs. When referring to it, hash it.
- Commit or delete `.env` / `credentials.json` — those require
a `git filter-repo` runbook + human sign-off.
- Merge your own PR.
## PR shape (pre-exposure path)
- Branch: `fix/<finding-id>`.
- Commit: `fix(sec): remove <class> <finding-id>`.
- Title: `fix(sec): remove <class> from <file> (<finding-id>)`.
- Body: finding id, exposure scope = "pre-exposure",
replacement pattern used, test pass evidence, one-line revert.
- Labels: `security`, `sde-remediation`.
- DRAFT. Never ready-for-review, never auto-merge.
## Triage template (exposed path)
Write TRIAGE.md on a `sde-triage/<finding-id>` branch with YAML
frontmatter including: finding_id, sde_class, exposure_scope,
first_seen_commit, first_seen_date; and body sections for:
- Rotation checklist (revoke, rotate, re-deploy, invalidate
cached sessions).
- Disclosure checklist (IR ticket, service owner, legal routing)..cursor/commands/remediate-sde.md
Filename is the command name — no frontmatter required.
# Remediate a single SDE finding
Arguments (both optional):
1. Finding id (e.g. `GITLEAKS-AWS-001`, `WIZ-SECRET-42931`).
2. SDE class: `secret`, `token`, `pii`, `pci`, or `phi`.
Infer everything else from the session: the repo root you're
already in, the default branch (from the git remote), the
approved secret store (from `docs/security/secrets.md` or
`SECURITY.md`), the redaction helper (grep for it), and the
test and lint commands (from the README, `package.json`
scripts, or `Makefile`).
If no finding id is provided AND no scanner MCP is wired in,
discover a target yourself before touching code:
- Run the lightest-weight secret/PII scanner available, in this
order: `gitleaks detect --source . --no-banner`,
`trufflehog filesystem . --json`, `detect-secrets scan
--all-files`, `trivy fs --scanners secret .`.
- Restrict to the WORKING TREE only — never scan commit
history. Exposed SDEs are rotation problems, handled by the
exposed-path branch of the rule.
- Pick the highest-confidence finding. Synthesize a local id:
`LOCAL-<scanner>-<rule>-<short-sha>`. Classify the SDE class
from the rule id (e.g. AWS-access-key → `secret`,
email-in-logs → `pii`).
- Note in the PR body that the finding was self-discovered and
which scanner produced it.
- If no scanner is installed, stop and post a summary in chat
naming what to install — do not guess.
Never grep for a secret literal yourself — leave pattern
matching to the scanner so the literal never enters chat
context.
Using the house rules in `.cursor/rules/remediate-sde.mdc`:
1. Confirm the literal appears in the current working tree. If
the chat message includes a file path + line, start there.
If the literal isn't present, stop and summarize
"not-reproduced".
2. Classify exposure scope.
- Run `git log --all -S '<literal hash>' -- <file>` to detect
prior commits. NEVER echo the literal — refer to it by a
hash only.
- Check the finding source: was it seen in CI logs or a
public repo?
- Any of the above → EXPOSED. Otherwise PRE-EXPOSURE.
3. EXPOSED path: do not edit the file. Create
`sde-triage/<finding-id>` branch, write TRIAGE.md per the
rule's template, push, and summarize the rotation +
disclosure checklist in chat.
4. PRE-EXPOSURE path:
a. Pick the replacement pattern per the rule (secret store
client for secrets/tokens; redaction helper for PII).
b. Apply the minimal edit. Add a regression guard (unit
test or scanner-config rule).
c. Run lint and tests. If either fails because of the edit,
revert and summarize.
d. Open a DRAFT PR per the rule's PR shape. Do not mark
ready-for-review.
Whenever you need to refer to the SDE literal, use a hash or an
abstract description. Never echo the value.Invoke from chat with /remediate-sde WIZ-SECRET-42931 secret.
From Cursor Automations, the same command is wired to the
security:sde label trigger.
Known limitations
- Exposure detection is git-history-shaped. The
git log -Sheuristic can miss a secret that was renamed between commits; pair with the scanner’s own “first seen” metadata when possible. - Hashing literals in chat. Cursor’s chat surface doesn’t natively redact — the agent must remember to hash. Treat any copy-paste of chat transcripts as sensitive until you’ve verified the agent obeyed the rule.
- History cleanup is out of scope. That lives in a separate
secret-rotationrunbook; this prompt refuses to try. - Redaction-helper detection relies on a grep list. Teams
with non-obvious helper names should record them in
docs/security/secrets.mdso the rule can cite them.
Changelog
- 2026-04-21 — v1, first published. Covers secret / token / pii / pci / phi. Exposed-SDE path deliberately refuses code edits and routes to rotation.