Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

DevSecOps: Shift Security Left in CI/CD

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.

Shift Security Left in CI/CDTraditionalSecurity at releaseManual pen testLate, expensive fixesDevSecOpsScan every commitBlock bad mergesDeploy only clean buildsProduction incidentStable releaseSame team owns code, tests, security gates, and deploy
DevSecOps shift security left in CI/CD moves vulnerability detection from post-release firefighting to automated pre-merge gates.

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.

DevSecOps Pipeline StagesValidateLint, syntaxTestPest, PHPUnitSecuritySAST, secretsBuildAssets, cacheDeployDeployer 7Merge blocked if security stage failsDeveloper fixes finding, pushes againNo manual security sign-off needed
A DevSecOps CI/CD pipeline inserts a dedicated security stage between tests and deploy so vulnerable builds never reach production.

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.

StageCheck typeTool examplesTypical fail policy
Pre-commit / MRSecrets detectionGitleaks, GitLab Secret DetectionBlock merge on any finding
ValidateLint + static rulesPHPStan, Larastan, ESLintBlock on error level
TestSecurity unit testsPest, custom auth testsBlock on failure
SecuritySAST + SCAGitLab SAST, composer auditBlock critical/high CVEs
BuildContainer scanTrivy, GrypeBlock critical OS CVEs
Pre-deployConfig auditCustom script, php artisan aboutBlock if debug=true
Post-deployRuntime monitoringfail2ban, log alertsAlert, 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.

  1. Store secrets in CI variables or a vault—not in the repo.
  2. Run Gitleaks on every merge request and on the default branch.
  3. Rotate any key that ever appeared in Git, even after deletion.
  4. Redact secrets in job logs; GitLab masking helps but is not perfect.
  5. 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.

Security Shift Left OutcomesReactive securityFix cost: highDowntime: likelyTrust loss: severeShift-left CI/CDFix cost: lowDowntime: rareTrust: preservedOWASP Top 10 risks caught in MR, not in prodReference: OWASP CI/CD Security RisksAutomate gates, measure MTTR drop
Shifting security left in CI/CD reduces fix cost and production downtime compared with reactive post-incident patching.

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.

Which Scan Do You Need?New merge requestCode changed?YesRun SASTPHPStan, GitLabDeps onlyRun SCAcomposer auditAlways: secrets scanGitleaks every push
DevSecOps scan selection: run SAST on code changes, dependency scans on lockfile updates, and secrets detection on every push.

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

DevSecOps treats security as a shared pipeline responsibility, not a quarterly audit deck. Shift left means running automated security checks during every commit and merge request, before Deployer touches production. On a Laravel GitLab CI pipeline, that looks like dependency scans, static analysis, and secrets detection blocking a bad build early. The payoff is fixing a SQL injection in a pull request in hours instead of firefighting after a law-firm portal leak.

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.

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.

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.

Start with a baseline pipeline that already runs Composer install, Pest tests, and asset checks. Include GitLab templates for SAST, Dependency-Scanning, and Secret-Detection. Add a dedicated security stage before deploy with composer audit and a Gitleaks job scoped to merge requests and the default branch. Set SAST_EXCLUDED_PATHS to vendor/, node_modules/, storage/, and bootstrap/cache/. If any security stage fails, the deploy job never runs. This mirrors the workflow I run before symlink swaps on production with Deployer 7.

Match scan cost to feedback speed. Run secrets detection with Gitleaks on every merge request and block on any finding. Run lint and static rules with PHPStan or Larastan during validate. Add Pest authorization tests during test. Run SAST and SCA with GitLab templates plus composer audit during security, blocking critical and high CVEs. Container scans with Trivy or Grype belong in build. Slow DAST scans run nightly or on release branches. Post-deploy, fail2ban and log alerts monitor runtime but alert rather than auto-rollback.

Static Application Security Testing reads source code without executing it and catches patterns like hard-coded SQL concatenation. Software Composition Analysis inspects composer.lock and package-lock.json for known CVEs. Composer 2.10 includes composer audit for 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. SAST is not a replacement for Pest authorization tests—it catches unsafe patterns your tests never thought to write.

Leaked API keys in Git history are the most common CI/CD security failure I see. Use GitLab masked and protected variables scoped to protected branches only. Never pass production secrets to feature-branch pipelines. Store secrets in CI variables, not the repo. Run Gitleaks on every merge request and 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. Production SSH keys should be 4096-bit RSA or Ed25519, stored only in CI variables.

No. Pipeline scans catch known patterns and CVEs. Pen tests find logic flaws and chained exploits that automated gates miss. Run automated gates on every commit and schedule manual penetration tests before major releases or after large architecture changes. On platforms with document uploads and payment flows, both layers matter. A green SAST scan does not prove an attacker cannot chain authorization bugs into a data leak.

Running scans without merge-blocking rules turns a green pipeline into theatre—enable branch protection so security stages are required. Scanning vendor/ drowns teams in false positives; exclude vendor/, node_modules/, and bootstrap/cache/ from SAST paths. Skipping PHP-FPM reload and permission checks after Deployer deploys leaves opcache serving old code. Treating WordPress and Laravel the same fails—WooCommerce 11.1 on WordPress 7.1 needs plugin vulnerability monitoring, not Larastan. Ignoring REST rate limiting, auth tests, and upload MIME checks misses attack surfaces pipeline SAST alone will not cover.

On Laravel projects I add Larastan at level 5 or 6 before enabling stricter gates. Jumping straight to level 9 creates noise and teams ignore noisy scanners. Exclude vendor/, node_modules/, storage/, and bootstrap/cache/ via SAST_EXCLUDED_PATHS. Tune thresholds first, then tighten. If your false positive rate exceeds 30%, adjust rules or exclusions rather than disabling scans. Scans over ten minutes get ignored—split heavy jobs and keep feedback short so developers actually fix findings.

Security tests belong beside feature tests, not as a replacement for SAST. Test that a guest cannot download another user's document. Test that an admin route returns 403 for a client role. Write authorization cases for business-critical access rules on legal-tech portals handling document uploads. These tests prove your business rules hold under real access patterns. SAST catches unsafe code patterns your tests never thought to write. Run them with php artisan test --parallel during the test stage before security scans gate the deploy.

Track a small set of metrics monthly. Mean time to remediate: hours from scan finding to merged fix. Critical findings in production should trend toward zero. False positive rate above 30% means tune rules, not disable scanners. Pipeline duration: keep the security stage under 15% of total time. Repeat findings for the same CWE signal a missing lint rule or training gap. Map SAST output to OWASP Top 10 categories so product owners understand severity without reading CVE JSON.

On production GitLab CI pipelines with Deployer 7, the deploy stage must depend on security completing green. If composer audit, Gitleaks, or SAST fails, Deployer never touches the server and vulnerable code never reaches production. This is the workflow I maintain on sister legal-tech sites on shared EC2 before symlink swaps. A dedicated security stage between tests and deploy moves vulnerability detection from post-release firefighting to automated pre-merge gates. Fixing issues while the author still has context costs hours, not clients and sleep.

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. Post-deploy runtime monitoring via fail2ban and log alerts catches issues build-time scanners miss. Pipeline gates block known CVEs, leaked secrets, and unsafe patterns. Server hardening on Ubuntu closes the gap between a green scan and a defensible production host. Combine both—automated pre-merge gates plus post-deploy hardening—not one or the other.

Share this article

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.

Quick Contact Options
Choose how you want to connect me: