A custom web application is secure enough for business when each user can see only their own data, logins and roles are tight, secret keys are kept out of the code, the framework and its packages are patched quickly, backups are tested, and someone is alerted when something odd happens. You do not need to read code to check this. You need the right questions for your developer, and you need to know which answers should worry you.
This checklist is for owners of custom CRMs, client portals, booking systems, internal tools and SaaS products, not WordPress sites. It uses the OWASP Top 10 2025, the most widely used list of web application risks, as its reference, and turns each risk into a plain question. It is not a tutorial. It is a list you can take into a meeting with your developer, plus a guide to when an outside review is worth paying for.
#Why a custom app needs its own checklist
A custom app's biggest risks sit in its own code and settings, not in a plugin someone else maintains. On a WordPress site, most security news is about plugins, and my article on WordPress website security for business owners covers that world. A custom CRM or portal is different: the rules about who sees what were written for your business, so only your developer can get them right.
The OWASP Top 10 2025 (opens in a new tab) is the reference most developers and auditors use. OWASP is a non-profit security community, and its list ranks the most serious risks in web applications. Here is what each item means for an owner.
| OWASP Top 10 2025 | What it means in plain words |
|---|---|
| A01 Broken Access Control | A user can see or change data that is not theirs |
| A02 Security Misconfiguration | A setting left open, a debug mode left on, a default password left in place |
| A03 Software Supply Chain Failures | A package or tool your app depends on is outdated, flawed or tampered with |
| A04 Cryptographic Failures | Sensitive data is not protected properly in storage or in transit |
| A05 Injection | Text typed by a user is treated as a command by the database or server |
| A06 Insecure Design | The feature itself was planned without thinking about abuse |
| A07 Authentication Failures | Logins, passwords and sessions can be guessed, stolen or reused |
| A08 Software or Data Integrity Failures | Updates or data are trusted without checking where they came from |
| A09 Security Logging and Alerting Failures | Attacks happen and nobody finds out |
| A10 Mishandling of Exceptional Conditions | When something goes wrong, the app fails in an unsafe way |
Two things stand out for owners. Misconfiguration, which is about settings rather than code, sits second. And the supply chain item reminds you that your app is only as safe as the packages it is built on.
#The checklist at a glance
Each row below is a question you can ask your developer, with the kind of answer that should reassure you. The sections after the table explain each one.
| Area | Ask your developer | A good answer sounds like |
|---|---|---|
| Access control | How do we stop one customer seeing another's data? | Every request is checked on the server, and the database itself enforces it |
| Logins and roles | Who can do what, and how do admins sign in? | Named roles, least access, two-step login for admins |
| Secrets and keys | Where are our API keys and database passwords? | In protected environment settings, never in the code or browser |
| Input handling | What happens if someone types code into a form? | All input is validated on the server and queries are parameterised |
| Updates | How fast do we apply framework security releases? | Within days for serious issues, on a regular schedule otherwise |
| Backups | When did we last restore a backup as a test? | A specific recent date, and how long it took |
| Logging and alerts | Would we know about 500 failed logins tonight? | Yes, and here is who gets the alert |
| Rate limits and bots | What stops a bot hammering our forms and login? | Limits per user and per address, plus bot protection on public forms |
| Security headers | Do we send the standard browser security headers? | Yes, including a content security policy and HTTPS-only |
| Failure handling | What happens when a payment or check fails halfway? | The app fails closed and rolls back, and nothing sensitive is shown |
#Access control: each user sees only their data
Access control is the rule that decides who can see and change each record, and it is the most common serious flaw in web apps. OWASP's page on A01 Broken Access Control (opens in a new tab) says 100% of the applications tested had some form of it.
The classic example is a link like "/invoice/1042". If a logged-in customer changes it to "/invoice/1043" and sees someone else's invoice, access control is broken. OWASP's advice is to deny by default, check ownership of every record, and enforce the rules in server-side code, because anything done only in the browser can be bypassed.
What to check:
- Ask for a demonstration: log in as one customer, then try to open another customer's record by changing the address. It should fail.
- Ask whether the database itself enforces the separation, not only the app code. On Supabase and PostgreSQL this is Row Level Security, explained in my article on keeping each customer's data separate in a SaaS app.
- Ask how caching is handled. The Next.js November 2026 security release (opens in a new tab) fixed a high severity issue where, in certain setups using Cache Components, cached content could be served to the wrong tenant.
#Logins and roles
Logins are the front door, and roles decide how far each person gets once inside. OWASP's page on A07 Authentication Failures (opens in a new tab) describes the usual gaps: weak or already-breached passwords allowed, bots free to try stolen passwords at scale, missing multi-factor login, and sessions that are not ended at logout or after inactivity.
What to check:
- Two-step login for every admin and for anyone who can see money or customer data. OWASP recommends multi-factor login to block attacks with stolen passwords.
- Named roles with the least access needed: a site supervisor does not need the accounts screen, and a client does not need the staff list.
- One account per person, never a shared office login, so actions can be traced.
- Leavers removed on their last day, and their sessions ended.
- Sessions that expire after inactivity and end at logout, plus a way to sign everyone out after an incident.
- Failed logins slowed down or limited, and logged, so password guessing is blocked and noticed.
#Secrets and keys
Secrets are the passwords and API keys your app uses to reach the database, payment gateway, email service and other systems. If one leaks, an attacker does not need to break in: they simply use the key.
Secrets should live in protected environment settings on the server, never in the code repository and never in anything sent to the browser. Each key should have only the permissions it needs, and there should be a list of every key and who can change it.
Rotation matters as much as storage. When the critical React2Shell flaw was announced, the Next.js advisory for CVE-2025-66478 (opens in a new tab) rated it CVSS 10.0 and told teams whose apps were online and unpatched to rotate their secrets after patching, starting with the most critical. Ask your developer whether rotating every key is a documented, practised job, or something nobody has tried.
#Input handling
Every form, search box, upload and API call is a way for outside data to enter your app, and the app must never trust it. Injection, A05 in the 2025 list, is what happens when typed text is treated as a command by the database or the server.
You do not need to know the techniques. Ask three questions: is all input checked on the server, not only in the browser; are database queries built safely so user text can never change the query; and are file uploads limited by type and size and stored away from the code. A clear yes to all three is what you want.
#Updates of frameworks and packages
A modern web app is built on hundreds of open source packages, and a flaw in any of them is a flaw in your app. OWASP's A03 Software Supply Chain Failures (opens in a new tab) category covers this. Its examples include the 2025 Shai-Hulud worm, which spread through npm packages and reached over 500 package versions.
OWASP's advice translates into a few owner-level checks:
- Keep a list of every component the app depends on, including the ones those depend on.
- Remove packages and features the app no longer uses.
- Watch for security advisories and apply fixes promptly.
- Stay on a supported version of the framework.
For Next.js apps, this is now a monthly routine. My article on Next.js 16 for business websites and apps explains the support dates and the security release program. Someone has to apply each release, and that is a natural part of ongoing maintenance and support.
#Backups and restore tests
A backup you have never restored is a hope, not a plan. Ask how often the database and uploaded files are backed up, where the copies are stored, how long they are kept, and when a restore was last tested.
A good answer names a schedule, a location separate from the live system, and a recent test with how long it took. Keep older copies too: a problem in the data can go unnoticed for weeks, and the latest backup may already contain it.
#Logging and alerts
Logging records what happened, and alerting makes sure a person finds out in time. OWASP's A09 Security Logging and Alerting Failures (opens in a new tab) page lists the common gaps: failed logins not recorded, logs nobody reviews, and no alert thresholds or escalation.
What to check:
- Logins, failed logins and permission errors are logged with enough detail to spot a suspicious account.
- Important actions, such as approvals, refunds and role changes, leave an audit trail.
- Logs do not contain passwords, card numbers or other personal data.
- A named person gets an alert when failures spike, and knows what to do next.
#Rate limits and bot protection on forms
Rate limits cap how often one user or address can try something, which stops bots guessing passwords, scraping data or flooding your forms. OWASP's access control guidance recommends rate limits on API and controller access to reduce the harm from automated attacks.
Ask for limits on login, password reset, sign-up, contact and quote forms, and any API that returns customer data. Public forms also benefit from bot protection, so your sales team is not reading spam all day.
#Security headers
Security headers are instructions your app sends to the browser about what the page is allowed to do. They are cheap to add and block whole classes of attack.
MDN's guide to Content Security Policy (opens in a new tab) explains that a content security policy restricts which scripts and resources a page may load, mainly to reduce cross-site scripting. It also covers stopping other sites from framing your pages, and pairing an HTTPS-only header with it. Ask whether the app sends these, and whether anyone has checked them since the last big release.
#Errors that fail safely
When something goes wrong, the app should stop safely rather than carry on in a half-finished state. This is A10 Mishandling of Exceptional Conditions in the 2025 list.
In business terms: a payment that fails halfway should not mark an invoice as paid, a permission check that errors should deny access rather than allow it, and an error page should never show internal details to the user. Ask how the app handles a failed payment, a timeout from a third-party service and a database error.
#The annual review
Security is not finished at launch, so put a review in the calendar once a year and after every big change. A big change means a new type of user, a new payment flow, a new integration that shares data, or customers from a new company on the same system.
The review can be short: walk through this checklist, check user accounts and roles, confirm the framework is on a supported version, test a restore, and read the last few months of security alerts. Budget for it as part of running the app, along with hosting and updates.
#Do it yourself or bring in a professional?
You can run most of this checklist yourself as a conversation with your developer. Bring in an outside review when the stakes or the doubts are higher.
| Situation | Sensible route |
|---|---|
| Small internal tool, a few trusted staff, no customer data | Use this checklist with your developer once a year |
| Portal or CRM holding client or financial data | Checklist plus an outside review of access control and logins |
| SaaS with customers from many companies | Outside review before launch and after major changes |
| Developer cannot answer several questions clearly | Outside review now |
| The original developer has left | Review the code, access, keys and hosting before anything else |
| Suspected breach or strange data | Treat it as an incident: preserve logs, rotate keys, then investigate |
When I review or tighten security on an existing app, the work covers the same areas as this list: access rules, roles, keys, updates, logging and failure handling, with a plain written report of what changed. That fits under custom web application development for larger apps and PHP and JavaScript development for smaller fixes.
#Where to start
Start with the two questions that catch the most serious problems: can one customer see another customer's data, and when did we last restore a backup? Ask your developer for a demonstration of the first and a date for the second.
Then take the table above to your next meeting and agree who owns each row. If several answers are vague, an outside look is worth it before the next big release, and you can ask me for one. If your business also runs a WordPress site, my guide to Google's dangerous site warning shows what happens when security slips there.
Frequently asked questions
What is the OWASP Top 10 2025?
It is a ranked list of the ten most serious security risks in web applications, published by the OWASP Foundation, a non-profit security community. The 2025 edition puts broken access control first, followed by security misconfiguration and software supply chain failures. Developers and auditors use it as a common reference.
How often should a custom web app be security reviewed?
Once a year as a routine, and again after any big change such as a new user type, a new payment flow or a new integration. Framework security releases should be applied in between, as they come out, not saved for the annual review.
Is a framework like Next.js or Laravel secure by default?
A good framework blocks many common attacks, but it cannot know your business rules. Who can see which record, which role can approve what, and how keys are stored are decisions your developer makes, and most serious flaws are in those decisions. The framework also needs regular security updates.
Do I need a penetration test for my web app?
Not always. A small internal tool may only need a checklist review. A portal or SaaS that holds customer or financial data, or serves customers from several companies, benefits from an outside review or penetration test before launch and after major changes.
What should I do if my developer cannot answer these questions?
Treat it as a signal to get an independent review, not as an accusation. Many apps are built in a hurry and security details are never written down. A review documents the current state, fixes the serious gaps first and leaves you with answers for next time.
Sources
The facts in this article were checked against these pages, last reviewed 12 November 2026.
- OWASP Top 10:2025, OWASP Foundationtop10.owasp.org/2025/
- A07:2025 Authentication Failures, OWASP Foundationtop10.owasp.org/2025/A07_2025-Authentication_Failures/
- A01:2025 Broken Access Control, OWASP Foundationtop10.owasp.org/2025/A01_2025-Broken_Access_Control/
- A03:2025 Software Supply Chain Failures, OWASP Foundationtop10.owasp.org/2025/A03_2025-Software_Supply_Chain_Failures/
- A09:2025 Security Logging and Alerting Failures, OWASP Foundationtop10.owasp.org/2025/A09_2025-Security_Logging_and_Alerting_Failures/
- Content Security Policy (CSP), MDN Web Docsdeveloper.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP
- November 2026 Security Release, Next.js Blognextjs.org/blog/november-2026-security-release
- Security Advisory: CVE-2025-66478, Next.js Blognextjs.org/blog/CVE-2025-66478




