Skip to content

Security

What evidence should back a client secrets finding

A Client-side secrets finding needs the asset path, pattern class, and redacted proof from a public response, not a rumor that "someone saw a key.

· by Henry Smith

What evidence should back a client secrets finding

I still reach for curl first when someone says a key leaked. Habit. The useful part is not the adrenaline. It is whether you can point at a public URL that returns the value, name the pattern class, and keep the raw secret out of the ticket thread.

SlaySlop's Client-side secrets check "searches public bundles and responses for exposed keys and tokens." Security product language adds the same observation in slightly longer form: client bundles and responses are checked for exposed keys, tokens, and credentials. Every finding is supposed to come with the evidence that triggered it. Secrets stay redacted so the report channel does not become a second leak.

That is the bar. Below it, the finding is gossip.

Outcome

Evidence for a Client-side secrets finding should let a reviewer reproduce the observation on a permissioned host without needing the original scanner session, while still gating the full credential value. Concretely: which page or asset, what kind of secret-shaped material, that it was reachable without auth, and when you looked.

Boundaries I keep in the ticket subject

Read-only public surface. Not a pentest. compare says so in plain language. Permission required. The check does not claim anything about private git history, CI secret stores, or authenticated admin JSON. Sibling instruments stay sibling: Exposed files and admin panels for reachable env files; Default credentials for vendor logins when ownership is verified.

A clean row on crawled assets is not a lifetime promise. Free teaser scans and full reports are still points in time. I rescan after the fix.

Loading diagram.

Happy path evidence packet

When the finding fires, I want this attached before anyone pastes panic into a client channel:

text
# Evidence packet (values redacted on purpose)
check: Client-side secrets
glossary: https://slayslop.com/glossary/client-secrets
page_url: https://www.example.com/pricing
asset_url: https://www.example.com/assets/checkout-widget.js
observed_at: 2026-09-06T15:30:00Z
pattern_class: cloud_access_key | stripe_secret | bot_token | other
auth_required: false
cache_control: public, max-age=31536000, immutable
secret_value: [REDACTED: rotate at provider; do not paste]
remediation: rotate → remove from client build → purge/rehash → rescan

Product ranking puts urgent leaks above lower-risk hardening. The packet should make that urgency obvious without dumping the credential into Notion.

I still verify fetchability myself:

bash
# Authorized confirmation only
curl -sI "https://www.example.com/assets/checkout-widget.js" | sed -n '1,20p'
http
HTTP/2 200
content-type: application/javascript
cache-control: public, max-age=31536000, immutable

Headers prove the object is public and sticky. The secrets question lives in the body. I do not paste body excerpts that contain live secrets into chat. Redaction in the scanner exists for a reason; copy that discipline into human channels.

What counts as enough proof

Asset path. A finding that says "somewhere in JS" wastes an afternoon. Point at the chunk or response URL the crawl actually fetched.

Pattern class, not theater. Distinguish secret-class material from intentionally public publishable keys. Maps keys and publishable payment identifiers can belong in the browser when scoped. Service-role tokens and live billing secrets do not. Evidence should support that classification without requiring the full string in the ticket.

Public reachability. If the value only appears behind a login you were not scanning, you are outside this check's claim. Client-side secrets is about public bundles and responses.

Time and cache context. Immutable long-cache objects keep old secrets alive after git looks clean. Note cache-control when it explains why a "fixed" build still serves the leak.

Rotation record. Evidence of exposure without evidence of rotation is half a ticket. Provider revoke first, then build cleanup.

Pitfalls that weaken the finding

Treating a repo grep as equivalent evidence. Source can be clean while a plugin inlines a value into the shipped file. The check observes the response.

Screenshotting DevTools with the full secret visible, then uploading that PNG to the portal. You just published the credential again. Prefer the redacted finding export.

Scanning a brochure host while the leak lives on app.. Evidence from the wrong URL does not back the finding you will debate on Friday.

Assuming "we use environment variables" answers the evidence question. Env vars inlined into a client bundle are just public values with extra steps. The artifact is the downloaded file.

Skipping the rescan. Fix prompts and integrations describe a boring loop: open the finding, apply a fix, scan again. I trust the second pass more than the commit message.

Related next step

If the packet is complete and the value is secret-class, rotate now. Then remove it from client-reachable output, bust the cached object, and rescan the same production URL. Keep Client-side secrets and Security and secrets open so the ticket wording matches what the product actually observed.

When I want ranked, redacted evidence without inventing a process, I run a permissioned SlaySlop pass and attach the finding as-is. Curl stays for confirmation. The report stays for the trail.