What is the most effective way to prevent SQL injection?
Use parameterized queries, also called prepared statements, for every query that includes variable data. A parameterized query sends the SQL structure and the user-supplied values to the database separately, so the values can never be reinterpreted as SQL code, which closes the injection vector at its root. Object-relational mappers and query builders that bind parameters give the same guarantee, but raw string concatenation - even with manual escaping - does not, because escaping is error-prone and context-dependent. Add least-privilege database accounts and allow-list input validation as defense in depth, but treat parameterization as the non-negotiable primary control.
How do I stop cross-site scripting (XSS) in a modern web app?
Combine context-aware output encoding with a strict Content Security Policy. Encoding ensures that user data is rendered as inert text in whatever context it appears (HTML body, attribute, JavaScript, or URL), and modern frameworks like React and Angular do this automatically for normal bindings. The danger is bypassing those defaults through raw-HTML sinks such as innerHTML or dangerouslySetInnerHTML; sanitize such input with a vetted library if you truly need HTML. Layer a nonce- or hash-based CSP on top so that even an injected inline script without the correct nonce is blocked by the browser.
Should I store JWTs in localStorage or in cookies?
It is a trade-off between XSS exposure and CSRF surface, and there is no universally correct answer. Anything in localStorage is readable by any JavaScript running on the page, so a single XSS flaw can exfiltrate the token; an HttpOnly cookie is invisible to script but is sent automatically, which reintroduces CSRF and requires SameSite plus anti-CSRF tokens. For most browser apps, an HttpOnly, Secure, SameSite cookie holding a short-lived token with a server-side refresh mechanism is the more defensible default. Whichever you choose, keep tokens short-lived and ensure you can revoke or rotate them.
What is the difference between authentication and authorization?
Authentication verifies who a principal is, while authorization decides what that authenticated principal is allowed to do. You authenticate once to establish identity (password, passkey, token) and then authorization is checked on every protected operation against the server's notion of identity and permissions. Conflating the two is a common source of bugs: a correctly logged-in user can still perform actions they should not, which is broken access control. Always enforce authorization server-side per request, never by trusting a client-supplied role or hiding options in the UI.
How do I prevent CSRF attacks?
Use anti-CSRF tokens and set the SameSite attribute on session cookies. A synchronizer or double-submit token is an unpredictable value the server issues and then validates on each state-changing request, proving the request came from your own pages rather than a forged cross-site one. SameSite=Lax or Strict further instructs the browser not to attach the session cookie on cross-site subrequests, which blocks most CSRF without any token. Note that CSRF specifically targets cookie-based sessions; APIs authenticated purely with a bearer token in a header that the browser does not attach automatically are generally not exposed to it.
Is HTTPS enough to secure my website?
No. HTTPS (via TLS) protects data in transit - confidentiality, integrity, and server authentication - but it does nothing about application-layer flaws such as injection, broken access control, XSS, or weak authentication. A site can be fully encrypted and still trivially hackable. Treat TLS as a mandatory baseline (with TLS 1.3, valid certificates, and HSTS), then address the OWASP Top 10 risks in the application itself, plus encryption at rest, secure session management, and least privilege.
What is the OWASP Top 10 and should I follow it?
The OWASP Top 10 is a regularly updated, community-driven list of the most critical web application security risks, used industry-wide as an awareness and prioritization baseline. It is not an exhaustive standard, but it captures the categories - broken access control, injection, cryptographic failures, security misconfiguration, and so on - that cause most real-world breaches. Use it to anchor a security program and developer training, and graduate to the more granular OWASP ASVS when you need testable, verifiable requirements. Following it does not certify you secure, but ignoring it almost guarantees common, avoidable holes.
How should I securely store user passwords?
Never store passwords in plaintext or with fast or reversible hashing. Use a slow, salted, memory-hard password hashing function designed for the purpose - Argon2id is the current first choice, with scrypt and bcrypt as accepted alternatives - so that even a database breach makes offline cracking expensive. The salt makes precomputed (rainbow-table) attacks useless and must be unique per password; the work factor should be tuned to be as high as your latency budget allows. Enforce a long minimum length, screen against known-breached passwords, and offer MFA on top.
What is SSRF and why is it dangerous in the cloud?
Server-Side Request Forgery (SSRF) tricks your server into making requests to a destination the attacker chooses, which is especially dangerous in cloud environments. Because the request originates from inside your trust boundary, it can reach internal-only services and, critically, the cloud instance metadata endpoint at 169.254.169.254, which may hand out temporary credentials. Mitigate it by validating and allow-listing outbound destinations, blocking link-local and private IP ranges, disabling unused URL schemes and automatic redirect following, and using metadata service hardening such as IMDSv2.
What is the principle of least privilege and how do I apply it?
Least privilege means every user, process, and service account is granted only the permissions strictly required for its task and nothing more. In a web stack you apply it by giving the application a database user limited to the tables and operations it actually uses, issuing scoped and short-lived API tokens, separating read and write credentials, and avoiding running services as root. The benefit is containment: when any one component is compromised, the attacker inherits only that narrow set of rights, sharply limiting the blast radius.
Do I still need server-side validation if the frontend already validates input?
Yes, always. Client-side validation is purely a usability and performance convenience and provides no security, because an attacker can bypass the browser entirely and send any payload directly to your API with tools like curl. Every security-relevant check - input validation, authorization, business rules, rate limits - must be enforced on the server, which is the only place you control. Treat all incoming data as untrusted regardless of which client supposedly sent it.
How do I secure cookies for session management?
Set the Secure, HttpOnly, and SameSite attributes on session cookies, and consider the __Host- prefix. Secure ensures the cookie is only sent over HTTPS, HttpOnly hides it from JavaScript so an XSS flaw cannot read it, and SameSite=Lax or Strict limits cross-site sending to reduce CSRF. Use high-entropy session identifiers, regenerate the session ID immediately after login to prevent fixation, enforce idle and absolute timeouts, and invalidate the session server-side on logout.
What security headers should every web app send?
At minimum send Content-Security-Policy (a strict, nonce- or hash-based policy), Strict-Transport-Security (HSTS to force HTTPS), and X-Content-Type-Options: nosniff (to stop MIME sniffing). Add Content-Security-Policy: frame-ancestors (or X-Frame-Options) to prevent clickjacking, and a sensible Referrer-Policy to limit referrer leakage. Headers are cheap, high-leverage defense in depth, but they complement - never replace - secure coding such as output encoding and access control.
How do I prevent broken access control and IDOR?
Enforce an authorization check on the server for every object access, verifying that the authenticated user owns or is permitted to act on the specific resource - not merely that they are logged in. The classic IDOR/BOLA failure is exposing an identifier (such as /invoices/123) and serving it without checking ownership, letting attackers enumerate others' data by changing the ID. Deny by default, centralize the authorization logic so it is hard to forget, use indirect or unguessable references where helpful, and add automated tests that attempt cross-tenant access.
What is the most phishing-resistant way to authenticate users?
WebAuthn / FIDO2 (passkeys and security keys) is the strongest widely available method because authentication uses public-key cryptography bound to the site's origin, so the signature is useless on a look-alike phishing domain and there is no shared secret to steal or replay. Unlike passwords and even TOTP codes, the private key never leaves the authenticator and cannot be phished. Where passkeys are not yet feasible, require MFA and prefer push or one-time-code factors over SMS, which is susceptible to SIM-swapping.
How do I manage third-party dependency and supply-chain risk?
Treat your dependencies as part of your attack surface and control what enters your build. Pin versions with a committed lockfile, scan dependencies continuously for known vulnerabilities, generate and keep a Software Bill of Materials (SBOM), and review additions for typosquatting and unexpected maintainership changes. For third-party scripts loaded in the browser, add Subresource Integrity hashes so a compromised CDN cannot silently swap the file. Run your build and CI with least privilege so a malicious package cannot reach your secrets.
When should I rely on a Web Application Firewall (WAF)?
Use a WAF as defense in depth and for fast virtual patching, but never as a substitute for fixing the underlying flaw. A WAF blocks requests matching known attack patterns and can buy you time after a vulnerability is disclosed, yet attackers routinely bypass signature-based filtering with novel encodings or logic that does not match a rule. Treat WAF alerts as useful signal and an early-warning layer, while you remediate the actual vulnerability in the application code.