Back-end security practices
Every demo shows the breach first, then the governed fix.
Hide API keys
An API key is a password that lets your app talk to another service (maps, payments, AI). Keeping it hidden means storing it in a secret place on the server — never in the code a visitor can see, and never in files that get shared or published.
If a key leaks, anyone can use your accounts and run up charges in your name. Leaked keys are one of the most common causes of surprise bills and account takeovers.
Browser · what visitors receive
Server · environment
Purge Git secrets
Git saves every version of your project's history — so even if you delete a password from a file today, it still exists in yesterday's version. Purging means permanently removing old secrets from that entire history, then making sure it can't happen again.
Deleting a secret in a new commit doesn't delete it from history. Anyone who downloads the project later can walk back in time and pull the old password right out.
Attacker checks out commit 4 · config.js
Use public DB key
Modern databases (like Supabase or Firebase) give two kinds of keys: a 'public' key that's safe for use in browsers, and a secret 'service' key that has full power. Using the public key means the browser only ever holds the harmless one.
If the powerful key ends up in the browser, anyone can read or erase your entire database. The public key is designed to be visible — it's only safe when paired with proper access rules.
Browser bundle
Server
Database
Enable row-level security
Row-level security (RLS) is a rule the database itself enforces: each user can only see and change their own rows. It's like an apartment building where the front door is shared, but each unit has its own lock.
Without it, one user can ask the database for someone else's records just by changing an ID number in the web address — and the database, with no rule saying otherwise, hands it over.
Encrypt sensitive data
Encryption scrambles data so it looks like meaningless noise to anyone who doesn't have the key. Do it for data sitting in storage ('at rest') and data traveling across the internet ('in transit').
If a laptop, backup, or database dump is stolen, encrypted data is unreadable garbage. Unencrypted data is an open book — this is exactly how large data breaches make the news.
Laptop
HTTPS wire
Encrypted backup drive
Thief opens the copy
Enforce server-side auth
Authentication and permissions must be checked by the server on every single request. Anything the browser checks can be skipped by the user, because the user controls the browser.
Hiding an admin button in the app does nothing if the server still answers when someone types the admin address directly. It's like hiding the key under the mat — the door itself is still unlocked.
Customer's browser
/admin/discounts — link not shown anywhere
Server
Lock record access
Locking record access means the server checks 'does this record belong to the person asking?' every time someone opens, edits, or deletes one. It's the per-record cousin of row-level security.
A very common hack: change the number in a link like /invoice/1043 to /invoice/1044 and view a stranger's invoice. If the server doesn't check ownership, the numbering itself becomes the only 'security'.
Block field tampering
Users can change anything sent from the browser — including hidden fields and prices. Block tampering by having the server decide everything important: prices, roles, quantities, discounts.
An app that trusts the browser's prices can be told 'this item costs $1' by anyone editing the page in the browser's tools. The server is the only referee the cheater can't talk to.
Secure session cookie
A session cookie is the little ID card your browser shows after logging in. Setting it 'secure' means: only sent over encrypted connections (Secure), invisible to web-page scripts (HttpOnly), and blocked from other websites (SameSite).
An unprotected cookie can be stolen by a malicious page, letting the thief impersonate you without ever knowing your password — the login itself stays useless without the card.
Cookie jar
Hidden script on page
document.cookie → ?Hash passwords
Hashing turns a password into a fixed-length fingerprint using a one-way function. You can check 'does this fingerprint match?' but you can never turn the fingerprint back into the password. Add a 'salt' (random extra data) so identical passwords get different fingerprints.
If the password table is stolen, hashed passwords stay useless to the thief. Plain-text or weakly-hashed passwords are an instant catastrophe — and users reuse passwords everywhere.
users table
Thief's result
—Parameterize queries
A parameterized query is how a database is asked questions safely: the question and the data travel separately, so user-supplied text can never be mistaken for a command.
Without it, a user typing ' OR 1=1 -- into a search box can make the database hand over every record — the classic SQL injection attack, still one of the most exploited vulnerabilities in the world.
Scan dependencies
Modern apps are built mostly from other people's packages (libraries). Scanning means automatically checking those packages against known-vulnerability lists (CVEs) and keeping them updated.
Your code can be perfect and still get hacked through an outdated library you didn't even know you had. Attacks on dependencies outnumber attacks on hand-written code.