Security is the topic most developers push to the backlog — until the first incident. Then it's too late for a calm rollout. You're in firefighting mode, writing post-mortems, and explaining to clients why their data leaked. This is a practical guide you can implement today — from static analysis to dependency scanning to a CI/CD pipeline that enforces security automatically.
Why security always ends up at the bottom of the list
It's not about bad intentions. Security doesn't give you immediate feedback — you don't see the effect the way you do with a new feature. There's no sprint called 'add security'. Everyone assumes someone else handled it.
The problem is systemic: most teams implement security reactively. The security audit sits in the backlog next to other "nice-to-haves" until something goes wrong. And when it does — the cost is incomparably higher than if it had been built in from the start.
Good news: tooling is mature enough today to automate 80% of the work. No dedicated security engineer required. No week-long project.
Step 1: Static Application Security Testing (SAST)
Static analysis is your first filter — you scan code before the application even runs. Tools analyze the AST (Abstract Syntax Tree) and look for patterns of known vulnerabilities.
SonarQube — open-source, self-hostable. Catches injection, hardcoded credentials, unused variables that could become attack vectors. Integrates with GitHub/GitLab in 15 minutes.
ESLint security plugins — if you write Node.js/TypeScript, eslint-plugin-security and eslint-plugin-no-unsanitized catch common mistakes like eval(), innerHTML assignments, and path traversal.
CodeQL (GitHub) — free for open-source, paid for private repos. Semantic analysis that understands data flow. Catches vulnerabilities that simpler pattern-matching tools miss.
Rule of thumb: SAST in the pre-commit hook and in the CI pipeline. Developers get feedback before push; pipeline blocks merges on critical findings.
Step 2: Dependency Scanning (SCA)
Your code might be clean — but the libraries you use? Not necessarily. Every Node.js/Python project has hundreds of transitive dependencies. That's a massive attack surface.
Trivy (Aqua Security) — scans Docker images, filesystems, and repositories. Detects CVEs in OS packages and application libraries. Plugs into CI like any other CLI tool.
Snyk — has a free tier for individual developers. Scans package.json/requirements.txt/Gemfile and suggests fixes. Can automatically open PRs with patches.
npm audit / pip-audit — built into the ecosystem, zero config. Run in pipeline and set threshold with --audit-level=high.
Important: don't ignore alerts. Set a policy: critical/high blocks deploy, medium/low → ticket for the next sprint.

Step 3: OWASP Top 10 — practical examples
OWASP Top 10 is the list of the most common web application vulnerabilities. Knowing it is the minimum bar for any developer. Three I see most often in code review:
Injection (SQL, NoSQL, Command) — still #1. ORM is not a security guarantee if you use raw queries. Always parameterized queries, never string concatenation in SQL.
Broken Authentication — weak tokens, missing secret rotation, JWT with unverified signatures (alg: none). Use battle-tested libraries, don't write your own auth.
IDOR (Insecure Direct Object Reference) — endpoint /api/orders/1234 returns another user's order if you don't check ownership. This is a partial authorization check failure — the most common bug in CRUD APIs.
- Injection → parameterized queries, ORM, input validation
- Broken Auth → mature lib (Passport, NextAuth), proper JWT config
- IDOR → always verify resource ownership in middleware
- Sensitive Data Exposure → TLS everywhere, encryption at rest
- Security Misconfiguration → CIS benchmarks, hardened Docker images
- XSS → Content Security Policy; React/Vue sanitize by default — don't work around it
Step 4: DAST — test like an attacker
DAST (Dynamic Application Security Testing) runs against a live application. It sends malicious payloads and observes the response. It complements SAST — because some vulnerabilities only surface at runtime.
OWASP ZAP — the flagship tool. Can run as a proxy during manual testing or in fully automated scan mode in CI. A baseline scan takes ~5 minutes and catches low-hanging fruit.
Recommended approach: ZAP baseline scan in the staging pipeline after every deploy. Full scan weekly or before each release.
Step 5: AI-assisted code review
AI models won't replace a security engineer, but they make a solid first filter during code review. Good prompting plus a code-aware model can catch logical vulnerabilities that pattern-based tools miss.
Practical use: security-angle CR checklist for every PR touching auth, payments, file uploads, or external APIs. AI reviews the diff and flags potential issues. Senior developer validates.
Caveat: never paste secrets or sensitive customer data into external models. Use a self-hosted LLM or an enterprise tier with a DPA.

Step 6: CI/CD pipeline as the last line of defense
Everything above only works if it's enforced automatically. Manual processes get skipped under deadline pressure.
Example security gate pipeline:
- Pre-commit: ESLint security + detect-secrets (no hardcoded creds)
- PR: SonarQube scan → comment on PR with results
- PR: npm audit / trivy → block merge at severity >= high
- Staging deploy: OWASP ZAP baseline scan
- Weekly: full dependency audit + image scan
Critical: the pipeline must block deploys on critical findings — not just warn. Warnings without consequences get ignored.
Self-hosting as a security model
There's another dimension of security that rarely gets discussed: control over your infrastructure. When you use a SaaS CRM, your customer data lives on someone else's servers, under someone else's privacy policy, with someone else's access controls.
Self-hosting gives you tenant isolation at the infrastructure level, full control over data access, audit logs you own, and compliance on your terms (GDPR, SOC2).
That's the philosophy behind Khirby — an open-source CRM you can deploy in your own infrastructure. Your data, your servers, your rules.
Security checklist — TL;DR
- SAST: SonarQube or CodeQL in CI pipeline
- ESLint security plugin in pre-commit hook
- Dependency scan: Snyk or Trivy in CI (block on high/critical)
- OWASP Top 10: code review checklist for auth, CRUD, file upload
- DAST: ZAP baseline scan on staging
- Secrets detection: git-secrets or detect-secrets
- TLS everywhere, encryption at rest for sensitive data
- Policy: critical/high blocks deploy, medium → ticket
Security isn't a project you'll ever "finish". It's a practice — a set of habits and automations that do the work before you even start thinking about attacks. Automate what you can, set the right blocking thresholds, review with OWASP Top 10 in mind. The rest takes care of itself.



