Web Security Basics Every Developer Must Know — cod-ai.com

March 2026 · 17 min read · 3,991 words · Last Updated: March 31, 2026Advanced

Three years ago, I watched a startup I'd been consulting for lose everything in 72 hours. Not from a sophisticated nation-state attack or some zero-day exploit that made headlines. They lost their entire customer database, their reputation, and eventually their business because of a single SQL injection vulnerability that a junior developer introduced during a rushed Friday deployment. The attack happened on a Monday morning. By Wednesday afternoon, they were drafting bankruptcy papers.

💡 Key Takeaways

  • The Authentication Trap That Catches Everyone
  • Cross-Site Scripting: The Vulnerability That Never Dies
  • SQL Injection: The Ancient Vulnerability That Still Works
  • HTTPS Isn't Optional Anymore

I'm Sarah Chen, and I've spent the last 12 years as a security architect at companies ranging from scrappy startups to Fortune 500 enterprises. I've seen the same preventable mistakes destroy businesses over and over again. The frustrating part? Most of these disasters could have been avoided with basic security knowledge that takes less time to learn than your average JavaScript framework.

Here's what nobody tells you when you're learning to code: security isn't some advanced topic you tackle after you've mastered everything else. It's foundational. It's like learning to drive without understanding that red lights mean stop. You might get away with it for a while, but eventually, you're going to cause a catastrophic accident.

According to the 2023 Verizon Data Breach Investigations Report, 74% of breaches involved the human element, including errors, misuse, or social engineering. But here's the kicker: when they analyzed web application attacks specifically, they found that 86% exploited vulnerabilities that had been documented and preventable for over a decade. We're not losing to sophisticated attackers. We're losing to our own ignorance of the basics.

The Authentication Trap That Catches Everyone

Let me tell you about authentication, because this is where I see developers make their first critical mistake. They treat it like a checkbox feature rather than the foundation of their entire security model. I once reviewed code where a developer had implemented authentication by checking if a user's email existed in a cookie. Not a signed cookie. Not an encrypted token. Just a plain text email address that anyone could modify in their browser's developer tools.

When I pointed this out, the developer said, "But it works!" And that's the problem right there. Security vulnerabilities don't announce themselves with error messages. They work perfectly until someone exploits them.

Here's what proper authentication actually requires. First, you need to understand the difference between authentication (proving who you are) and authorization (proving what you're allowed to do). I've seen production systems where these concepts were so muddled that fixing one security issue created three more.

Password storage is non-negotiable. You must use a proper password hashing algorithm like bcrypt, scrypt, or Argon2. Not SHA-256. Not MD5. Definitely not plain text. I still encounter databases in 2026 where passwords are stored in plain text, and every single time, the developer tells me they "didn't think anyone would actually try to hack them." That's like leaving your front door unlocked because you don't think anyone would actually rob you.

The numbers here are stark. According to the 2023 Identity Theft Resource Center report, there were 3,205 data compromises affecting over 353 million victims in the United States alone. When researchers analyzed the breached data, they found that in cases where password storage methods were disclosed, 43% used inadequate hashing or no hashing at all.

Session management is where things get interesting. You need to generate cryptographically secure random session tokens. The built-in random number generators in most languages are not cryptographically secure. In Node.js, you want crypto.randomBytes(), not Math.random(). In Python, you want secrets.token_hex(), not random.random(). I've seen session tokens generated with timestamps and user IDs concatenated together. An attacker can predict those in seconds.

Your session tokens should be at least 128 bits of entropy. They should be transmitted only over HTTPS. They should have the HttpOnly flag set so JavaScript can't access them. They should have the Secure flag set so they're never sent over unencrypted connections. They should have the SameSite attribute set to prevent CSRF attacks. And they should expire. I recommend 30 minutes of inactivity for sensitive applications, maybe 24 hours for lower-risk scenarios.

Cross-Site Scripting: The Vulnerability That Never Dies

XSS attacks are like cockroaches. They've been around forever, everyone knows about them, and yet they keep showing up in production code. The OWASP Top 10 has included XSS vulnerabilities since its inception in 2003, and it's still there in 2026. That's 21 years of the same preventable vulnerability.

"Security isn't some advanced topic you tackle after you've mastered everything else. It's foundational. It's like learning to drive without understanding that red lights mean stop."

I remember auditing a healthcare application that displayed patient notes entered by doctors. The developers had built a rich text editor that allowed basic formatting. Sounds reasonable, right? Except they were taking that HTML input and rendering it directly on the page without any sanitization. I demonstrated the vulnerability by entering a patient note that contained a script tag. That script could have stolen session tokens, modified medical records, or exfiltrated patient data. The developers were shocked. They'd never considered that a doctor might be malicious, or that a doctor's compromised computer might inject malicious code.

Here's the fundamental principle: never trust user input. Ever. Not from doctors, not from administrators, not from your CEO. Every single piece of data that comes from outside your application is potentially malicious until proven otherwise.

There are three types of XSS you need to understand. Stored XSS is when malicious code gets saved in your database and executed every time someone views that data. Reflected XSS is when malicious code in a URL parameter gets immediately reflected back in the response. DOM-based XSS is when client-side JavaScript takes user input and inserts it into the page without proper sanitization.

The solution isn't complicated, but it requires discipline. You need to escape output based on context. If you're inserting data into HTML content, you need HTML entity encoding. If you're inserting data into a JavaScript string, you need JavaScript escaping. If you're inserting data into a URL, you need URL encoding. If you're inserting data into CSS, you need CSS escaping.

Modern frameworks help with this. React, Vue, and Angular all escape output by default. But they're not magic. If you use dangerouslySetInnerHTML in React or v-html in Vue, you're bypassing those protections. I've seen developers use these features because they "needed" to render HTML, without understanding that they were opening an XSS vulnerability.

Content Security Policy is your second line of defense. CSP is an HTTP header that tells the browser what sources of content are legitimate. You can block inline scripts entirely, restrict which domains can load JavaScript, and prevent a whole class of XSS attacks. According to Google's research, implementing a strict CSP can prevent approximately 95% of XSS attacks. Yet in my experience, fewer than 30% of applications I audit have any CSP at all, and most of those are so permissive they're essentially useless.

SQL Injection: The Ancient Vulnerability That Still Works

SQL injection should be extinct. It's been well-understood since the 1990s. Bobby Tables has been a meme for over a decade. And yet, according to Akamai's 2023 State of the Internet report, SQL injection attempts account for 65% of all web application attacks. Why? Because it still works.

Vulnerability TypeRisk LevelPrevention DifficultyCommon Cause
SQL InjectionCriticalEasyUnsanitized user input in queries
Weak AuthenticationCriticalEasyPoor password policies, no MFA
XSS (Cross-Site Scripting)HighModerateUnescaped user content in HTML
Broken Access ControlHighModerateMissing authorization checks
Security MisconfigurationMediumEasyDefault settings, exposed endpoints

I once consulted for an e-commerce company that had been in business for eight years. They'd processed millions of transactions. They had a team of 15 developers. And their search functionality was vulnerable to SQL injection. The code looked something like this: they took the search term from the URL parameter and concatenated it directly into a SQL query. No parameterization. No input validation. Nothing.

When I demonstrated the vulnerability by extracting their entire user table in a single request, the CTO went pale. They'd been operating with this vulnerability for eight years. Thousands of customers' personal information, credit card details, purchase history—all of it accessible to anyone who knew basic SQL syntax.

The fix is straightforward: use parameterized queries or prepared statements. Every modern database library supports them. In Node.js with PostgreSQL, you use $1, $2 placeholders. In Python with SQLite, you use ? placeholders. In PHP with PDO, you use :name placeholders. The database driver handles escaping and ensures that user input is treated as data, never as code.

🛠 Explore Our Tools

SQL Formatter & Beautifier — Free Online Tool → COD-AI vs Cursor vs GitHub Copilot — AI Code Tool Comparison → How to Decode JWT Tokens — Free Guide →

But here's where developers get tricky. They think they can outsmart SQL injection with input validation. They'll strip out semicolons or quote characters or the word "DROP." This is security through obscurity, and it doesn't work. Attackers have dozens of techniques to bypass these filters. They'll use URL encoding, Unicode characters, or SQL comments to sneak past your validation.

Object-Relational Mappers like Sequelize, SQLAlchemy, or Entity Framework help, but they're not foolproof. I've seen developers use raw query methods in ORMs, completely bypassing the protection. I've seen developers build dynamic queries by concatenating strings, even when using an ORM. The tool doesn't matter if you're using it wrong.

The principle of least privilege applies here too. Your application shouldn't connect to the database with an account that has full administrative privileges. If your application only needs to read and write to specific tables, that's all the database user should be able to do. When that e-commerce company got breached, the attacker could have dropped their entire database because the application connected with a superuser account. Proper database permissions would have limited the damage significantly.

HTTPS Isn't Optional Anymore

I still encounter developers who think HTTPS is only necessary for login pages or checkout flows. This is dangerously wrong. Every single page of your application should be served over HTTPS. Every API endpoint. Every image. Every stylesheet. Everything.

"We're not losing to sophisticated attackers. We're losing to our own ignorance of the basics. 86% of web application attacks exploit vulnerabilities that have been documented and preventable for over a decade."

Here's why this matters more than you think. When you serve a page over HTTP, everything is transmitted in plain text. Not just passwords. Session cookies. CSRF tokens. API keys. Personal information. All of it visible to anyone who can intercept the traffic. And intercepting traffic is easier than most developers realize.

I demonstrated this at a conference once. I set up a rogue WiFi access point with a name like "Conference Guest WiFi." Within 30 minutes, I had captured session cookies from dozens of attendees browsing sites over HTTP. I could have hijacked their sessions, stolen their data, or modified the content they were viewing. The scary part? This requires no sophisticated hacking skills. The tools are free and the tutorials are on YouTube.

Let's Encrypt made HTTPS free and automated. There's no excuse anymore. You can get a valid SSL/TLS certificate in minutes, and it auto-renews. The performance overhead of HTTPS is negligible with modern hardware and HTTP/2. According to Cloudflare's measurements, HTTPS adds less than 50 milliseconds of latency on average.

But getting a certificate isn't enough. You need to configure it properly. Use TLS 1.2 or 1.3 only. Disable older protocols like SSL 3.0 and TLS 1.0—they have known vulnerabilities. Use strong cipher suites. Enable HTTP Strict Transport Security (HSTS) to tell browsers to always use HTTPS. Enable HSTS preloading to protect users even on their first visit.

Mixed content is a common mistake. If your page is served over HTTPS but loads resources like images or scripts over HTTP, browsers will block those resources or show security warnings. I've seen production sites where the main page was HTTPS but the login form submitted to an HTTP endpoint. That's worse than no HTTPS at all because it gives users a false sense of security.

Cross-Site Request Forgery: The Invisible Attack

CSRF is one of those vulnerabilities that developers don't understand until they see it exploited. The attack is elegant in its simplicity. An attacker tricks a user into making a request to your application while they're authenticated. The browser automatically includes the session cookie, and your application processes the request as if the user intended it.

I saw this exploited at a financial services company. They had a money transfer feature that took the recipient account and amount as POST parameters. No CSRF protection. An attacker created a webpage with a hidden form that automatically submitted when the page loaded. They distributed the link through phishing emails. When authenticated users visited the page, it silently transferred money to the attacker's account. The company lost $47,000 before they noticed the pattern.

The standard defense is CSRF tokens. Your application generates a random token, stores it in the user's session, and includes it in every form. When the form is submitted, you verify that the token matches. Since the attacker can't read the token from your site (thanks to the same-origin policy), they can't include it in their malicious request.

But CSRF tokens only work if you implement them correctly. The token must be unpredictable—use a cryptographically secure random number generator. The token must be tied to the user's session. The token must be validated on every state-changing request. And the token must be included in a way that the attacker can't access it.

I've seen developers put CSRF tokens in URLs. This doesn't work because URLs can leak through Referer headers, browser history, and server logs. I've seen developers use the same CSRF token for all users. This doesn't work because an attacker can just grab the token from their own session. I've seen developers validate CSRF tokens only on POST requests but allow the same action via GET. This doesn't work because GET requests are even easier to trigger.

The SameSite cookie attribute provides additional protection. Setting SameSite=Strict or SameSite=Lax prevents the browser from sending cookies on cross-site requests. This blocks most CSRF attacks at the browser level. But it's not a complete replacement for CSRF tokens because not all browsers support it, and there are edge cases where it doesn't apply.

API Security: More Than Just Authentication

APIs have become the backbone of modern applications, and they're also becoming the primary attack vector. According to Gartner, API attacks increased by 681% between 2021 and 2023. Yet most developers treat API security as an afterthought.

"Most security disasters could have been avoided with basic security knowledge that takes less time to learn than your average JavaScript framework."

I audited a mobile app backend where the API had proper authentication but no authorization checks. Once you had a valid API token, you could access any user's data by changing the user ID in the request. The developers assumed that because the API required authentication, it was secure. They never considered that an authenticated user might try to access someone else's data.

This is called an Insecure Direct Object Reference, and it's shockingly common. The fix is simple: always verify that the authenticated user has permission to access the requested resource. Don't just check if they're logged in. Check if they own the data or have been granted access to it.

Rate limiting is critical for APIs. Without it, attackers can brute force authentication, scrape your entire database, or launch denial-of-service attacks. I recommend implementing rate limiting at multiple levels: per IP address, per user account, and per API endpoint. For authentication endpoints, I typically set a limit of 5 failed attempts per 15 minutes. For data retrieval endpoints, maybe 100 requests per minute. For expensive operations like search or report generation, maybe 10 requests per minute.

API keys should be treated like passwords. They should be long, random, and unpredictable. They should be transmitted only over HTTPS. They should be stored securely on the client side—not hardcoded in mobile apps or JavaScript files. I've extracted API keys from decompiled mobile apps more times than I can count. If your API key is in your client-side code, assume it's public.

Input validation is even more critical for APIs because they often receive structured data like JSON or XML. You need to validate not just the values but the structure. Check data types. Enforce length limits. Validate against a schema. I've seen APIs that crashed when sent a deeply nested JSON object because they didn't limit recursion depth. I've seen APIs that leaked memory when sent extremely long strings because they didn't enforce size limits.

Error messages in APIs need special attention. Detailed error messages are helpful for developers but dangerous in production. I've seen APIs that returned full SQL error messages, revealing table names and column names. I've seen APIs that returned stack traces showing file paths and internal logic. Every piece of information you leak makes an attacker's job easier.

Dependency Management: The Supply Chain Problem

Modern development means using hundreds or thousands of third-party dependencies. The average Node.js project has over 1,000 dependencies when you count transitive dependencies. Each one is a potential security vulnerability.

The 2023 Sonatype State of the Software Supply Chain report found that 1 in 8 open source downloads contained a known security vulnerability. That's 12.5% of all downloads. And those are just the known vulnerabilities. Zero-day vulnerabilities in dependencies are discovered regularly.

I worked with a startup that got breached through a vulnerability in a logging library they'd installed two years earlier. The library had been updated to fix the vulnerability, but they never updated their dependencies. The vulnerability was publicly disclosed. Exploit code was available on GitHub. And they were still running the vulnerable version.

You need a process for managing dependencies. Use tools like npm audit, pip-audit, or OWASP Dependency-Check to scan for known vulnerabilities. Run these scans regularly—I recommend daily in CI/CD pipelines. Set up automated alerts when new vulnerabilities are discovered in your dependencies.

But scanning isn't enough. You need to actually update your dependencies. I know this is scary. Updates can break things. But running vulnerable code is scarier. The key is to update regularly in small increments rather than letting dependencies get years out of date and then trying to update everything at once.

Be selective about what dependencies you add. Every dependency is code you're trusting with your application's security. Before adding a dependency, check how actively maintained it is. Look at the number of contributors. Check when the last commit was. Read the issues and pull requests. A popular package with thousands of weekly downloads can still be abandoned or poorly maintained.

The 2021 Log4Shell vulnerability was a wake-up call for many organizations. A critical vulnerability in a widely-used Java logging library affected millions of applications. Companies scrambled to patch their systems. Some didn't even know they were using Log4j because it was a transitive dependency several layers deep. This highlighted the importance of having a complete inventory of your dependencies.

Security Headers: The Low-Hanging Fruit

Security headers are one of the easiest ways to improve your application's security posture, yet most applications don't use them properly. These are HTTP response headers that tell the browser how to handle your content securely.

Content-Security-Policy is the most powerful but also the most complex. It controls what resources the browser is allowed to load. You can block inline scripts, restrict which domains can load JavaScript, prevent framing attacks, and more. A strict CSP can prevent most XSS attacks even if you have a vulnerability in your code.

X-Frame-Options prevents your site from being embedded in an iframe on another domain. This protects against clickjacking attacks where an attacker overlays invisible iframes to trick users into clicking things they didn't intend to. Set it to DENY or SAMEORIGIN unless you specifically need your site to be frameable.

X-Content-Type-Options prevents browsers from MIME-sniffing responses away from the declared content type. Set it to nosniff. This prevents attacks where an attacker uploads a file that looks like an image but contains JavaScript, and the browser executes it.

Strict-Transport-Security tells browsers to always use HTTPS for your domain. Set it with a long max-age (I recommend at least one year) and include subdomains. Once a browser sees this header, it will refuse to connect to your site over HTTP, even if the user types http:// in the address bar.

Referrer-Policy controls how much information is sent in the Referer header when users navigate away from your site. This can prevent leaking sensitive information in URLs. I typically use strict-origin-when-cross-origin as a good balance between functionality and privacy.

Permissions-Policy (formerly Feature-Policy) lets you control which browser features your site can use. You can disable the camera, microphone, geolocation, and other sensitive APIs. This limits the damage if your site is compromised.

According to the 2023 Security Headers report, only 7% of the top 1 million websites implement a strict Content-Security-Policy. Only 23% use X-Frame-Options. Only 18% use Strict-Transport-Security. These are free protections that take minutes to implement, yet most sites don't use them.

The Security Mindset: Thinking Like an Attacker

Technical controls are important, but the most critical security skill is developing a security mindset. You need to think like an attacker. When you build a feature, ask yourself: how could someone abuse this? What happens if I send unexpected input? What if I send too much input? What if I send no input? What if I send the same request 10,000 times?

I teach developers to practice threat modeling. For every feature, identify what could go wrong. What are you trying to protect? Who might attack it? What are their capabilities? What are the possible attack vectors? This doesn't need to be a formal process with diagrams and documentation. Even spending five minutes thinking through these questions will catch most obvious vulnerabilities.

Defense in depth is a fundamental principle. Don't rely on a single security control. Layer multiple protections so that if one fails, others are still in place. Use input validation and output encoding. Use CSRF tokens and SameSite cookies. Use authentication and authorization. Use HTTPS and security headers. Each layer makes an attacker's job harder.

The principle of least privilege applies everywhere. Give users, processes, and systems only the minimum permissions they need. Your application shouldn't run with root privileges. Your database user shouldn't have DROP TABLE permissions. Your API tokens shouldn't have access to everything. When something gets compromised—and eventually something will—limited permissions limit the damage.

Security is not a one-time task. It's an ongoing process. New vulnerabilities are discovered constantly. Attack techniques evolve. Your application changes. You need to stay informed about security issues in your dependencies, your frameworks, and your infrastructure. You need to regularly review your code for security issues. You need to test your security controls to make sure they actually work.

I've seen too many developers treat security as someone else's problem. "We have a security team for that." "That's the ops team's responsibility." "We'll add security later." This mindset is how breaches happen. Security is everyone's responsibility. Every developer needs to understand these basics and apply them in their daily work.

The startup I mentioned at the beginning? They could have prevented their breach with basic input validation and parameterized queries. The healthcare application? Output encoding would have stopped the XSS vulnerability. The financial services company? CSRF tokens would have prevented the unauthorized transfers. These weren't sophisticated attacks requiring nation-state resources. They were basic attacks exploiting basic vulnerabilities.

Security doesn't have to be complicated. Start with these fundamentals. Use parameterized queries. Escape output. Implement authentication properly. Use HTTPS everywhere. Add security headers. Keep dependencies updated. Think like an attacker. These basics will prevent the vast majority of attacks you'll face.

The cost of learning these basics is a few hours of your time. The cost of not learning them could be your company's reputation, your customers' data, or your career. I've seen all three happen. Don't let it happen to you.

Disclaimer: This article is for informational purposes only. While we strive for accuracy, technology evolves rapidly. Always verify critical information from official sources. Some links may be affiliate links.

C

Written by the Cod-AI Team

Our editorial team specializes in software development and programming. We research, test, and write in-depth guides to help you work smarter with the right tools.

Share This Article

Twitter LinkedIn Reddit HN

Related Tools

SQL Formatter & Beautifier — Free Online Tool Top 10 Developer Tips & Tricks Chris Yang — Editor at cod-ai.com

Related Articles

Hash Functions Explained for Developers (MD5, SHA-256, bcrypt) Web Performance Optimization: Make Your Site Fast — cod-ai.com Clean Code: 10 Principles That Make You a Better Developer — cod-ai.com

Put this into practice

Try Our Free Tools →

🔧 Explore More Tools

Chatgpt Coding AlternativeReplit AlternativeDiff CheckerMinifierCode FormatterHow To Generate Typescript Types

📬 Stay Updated

Get notified about new tools and features. No spam.