Public means public
A website has two kinds of file. The ones the browser fetches, which are public to anyone who asks, and the ones that stay on the server. The line between them is the single most important line on a client site, and it gets crossed by accident far more often than by attack.
A developer pastes an API key into a script to get a map working and ships it. A plugin writes its configuration into a folder the web server also serves. A backup lands in the web root as a zip. A build tool publishes a source map with the environment baked in. None of these feel like a security decision at the time, and all of them leave a secret in a place a search engine, a scanner or a bored visitor can read.
This article covers what actually leaks, how to find it from the outside and the working habits that keep it out. It is written for studios maintaining client sites they did not necessarily build.
What leaks, in practice
The patterns worth looking for are recognisable by shape, which is what makes them checkable from the outside:
- Cloud provider access keys. Long, fixed-format identifiers that unlock storage, email sending or compute. They end up in scripts that upload files from the browser.
- Private key blocks. A file that starts with a "BEGIN PRIVATE KEY" header is a private key, full stop. These arrive in public folders when a certificate is set up by hand and the working files are never moved.
- Source-hosting and chat-platform tokens. Personal access tokens for a code host or a messaging tool, pasted into a deployment script or a notification helper that was later bundled into the site.
- API secret keys with a recognisable prefix. Many services issue secrets with a fixed prefix such as "sk-". A secret key, unlike a publishable key, should never be in a browser.
- Plugin and platform leftovers. Readme and changelog files that print exact versions, configuration backups, exported databases, installer scripts that were never deleted and debug logs with paths and credentials in them.
The first four are a credential in the open. The last is a map for someone who wants to find one.
How to find it from the outside
You do not need the site's login to check for most of this, and checking from the outside is the honest test, because it is the view an attacker has. Fetch the public pages and the scripts they load, and look for the key patterns above. Request the usual leftover paths and see whether the server answers with a file or a 404. Read the source maps if they are published.
Our hosted website audit does the first part as a matter of routine. It fetches the public pages of a site on our servers, scans the page and its public files for key patterns with a fixed shape and reports a finding with the page it is on and the evidence masked, so the report itself never repeats the secret. Because this is the one finding that could help an attacker as much as the owner, the security section is not in the free check. It appears in the Website Audit Report only after the studio has proved it controls the domain, with a meta tag or a file. When nothing is found, the report says so in one fixed sentence: no passwords or keys found in the public files we checked. It does not say the site is secure, because a public check cannot know that.
The habits that keep keys out
Secrets live in the environment, never in the code
Every platform the studio maintains has a place for configuration that is not served to the browser: an environment file outside the web root, a hosting panel's secrets store, a managed platform's settings page. Use it. A key in a script is a key in the open the moment the script is deployed. The OWASP secrets management guidance is the standard reference for the longer version of this rule.
Browser code gets publishable keys only
Services that offer a browser-side key label it publishable, restricted or client. If a key is called secret, it belongs on the server, behind a small endpoint the browser calls instead. If the service offers only a secret key, that is the answer: the browser cannot have it.
The web root holds the site and nothing else
No backups, no exports, no installer scripts, no working files from a certificate setup. If a file does not need to be fetched by a browser, it does not belong in a folder the web server serves. This is a five-minute check on every handover and every migration.
Plugins are patched, pruned and quiet
A plugin that is installed and inactive still ships its files. Remove what is not used. Patch what is, on a schedule, because known weaknesses in web software are among the most exploited routes in. Patching applications is one of the mitigation strategies in the Australian Signals Directorate's Essential Eight. And turn off the readme, version and debug output that plugins print by default, so the public site does not announce what it runs.
Build tools do not publish their environment
A production build should strip source maps or publish them without environment values, and the build configuration should be checked once for any variable that is prefixed as public when it should not be.
When a key is found
Rotate first, investigate second. Revoke the exposed key at the service that issued it, issue a new one into the environment, redeploy and only then work out how long it was exposed and whether it was used. A key that was public for an hour may have been scraped in that hour. The order matters because the investigation takes longer than the rotation, and the key is live for the whole of it.
Then put the finding in the maintenance plan report, closed, with the habit that prevents it. Clients do not expect perfection from their studio. They expect to hear about it from their studio first.
See what a website audit report finds on a real site. Get a free website audit: enter a URL and an email, and we check the public pages on our servers. We never log in and never touch your files.
