Small products are attacked for the same reasons large ones are: automated scanners do not care how big you are. They probe every public server for default passwords, exposed databases, known vulnerabilities in outdated software and login forms without limits. A small business app with customer data is a target simply because it is online.
You do not need a security team to be in good shape. You need a set of basics, done consistently. This post lists the foundations I put in place on every product I build and run, in plain terms, with the reasoning behind each.
1. Authentication done properly
- Never store passwords in plain text or with fast hashes. Use a slow, salted password hashing algorithm such as Argon2 or bcrypt, through a well-maintained library.
- Rate-limit login attempts, password resets and one-time code requests, per account and per IP address.
- Offer two-factor authentication for admin and staff accounts at minimum.
- Use short-lived sessions or tokens, with the ability to revoke them, so a stolen token or a lost phone can be cut off.
- Do not reveal whether an account exists in login or reset messages.
Where possible, use a mature authentication library or service instead of writing your own. Authentication is full of subtle details.
2. Authorization on the server, for every request
The most common serious vulnerability in business apps is not exotic: a user changes an ID in a request and sees or edits someone else's data. The app hid the button, but the API never checked.
- Check permissions on the server for every request, based on who the user is and what the record belongs to.
- Never trust IDs, roles or prices sent by the client.
- Write tests for permission rules on the most sensitive endpoints.
- Apply the same checks to admin panels and staff apps. See what your admin panel needs.
For products serving several companies, this extends to keeping each client's data separate. See multi-tenant or per-client deployments.
3. Treat all input as untrusted
- Use parameterized queries or an ORM, never string-built SQL.
- Validate input on the server: types, lengths, allowed values.
- Escape output in web pages to prevent cross-site scripting; modern frameworks do this by default, so be careful whenever you bypass it.
- Check uploaded files: type, size, and store them outside the web root with generated names. Never execute or serve them as code.
- Protect against cross-site request forgery for cookie-based sessions.
If your product uses AI models, text that reaches the model is input too, and it can try to manipulate it. See prompt injection risks.
4. Secrets out of the code
API keys, database passwords and signing keys must never be committed to the repository or shipped inside a mobile app or web page.
- Keep secrets in environment variables or a secrets manager.
- Give each environment its own secrets; staging should never hold production keys. See why you need a staging environment.
- Rotate secrets when someone with access leaves, and immediately if one leaks.
- Use secret scanning in your repository to catch accidents.
5. HTTPS everywhere
Serve everything over HTTPS, redirect plain HTTP, and enable HSTS once you are confident. Modern reverse proxies obtain and renew certificates automatically, so there is no reason not to. Set secure cookie flags, so session cookies are never sent over plain connections or readable by scripts.
6. Security headers
A few HTTP headers block whole classes of attacks:
- Content-Security-Policy to control which scripts can run.
- X-Content-Type-Options to stop content type guessing.
- Frame protection to prevent your pages from being embedded by other sites for clickjacking.
- Referrer-Policy to limit what is leaked in links.
Start with a sensible baseline and tighten it as you learn which resources your site needs.
7. Dependencies and updates
Most applications are mostly other people's code: frameworks, libraries, base images. Vulnerabilities in them are published regularly.
- Enable automated dependency alerts and update pull requests.
- Update frameworks and runtimes on a schedule, not only when forced.
- Rebuild container images regularly to pick up base image fixes.
- Keep the server's operating system patched, with automatic security updates. See hardening a new Linux server.
8. Minimal exposure
- Expose only what must be public: usually the web ports through a reverse proxy.
- Never expose databases, caches or admin tools directly to the internet.
- Restrict admin panels by login strength and, where practical, by network.
- Remove debug modes, default accounts and sample pages before launch.
9. Backups and recovery
Security includes being able to recover. Ransomware, a compromised account or a destructive bug can all destroy data. Keep automated, encrypted, off-site backups that the production server cannot delete, and test restoring them. See Postgres backups that actually restore.
10. Logging and monitoring
You cannot respond to what you cannot see:
- Log authentication events, permission failures, admin actions and errors.
- Never log passwords, tokens or full payment details.
- Alert on unusual patterns: spikes in failed logins, errors or traffic.
- Keep an audit trail of changes to sensitive data.
See monitoring and alerts for a small product.
11. Personal data
Collect only what you need, keep it only as long as you need it, and know where it is. Data protection laws differ between Lebanon, the GCC countries, Europe and elsewhere, and some clients have their own requirements on where data is stored. If you serve users in several countries, take advice on the rules that apply, and design your data handling so it can meet them.
12. An incident plan
Write down, before you need it:
- Who decides and who acts if something goes wrong.
- How to revoke sessions, rotate secrets and take a service offline.
- How to restore from backup.
- Who must be informed: users, clients, authorities where the law requires it.
A one-page plan, read once by the team, is far better than improvising during an incident.
Mobile apps
Mobile apps add a few specifics:
- Store tokens in the platform's secure storage, not in plain app storage.
- Remember that anything inside the app can be extracted; keep secrets on the server.
- Use certificate validation as standard, and do not disable it for convenience in release builds.
- Plan for forcing an update if a serious issue is found in an old app version. See API design for a mobile backend.
Getting an outside view
For products handling sensitive data or payments, an external review or penetration test is worth it before launch or major releases. For an existing product, a technical audit covers security alongside the rest of the system. See what a technical audit should cover.
Summary
Most breaches of small products come from basic gaps: missing permission checks, exposed services, outdated software, leaked secrets and untested backups. Cover the basics above, keep them up to date, and you remove most of the risk.
If you want your product's security reviewed or built in from the start, read about me, see my work, and get in touch.