Everything your front-end code receives or contains is visible to the person using it. They can open the developer tools, read your source, see network requests and inspect storage. Keep this in mind for every piece of data.
What never belongs in front-end code
- API keys or secrets with real privileges (payment keys, database or admin tokens, private keys).
- Passwords, in code or storage.
- Private business logic you rely on for security (price checks, discount rules, permission checks).
- Other people’s personal data that the current user should not see.
If it is in the JavaScript file, it is public, even if you minify or obfuscate it.
Where secrets belong
On a server. The browser calls your server, and your server calls the third-party service using the secret. The server decides what the user is allowed to do.
Browser ──(no secret)──▶ Your server ──(secret key)──▶ Third-party API
Some keys are designed to be public (for example, a map provider’s key restricted to your domain). Read the provider’s documentation and restrict such keys by domain and quota.
localStorage and sessionStorage
They are readable by any script on your page, including a malicious one that gets in through an XSS bug or a compromised library (XSS basics). So do not store:
- session tokens, access tokens or refresh tokens,
- passwords or password hints,
- payment details,
- sensitive personal information.
// Do not do this
localStorage.setItem("authToken", token);
A safer approach for sessions is a server-set cookie with HttpOnly (not readable by JavaScript), Secure (only over HTTPS) and SameSite (limits cross-site sending). Follow the guidance of your platform or framework.
What it is fine to store
- Interface preferences: theme, language, layout.
- Non-sensitive drafts and UI state.
- Public cached data.
See Storage Limits and Warnings.
Treat stored data as untrusted
A user can edit localStorage in the developer tools. Never use it to decide what a user is allowed to do (“isAdmin”: true). Permissions must be checked on the server.
// Wrong: the user can set this themselves
if (localStorage.getItem("isAdmin") === "true") showAdminPanel(); // only a convenience, never real security
Showing or hiding a button is fine for a better interface, as long as the server enforces the rule.
Logging
Do not log passwords, tokens or personal data with console.log, or send them to analytics and error trackers. Logs are often shared and stored.
URLs
Do not put secrets in URLs (query strings). They end up in browser history, server logs and the Referer header.
Source maps and comments
Check that comments or source maps in production files do not expose internal details, passwords or private URLs.
Hardening checklist
- No secrets in the repository or the bundle (use environment variables on the server).
- Sessions in secure cookies, not
localStorage. - HTTPS everywhere.
- Safe output (textContent vs innerHTML).
- A Content Security Policy.
- Server-side validation and permission checks.