Web Security Without the Paranoia: 5 Repeated Mistakes in SMEs
OWASP Top 10 is a solid theoretical framework, but it often paralyzes SMEs. Here are the 5 concrete issues we see over and over in projects that go live without a second thought.
28 de noviembre de 2025
The conversation about software security almost always starts with an OWASP Top 10 PDF and ends in paralysis: there are so many things to check that the team decides to "deal with it later." And "later" usually means after there’s already a problem.
Let’s flip the script. These are the 5 concrete issues we see repeatedly in SME projects that were already live. If you address these five, you’ll be ahead of 90% of web apps out there.
1. Validation Only on the Frontend
The most common mistake. The form includes client-side JavaScript validation: "this field is required," "the email must contain an @ sign," etc. And the backend assumes the data arrives clean.
The problem? Anyone with curl, Postman, or a browser’s dev tools can send whatever they want to the backend, bypassing frontend validation entirely.
What you need to do: All critical validation must also happen on the backend. Frontend validation improves UX (users see errors quickly). Backend validation improves security (your database doesn’t receive garbage).
In projects like Mi Seguro de Auto, where personal data is processed and real policies are quoted, every field is validated twice: on the client for immediate feedback, and on the server for trust.
2. Hardcoded Secrets in the Codebase
We’ve seen this more times than we’d like in audits. API keys, database passwords, service tokens—all sitting in the repo in files like config.js or constants.ts.
This is a double-edged problem: anyone with access to the code (including former developers) has access to your systems. And if the repo ever leaks (which happens more often than you think), those secrets are exposed.
What you need to do:
- Store all credentials in environment variables (
.env). - Always add
.envto.gitignore. - Include a
.env.examplewith variable names but no actual values. - For production, use your provider’s secret manager (Vercel, AWS Secrets Manager, etc.).
- Rotate credentials when someone leaves the team.
3. Missing Row-Level Security in Multi-Tenant Databases
If your app serves multiple clients/users who should not see each other’s data, isolation cannot rely solely on application-level filters.
Typical scenario: a query like WHERE user_id = ? and you trust the code to always insert the correct ID. One IDOR vulnerability or a bug in any endpoint could let a user view another’s data.
What you need to do: Implement Row-Level Security (RLS) at the database level. In Postgres (and Supabase), this is done with RLS policies that enforce automatically. The database won’t return rows that don’t belong to the current user, no matter how the query is written.
This extra defense layer is pure gold. Even if an endpoint forgets the filter or an attacker crafts an unexpected query, RLS keeps your data safe.
4. DIY Authentication
"We built our own auth system because having full control is more secure." This is the fastest way to introduce a serious vulnerability.
Doing auth well (password hashing with Argon2 or bcrypt and salts, JWT tokens with rotation, secure password recovery, timing attack prevention, rate-limiting login attempts) takes weeks, and it rarely works right the first time.
What you need to do: Use a mature provider. Supabase Auth, Auth0, Clerk, or NextAuth/Auth.js. They handle the hard stuff and stay up to date with best practices. Your code just orchestrates—it doesn’t roll its own crypto.
5. Logs Leaking Sensitive Data
When something breaks in production, the first instinct is to log everything. And in that everything? Plain-text passwords (because they came in the request body), tokens, credit card data, ID numbers.
Those logs end up in tools like Sentry, Datadog, or CloudWatch—accessible to more people than they should be—and stick around for months.
What you need to do:
- Maintain a list of sensitive fields that never get logged (
password,token,creditCard,ssn,dni, etc.). - Sanitize before logging: automatically replace sensitive values with
***. - Audit logs regularly to catch leaks early.
What’s Not on This List (On Purpose)
OWASP highlights more advanced issues like cross-site scripting, SQL injection, and insecure deserialization. These are important, but modern frameworks (React, Next.js, ORMs like Prisma) handle these vectors by default—if you’re not actively fighting against them. For an SME launching a product, the five issues above deliver far more security ROI than worrying about CSRF when you’re already using Next.js properly configured.
Conclusion
Security isn’t a project—it’s a habit. If you address these five points during development, review them annually, and keep dependencies updated, you’ll be in good shape. If you’ve never considered any of these and have something live processing customer data, it’s worth a review.
Want a pragmatic security audit for your app? Not an 80-page PDF, but a focused report with actionable fixes and a prioritized order? Get in touch.
By Esteban Aleart, Founder & Lead Engineer at Pair Programming.
FAQ
My site is small—do I really need to worry about security?
Absolutely. If your site stores user data (emails, phone numbers, or anything more sensitive), then yes. Automated attackers don’t discriminate by size: they scan the entire web for known vulnerabilities. A poorly protected small site gets compromised just like a large one.
How often should I run a security audit?
For SMEs with live web apps, an annual audit is reasonable. If you handle sensitive data (health, financial) or have a large user base, aim for every six months.
How much does a security audit cost?
A practical audit for a typical web app ranges from **USD 800 to USD 3,500**, depending on scope. Formal, certified audits cost significantly more.
What should I do if I experience a security incident?
1) **Contain** the breach (lock out the attacker, rotate credentials). 2) **Assess** the impact (what data was exposed?). 3) **Notify** stakeholders (users, authorities if required). 4) **Post-mortem** to prevent recurrence. Having a written plan *before* an incident hits is the only thing that prevents chaos.
Is using services like Supabase or Auth0 secure?
Yes—far more secure than rolling your own. These services have dedicated security teams and formal certifications. The risk shifts to the provider, which is a net win.
Artículos relacionados
Por que Next.js es nuestro stack default (y cuando no lo elegimos)
Mismo stack en cotizadores públicos, CRMs internos, plataformas con IA y sitios premium europeos. No es casualidad. Te cuento por que Next.js + Supabase es nuestro default y cuando lo cambiamos.
NegocioTransformación digital sin buzzwords: qué significa de verdad para una PyME
Transformación digital es uno de esos buzzwords que ya no significan nada. Cuando una PyME real lo necesita, lo que necesita son 3 cosas concretas. Te las cuento sin powerpoint.
TecnologíaCloud y DevOps para PyMEs: infraestructura escalable sin sobre-ingeniar
La mayoría de las pymes no necesitan Kubernetes. Necesitan algo que funcione, qué no se caiga el día que aparece un cliente importante, y que no las funda en costos fijos. Vamos al grano.