BlogWeb Development

Web Application Security Checklist for Custom-Built Products

Z

Zihan

5 min read

Security isn't a phase, it's a set of defaults

Every web application security checklist we've seen treats security as a final review step before launch, and that's exactly backwards. By the time you're running a pre-launch security audit, the architecture is already set, you're finding things to patch, not opportunities to design out entire classes of vulnerability. The checklist that actually matters is the one applied at the schema and API design stage, not the one run the week before go-live.

This distinction matters because the cost of fixing a design flaw grows enormously the later you catch it. A missing authorization check found in a code review costs an hour. The same flaw found by a penetration tester the week before launch costs a scramble across the whole team. Found after a real incident, it costs customer trust, and sometimes the relationship with the client entirely. Every security practice we recommend here is cheaper the earlier it's adopted, which is the whole argument for building it in as a default rather than auditing for it later.

Authentication and authorization are not the same checkbox

We see this mistake constantly: a team implements solid authentication, password hashing, MFA, session handling, and treats the security work as done. Authorization, the question of what an authenticated user is actually allowed to touch, gets handled ad hoc, scattered across route handlers as if-statements. That's how you end up with a broken access control vulnerability, where user A can view user B's data simply by changing an ID in the URL, because nobody centralized the "can this user access this specific record" check.

The fix isn't complicated, just disciplined: authorization checks belong in one layer, ideally close to the data access itself, not duplicated across every endpoint that touches a resource. Centralize it once and every future feature inherits the protection instead of needing its own security review.

Input validation at the boundary, not scattered through the app

Every piece of data entering your system, form submissions, API payloads, query parameters, file uploads, needs validation at the point it enters, using a strict schema that rejects anything unexpected rather than trying to sanitize it after the fact. This single practice closes off SQL injection, most XSS vectors, and a huge share of the exploits that show up in real-world breach reports. Trusting client-side validation alone, or validating loosely and hoping downstream code handles the edge cases, is how avoidable vulnerabilities make it to production.

File uploads deserve a specific callout here because we still see them handled loosely on otherwise well-built applications. Validating file type by extension alone, storing uploads inside the application's own execution path, or skipping virus scanning are all common shortcuts that turn a convenience feature into an entry point. Treat every uploaded file as untrusted content, store it outside anything that gets executed, and validate its actual contents, not just its filename.

Secrets management is where good intentions go to die

We still find API keys committed to git history, database credentials in environment files checked into a repo, and third-party tokens hardcoded directly into client-side JavaScript where anyone can read them from the browser. A working secrets management setup, environment variables injected at deploy time, a proper secrets manager for anything sensitive, rotation on a schedule, needs to be part of the initial infrastructure setup, not something retrofitted after a scare.

The most dangerous vulnerability in most applications isn't a clever exploit — it's the security control everyone assumed someone else had already added.

Dependency risk is bigger than most teams admit

A modern web application pulls in hundreds of third-party packages, and each one is a piece of code you didn't write running with your application's trust level. Automated dependency scanning, prompt patching of known vulnerabilities, and genuinely minimizing unnecessary dependencies aren't optional hygiene, they're one of the highest-leverage security practices available, because supply chain compromises bypass every other control you've built.

We also push back on the reflex to add a new package for something a few lines of application code could handle directly. Every dependency you don't add is a dependency you'll never need to patch, audit, or worry about when its maintainer disappears or its account gets compromised. This is especially true for small utility libraries that wrap a handful of standard library calls, the convenience rarely outweighs the long-term exposure of one more link in your supply chain.

Logging and monitoring decide how bad an incident actually gets

Every application eventually has a security incident of some size, and the difference between a contained issue and a genuine crisis is almost always how fast it's detected and how much visibility you have into what happened. Structured logging of authentication events, access to sensitive records, and anomalous patterns, combined with alerting that a human actually sees, turns "we don't know how long this has been happening" into "we caught this within the hour." A security checklist that stops at prevention and skips detection is only doing half the job.

If you're scoping something like this, see our custom web application development.

Written by

Co-Founder at CookieTech and the team's AI lead, focused on backend systems and applied AI.

Z

Zihan

5 min read

Building somethinglike this? Let's talk.

Book a free 30-min call we'll tell you if it's a 90-day build.