Your recorded test might be committing a session cookie
The fastest way to write an API test is to record a real request and replay it. The fastest way to leak a credential is the same move. The request you just captured carries a live session cookie, an Authorization: Bearer header, maybe an SSN or a card number in the JSON body. Save it verbatim as a spec and all of that lands in git, in plain text, in a file other people clone.
It happens because the convenient path and the safe path look identical at the moment you hit save. The request works. The test passes. The secret is three lines down where nobody looks until it shows up in a leaked-credentials scan.
What Hover strips before it writes
When Hover crystallizes a recorded request into a committed .security.spec.ts, it runs the request through a sanitizer first. Three passes:
Credential-bearing headers get dropped outright: cookie, set-cookie, authorization, proxy-authorization, x-api-key, x-auth-token, x-amz-security-token. They don't get masked, they get removed, because CI auth comes from a Playwright storageState fixture, not from a string baked into the file.
Query-string values that name a credential get masked: a ?token=... or ?api_key=... in the URL is a common leak, so the value comes out and a placeholder goes in.
JSON body fields get masked by key name: password, token, secret, api_key, access_token, auth, ssn, credit_card, and the spelling variants. The matcher covers every JSON value type, not just strings. An SSN sent as a number ("ssn": 123456789) used to slip past a string-only matcher straight into the committed file. It doesn't anymore.
One alternation, so coverage can't drift
There's a sharp edge here worth calling out. An early version kept two separate lists, one for URL params and one for body fields. They drifted: auth and apikey were in the URL list and missing from the body list, so a body field named auth leaked while the same name in the query string got caught. Two lists that are "supposed to match" eventually don't.
Now both matchers derive from a single alternation. Add a credential name once and the URL pass and the body pass both pick it up. You can't fix one and forget the other, because there's only one to fix.
You see what it dropped
The sanitizer returns the list of header and field names it stripped or masked, and Hover surfaces it. Saving a spec isn't a silent rewrite. You get told "dropped: cookie, authorization; masked: ssn" so you know the regression test is real and the secret isn't in it. Auth comes back at run time from the fixture, the assertions run the same, and the file is safe to commit.
This is the unglamorous half of the explore-then-crystallize idea. An AI authoring tests is only useful if the artifact it leaves behind is one you'd actually commit. A spec with a live token in it is not that artifact, so the sanitizer runs on the way out, every time.
Try Hover on your own app.
One command adds the widget to your dev server. Author tests with AI, ship plain Playwright.
npx @hover-dev/cli setup