
September 09, 2026
11 min read
By Kokil Thapa | Last reviewed: September 2026
DevSecOps: Shift Security Left in CI/CD means you run security checks during every commit and merge request—not in a panic after a breach. On a production Laravel GitLab CI pipeline, that looks like dependency scans, static analysis, and secrets detection blocking a bad build before Deployer touches the server. I've maintained sister legal-tech sites on shared EC2 with this exact workflow. Security belongs in the pipeline, not in a quarterly audit deck.
What is DevSecOps and why should you shift security left in CI/CD?
DevSecOps treats security as a shared pipeline responsibility. Developers, ops, and security engineers use the same CI/CD system to catch flaws early. "Shift left" simply means moving those checks closer to the first commit.
Traditional security often waits until pre-release or post-incident review. That model fails on small teams. A solo developer shipping Laravel 13 on PHP 8.3 cannot afford a separate security sprint every month. Pipeline gates scale better.
The payoff is measurable. Fixing a SQL injection in a pull request costs hours. Fixing it after a law-firm portal leak costs clients, lawyers, and your sleep. On platforms like Mijar Law Associates, document uploads and payment flows demand server-side validation plus automated scanning.
DevSecOps is not a product you install once. It is a workflow change. Your CI/CD best practices for small teams already include linting and tests. Security stages slot into that same YAML file.
Core principles that actually stick
- Automate first: Manual checklists rot. Pipeline jobs run every time.
- Fail fast: Block merges when critical findings appear. Warnings can wait.
- Keep feedback short: Scans over ten minutes get ignored. Split heavy jobs.
- Fix ownership stays with devs: Security reports must name file and line.
- Protect secrets: Never echo credentials in job logs. Use masked variables.
How do you integrate security scanning into a GitLab CI pipeline?
GitLab CI is what I use on shared VPS deploys with Deployer 7. Security templates ship as included jobs. You extend an existing Laravel pipeline rather than rebuilding it.
Start with a baseline pipeline that already runs Composer install, Pest tests, and asset checks. Add security stages before the deploy stage. If any stage fails, the deploy job never runs.
Example GitLab CI security stages for Laravel 13
# .gitlab-ci.yml (excerpt)
stages:
- validate
- test
- security
- build
- deploy
include:
- template: Security/SAST.gitlab-ci.yml
- template: Security/Dependency-Scanning.gitlab-ci.yml
- template: Security/Secret-Detection.gitlab-ci.yml
variables:
SAST_EXCLUDED_PATHS: "vendor/,node_modules/,storage/,bootstrap/cache/"
composer_audit:
stage: security
image: php:8.3-cli
script:
- composer install --no-interaction --prefer-dist
- composer audit --format=plain
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
gitleaks_scan:
stage: security
image:
name: ghcr.io/gitleaks/gitleaks:latest
entrypoint: [""]
script:
- gitleaks detect --source . --verbose --redact
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
pest_tests:
stage: test
script:
- php artisan test --parallel
This pattern mirrors what I run before symlink swaps on production. The deploy stage depends on security completing green. See the full walkthrough in deploy a Laravel app with GitLab CI/CD to a VPS.
Composer 2.10 includes composer audit for known CVEs in PHP packages. Pair it with GitLab dependency scanning for defence in depth. Either tool can catch a vulnerable symfony/http-kernel version before it ships.
For deeper secret handling, read CI/CD secrets management best practices and secrets scanning in Git with Gitleaks. Official GitLab docs on application security scanning list every template variable you can tune.
Which security checks should run at each CI/CD stage?
Not every scan belongs in every stage. Fast checks run on every push. Slow DAST scans run nightly or on release branches. Match scan cost to feedback speed.
| Stage | Check type | Tool examples | Typical fail policy |
|---|---|---|---|
| Pre-commit / MR | Secrets detection | Gitleaks, GitLab Secret Detection | Block merge on any finding |
| Validate | Lint + static rules | PHPStan, Larastan, ESLint | Block on error level |
| Test | Security unit tests | Pest, custom auth tests | Block on failure |
| Security | SAST + SCA | GitLab SAST, composer audit | Block critical/high CVEs |
| Build | Container scan | Trivy, Grype | Block critical OS CVEs |
| Pre-deploy | Config audit | Custom script, php artisan about | Block if debug=true |
| Post-deploy | Runtime monitoring | fail2ban, log alerts | Alert, do not rollback auto |
Static Application Security Testing (SAST) reads source code without executing it. It catches patterns like hard-coded SQL concatenation. Software Composition Analysis (SCA) inspects composer.lock and package-lock.json for known CVEs.
On Laravel projects I add Larastan at level 5 or 6 before enabling stricter gates. Jumping straight to level 9 creates noise. Teams ignore noisy scanners. Tune thresholds first, then tighten.
Security tests belong beside feature tests
Laravel testing with Pest in CI/CD should include authorization cases. Test that a guest cannot download another user's document. Test that an admin route returns 403 for a client role.
// tests/Feature/DocumentAccessTest.php
it('forbids cross-tenant document download', function () {
$owner = User::factory()->create();
$intruder = User::factory()->create();
$document = Document::factory()->for($owner)->create();
$this->actingAs($intruder)
->get(route('documents.download', $document))
->assertForbidden();
});
These tests are not a replacement for SAST. They prove your business rules hold. SAST catches patterns your tests never thought to write.
How do you manage secrets and credentials in a DevSecOps pipeline?
Leaked API keys in Git history are the most common CI/CD security failure I see. A developer copies .env into a support ticket. A log prints DB_PASSWORD during debugging. Pipeline design must assume mistakes will happen.
Use GitLab masked and protected variables for production credentials. Scope variables to protected branches only. Never pass production secrets to feature-branch pipelines unless you enjoy surprise database wipes.
- Store secrets in CI variables or a vault—not in the repo.
- Run Gitleaks on every merge request and on the default branch.
- Rotate any key that ever appeared in Git, even after deletion.
- Redact secrets in job logs; GitLab masking helps but is not perfect.
- Audit self-hosted CI runner security if you use your own hardware.
For password generation during setup, point teammates to the password generator tool rather than reusing weak defaults. Production SSH keys deserve 4096-bit RSA or Ed25519. Store the private key only in CI variables.
The OWASP Top 10 remains the vocabulary for prioritising findings. Map SAST output to those categories so product owners understand severity without reading CVE JSON.
What are common DevSecOps mistakes on Laravel and PHP projects?
Teams adopt scanners and still ship insecure code. The tooling works. The workflow does not. These mistakes show up repeatedly on client projects and on my own maintenance stacks.
Running scans without merge-blocking rules
A green pipeline with ignored security artifacts is theatre. Configure branch protection so the security stage is required. In GitLab, enable "Pipelines must succeed" on the default branch.
Scanning vendor/ and drowning in false positives
Exclude vendor/, node_modules/, and compiled caches from SAST paths. You cannot fix Symfony core from your app repo. Focus on app/, routes/, and config/.
Skipping opcache and permission checks after deploy
Security does not end at CI. After Deployer swaps the release symlink, reload PHP-FPM so opcache picks up patched files. Verify storage/ and bootstrap/cache/ permissions. I cover server hardening in Ubuntu server security best practices and offer Linux system administration for teams that want hands-on help.
Treating WordPress and Laravel the same
WooCommerce 11.1 on WordPress 7.1 needs plugin vulnerability monitoring, not Larastan. Follow a WordPress security hardening checklist alongside CI scans. Magento 2.4.x shops need Adobe security patch workflows in the pipeline too.
Ignoring API and upload attack surfaces
REST endpoints need rate limiting, auth tests, and input validation reviews. File uploads need MIME checks and storage outside the web root. The API security complete checklist and file upload security guide pair well with pipeline SAST.
How do you measure whether shifting security left is working?
Executives ask for ROI. Engineers ask if the pipeline is faster or slower. Track a small set of metrics monthly. Do not boil the ocean.
- Mean time to remediate (MTTR): Hours from scan finding to merged fix.
- Critical findings in production: Should trend toward zero.
- False positive rate: If above 30%, tune rules or exclusions.
- Pipeline duration: Security stage should stay under 15% of total time.
- Repeat findings: Same CWE twice means missing lint rule or training gap.
SonarQube code quality and security gates and code coverage gates in CI add quality metrics beside security counts. Coverage alone does not prove security, but untested auth code is a red flag.
For containerised workloads, add image scans before registry push. Distroless images for security shrink the attack surface that Trivy must evaluate. Smaller images scan faster too.
Teams building new platforms often want a security-aware architecture from day one. That is where custom software development and enterprise application development engagements start—with CI/CD and security gates in the first sprint, not sprint twelve.
If you maintain legal-tech or eCommerce portals, pair pipeline security with support and maintenance so dependency updates land weekly. A green scan six months ago means nothing when composer.lock has drifted.
For regex-heavy validation rules in security tests, the regex tester saves time. For JSON webhook payloads in CI fixtures, use the JSON formatter to catch malformed test data before it hits the pipeline.
The NIST Secure Software Development Framework (SSDF) formalises many of these practices. You do not need NIST paperwork to start. You need one blocking security job this week.
Key Takeaways
- Add a dedicated security stage in CI/CD before deploy; block merges on critical SAST, SCA, and secrets findings.
- Run
composer audit, Gitleaks, and GitLab security templates on every merge request for Laravel 13 on PHP 8.3+. - Exclude
vendor/from SAST paths; write Pest authorization tests for business-critical access rules. - Store credentials in masked CI variables; rotate any secret ever committed to Git.
- Measure MTTR and production criticals monthly; tune noisy scanners instead of disabling them.
- Combine pipeline gates with server hardening—PHP-FPM reload, permissions, and fail2ban after Deployer releases.
People Also Ask
What is the difference between DevOps and DevSecOps?
DevOps automates build, test, and deploy. DevSecOps adds automated security checks into that same pipeline. Security is not a separate team gate at the end. Every merge request gets scanned.
When should you shift security left in CI/CD?
From the first pipeline you create. Adding scans later is harder because teams resist new merge blockers. Start with secrets detection and dependency audit—they are fast and high value.
Can small teams afford DevSecOps tooling?
Yes. GitLab security templates, Composer audit, Gitleaks, and PHPStan are free. Cost is pipeline minutes, not licence fees. A single prevented credential leak pays for months of CI runtime.
Does DevSecOps replace manual penetration testing?
No. Pipeline scans catch known patterns and CVEs. Pen tests find logic flaws and chained exploits. Run automated gates on every commit; schedule manual tests before major releases or after large architecture changes.
Build security into your pipeline before the next incident
DevSecOps: Shift Security Left in CI/CD is the cheapest insurance a Laravel or WordPress team can buy. Automated gates catch secrets, CVEs, and unsafe patterns while the author still has context. Production firefighting is avoidable.
Start with one merge-blocking security job this week. Expand stages as false positives drop. If you want help wiring GitLab CI, Deployer 7, and server hardening on Ubuntu 24, review the Notary Kathmandu portfolio case or read more on the blog. For hands-on pipeline design, contact us or learn more about my DevOps work since 2010.
Frequently Asked Questions
0 Comments
Leave a comment
Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

