Skip to content

Engineering

Fixing Client Secrets without guessing

Fix client-side secret exposures by rotating first, removing the value from public bundles and responses, then rescanning—without guessing which key still matters.

· by Henry Smith

Fixing Client Secrets without guessing

I still reach for curl first when a secrets finding shows up. Not because curl is the scanner. Because I want to see the public asset with my own eyes before I invent a theory about which env file is guilty. Guessing is how you rotate the wrong key and leave the live one in the chunk.

SlaySlop's Client-side secrets check "searches public bundles and responses for exposed keys and tokens." The fix path has to honor that observation point: the value was public. Treat it as burned, then make the public surface stop serving it.

Outcome I want

After the fix, the credential no longer works at the provider, the public bundle or response no longer contains it, and a follow-up scan on the same URL stops reporting the exposure. I also want the ticket to cite an asset path and a check name, not a vibe that "we cleaned env."

Boundaries I keep on a sticky note

Read-only scanners do not rotate keys for you. SlaySlop does not edit the site. You need permission. This is not a pentest. Sensitive findings are redacted in the product so the report channel does not become a second leak. I work from the redacted evidence plus my own authorized fetch.

Sibling issues stay in their lanes. Exposed files and admin panels covers reachable env files and admin consoles. Default credentials covers vendor default logins when ownership is verified. I fix Client-side secrets on the bundle/response path without pretending those other checks are done.

Loading diagram.

Happy path without guessing

1. Read the finding, not the Slack rumor. Open severity, evidence, and affected page. Security product copy says every finding comes with the evidence that triggered it, and secrets stay redacted. That is enough to know which asset class failed.

2. Classify the match. Secret-class keys (billing secrets, cloud secret keys, bot tokens, private API keys) get rotation. Intentionally public publishable keys get restriction review, not a theatrical revoke that breaks checkout for no reason.

3. Rotate first when it is secret-class. Anyone who fetched the bundle may already have the value. Deleting a line without revoke leaves the downloaded copy useful. I do this in the provider console before I celebrate a git commit.

4. Remove the value from client-reachable output. Move secret use to server-only code. Drop public env prefixes from secret variables. Stop serializing secret fields into window config. Rebuild.

5. Bust caches. Hashed filenames help. Immutable CDN objects with the old hash need purge or natural expiry strategy. I check the URL the finding named.

6. Rescan. Fix prompts and integrations describes the loop cleanly: open a finding, copy a fix prompt into Cursor or another agent if you work that way, then scan again to confirm the issue is actually gone. I like that last step because it replaces optimism with the same observer.

bash
# Permissioned verification sketch after deploy
ASSET="https://www.example.com/assets/index-NEWHASH.js"
curl -sL "$ASSET" | rg -n "sk_live_|AKIA[0-9A-Z]{16}|xoxb-" && echo "still present" || echo "no high-signal prefix in this asset"
text
# Ticket notes I actually keep
check: Client-side secrets
asset: /assets/index-oldhash.js
action: revoked provider key KEY_ID_redacted; removed from server-only path; redeployed
verify: rescan URL https://www.example.com/checkout — finding cleared

If I use a paste-ready fix prompt from the product, I still read it. Prompts start from the actual finding, not generic advice. That helps when the agent would otherwise "fix" a different file than the one serving traffic.

Pitfalls that look like fixes

Renaming the variable. SECRET to SECRET_V2 in a client bundle is still a public value.

Encoding or splitting the string. Obfuscation in shipped JS is not secrecy. The check searches for exposed keys and tokens; creativity in formatting is not a control.

Rotating and forgetting a second environment. Preview deploys and mobile webviews can pin old chunk URLs.

Closing the ticket on grepping the repo alone. The observer that created the finding looked at public bundles and responses. Match that observer on verify.

Pasting the raw secret into the portal to "prove" the bug. Use redacted evidence. The product gates sensitive values for a reason.

Related next step

When the rescan is clean, glance at Exposed files and admin panels so an .env backup is not sitting next to your shiny new chunk. Then leave monitoring on if regressions matter to the client.

References I keep in the ticket footer: Client-side secrets, Security and secrets, Fix prompts and integrations. Soft close: a permissioned pass on SlaySlop is how I confirm the public surface matches what I think I shipped—after rotate, not instead of it.