Security10 min read

How to Add a Security Gate to Your CI/CD Pipeline

A CI/CD security gate blocks vulnerable code from reaching production. Learn how to implement one in GitHub Actions using DeployReady, Semgrep, and secrets scanning.

Adding a security gate to your CI/CD pipeline is the difference between finding vulnerabilities before deployment and finding them after a breach. A security gate is a checkpoint in your pipeline that evaluates your code against a set of automated security checks—secrets scanning, static analysis, dependency audits, application-layer readiness checks—and blocks the deployment if critical findings are present. Without one, every push to production is a security roll of the dice: you are hoping the last commit did not introduce a hardcoded API key, a dependency with a known critical CVE, or an authorization gap that your functional tests never exercise.

Most engineering teams already have testing gates. They block on failing unit tests, type errors, and linting violations. Security gates follow exactly the same pattern but target a different failure class: code that works correctly but is exploitable. The two categories of failure rarely overlap. A function can pass every unit test and still return another user's data to an attacker who knows which parameter to change. Security automation catches what correctness tests miss—and it catches it on every commit, not periodically in a manual review cycle.

This guide covers what to include in a security gate, how to implement one in GitHub Actions, how to integrate DeployReady as the application-layer check, and how to tune severity thresholds so the gate catches real vulnerabilities without blocking on noise. If you are auditing an AI-generated or vibe-coded application, the guide on vibe coding security risks in the enterprise covers the specific vulnerability patterns those apps introduce that a security gate must catch.

What Is a CI/CD Security Gate?

A security gate is a required status check in your CI/CD pipeline that runs automated security analysis against each commit or pull request and returns a pass or fail verdict. When the check fails, the pipeline stops: the deployment does not proceed to staging or production until the finding is addressed. When it passes, the deployment continues with the confidence that the commit did not introduce the vulnerability classes the gate covers.

Gates operate at different severity thresholds. A well-configured gate blocks on critical findings—any detected credential in code, any dependency with a known actively exploited CVE, any application readiness score below your minimum threshold—and warns on high and medium severity findings without blocking. This distinction matters for adoption: a gate that blocks on every low-severity finding creates friction that leads developers to disable it or add bypass flags. A gate that blocks only on genuinely dangerous findings earns trust because every block it triggers is a real problem worth fixing before the code ships.

  • →Block on: any credential or secret detected in source code or git history; any dependency with a critical CVE (CVSS 9+) in the production dependency tree; any SAST finding classified critical under OWASP Top 10 mapping; any application readiness score below configured threshold.
  • →Warn on (do not block): high severity dependency CVEs where your usage pattern is not in the vulnerable code path; medium-severity SAST findings without a clear exploit path; missing security headers on non-production environments.
  • →Log only: low severity linting-style findings; informational notes about outdated dependency versions with no known CVE; stylistic code patterns that are not exploitable in your deployment context.

Which Security Checks to Automate in Your Pipeline

A complete security gate covers four distinct check categories. Each targets a different failure mode; none is a substitute for the others. Running only SAST, for example, will catch injection patterns in your code but miss a hardcoded Stripe secret key in a utility file. Running only secrets scanning will catch the credential exposure but miss the SQL injection path. The four categories together cover the vulnerability classes that appear on every enterprise security questionnaire and in every OWASP Top 10 assessment.

  • →Secrets scanning: detects credential values, API keys, tokens, and private keys committed to source code or present in environment files that are checked in. Tools: gitleaks, trufflehog, or the GitHub secret scanning native integration on public repositories. Configuration: scan the full git history on first run, then only new commits on subsequent runs. Block on any detection—a detected secret is always a critical finding regardless of CVSS.
  • →Static application security testing (SAST): analyzes source code for vulnerability patterns without executing it. Covers SQL injection, command injection, path traversal, hardcoded credentials in logic, insecure deserialization, broken access control patterns, and similar classes. Tools: Semgrep with the p/security-audit ruleset (open source, language-agnostic, runs in seconds for most codebases), CodeQL for deeper analysis on larger projects, Bandit for Python. Block on OWASP Top 10 critical findings.
  • →Software composition analysis (SCA): audits your dependency tree for known CVEs. npm audit, pip-audit, Dependabot, Snyk, and OWASP Dependency-Check all serve this purpose. Block on critical CVEs for dependencies in your production dependency tree. Dev-only dependencies with CVEs are worth warning on but rarely justify a deployment block on their own.
  • →Application-layer readiness checks: verifies that your deployed application returns correct security headers, that environment variable handling is not leaking secrets into client-side JavaScript bundles, that database access rules (Supabase RLS, Firebase security rules) are not disabled, and that authentication endpoints respond correctly to bypass attempts. This is where DeployReady fits—static language analysis tools cannot check a running application's security headers or verify that your Supabase tables have RLS enabled in your actual database.

How to Implement a Security Gate in GitHub Actions

GitHub Actions security gates are implemented as required status checks on branch protection rules. The gate runs as a workflow on every pull request targeting main (or your production branch), and the branch protection rule prevents merging until the check passes. This architecture has one critical property: the gate cannot be bypassed by a commit message flag or a developer-side workaround, because the check is enforced at the repository server level, not in the workflow itself.

A practical security gate workflow runs the checks in sequence: secrets scan first (fastest, highest severity if it fails), then SAST, then SCA, then application-layer checks. Each step fails fast if a blocking finding is detected. This keeps the gate fast for clean commits and informative when something is wrong—the failure message names the check that blocked and what it found, giving the developer a specific fix target rather than a generic security failure.

  • →Create a workflow file at .github/workflows/security-gate.yml. Set the trigger to pull_request with branches: [main] and to push with branches: [main]. This ensures the gate runs on both PRs and direct pushes to main.
  • →Add a secrets-scan job using gitleaks with the --no-git flag for a full history scan on initial setup, then switch to scanning only the diff (--diff flag) for subsequent runs to keep the check fast. Exit code 1 from gitleaks means a credential was detected—fail the job and surface the finding.
  • →Add a SAST job using Semgrep with the p/security-audit ruleset. Set --error to fail the job on any finding at severity ERROR or WARNING in the security-audit ruleset. Add p/owasp-top-ten for explicit OWASP Top 10 mapping if your team is preparing for a compliance audit or enterprise security questionnaire.
  • →Add an SCA job using npm audit --audit-level=critical (or pip-audit --severity critical for Python projects). This exits non-zero only on critical CVEs in your production dependencies, which is the threshold that justifies blocking a deploy rather than opening a ticket.
  • →Set the security-gate workflow as a required status check in your repository under Settings > Branches > Branch protection rules > Require status checks to pass before merging. This is the enforcement step without which the gate is advisory only.

Running DeployReady as Your Application-Layer Security Gate

SAST and secrets scanning operate on your source code. They cannot check whether your deployed application returns a Content-Security-Policy header, whether your Supabase tables have Row Level Security enabled in production, or whether your authentication endpoints are bypassed by common techniques. That layer of verification requires a tool that checks the running application—or performs static analysis specifically designed for web application security posture. DeployReady is Belsoft's open-source CLI that covers this layer: 30+ checks covering OWASP Top 10 patterns, Supabase RLS configuration, Firebase security rules, exposed secrets in environment variable handling, missing security headers, and auth bypass patterns. It is MIT-licensed, free on npm, and runs entirely locally—no data leaves your environment and no account is required.

  • →Add a deployready job to your security gate workflow. The step is: run npx deployready --ci from your project root. In CI mode, DeployReady outputs structured findings and exits with code 1 if the readiness score falls below the configured threshold or any critical finding is detected.
  • →Set a minimum score threshold that reflects your deployment context. For applications handling user data, a score of 70 is a reasonable minimum for staging and 85 for production. For applications undergoing an enterprise security review, the threshold should match your review criteria—most enterprise security questionnaires have an equivalent of a 90+ requirement.
  • →DeployReady's Supabase RLS check is particularly valuable as a CI gate for teams using AI-generated code. Vibe coding tools generate migration files that create tables without consistently adding RLS policies. This check catches a table with RLS disabled before it reaches production—a finding that would otherwise require a manual database schema review to detect after the migration has already run.
  • →The readiness score gives you a trend line across deployments. If the score drops between commits, the new commit introduced a finding. This is a faster feedback loop than waiting for a manual security review or an enterprise buyer's security questionnaire to surface the gap.

Security Gates for Vibe-Coded and AI-Generated Applications

Teams building with Lovable, Bolt, Cursor, v0, or Replit have a heightened need for CI security gates because AI-generated code introduces vulnerability patterns at higher rates than hand-written code. A 2026 audit of over 5,600 vibe-coded applications found that 71% had at least one critical vulnerability. Veracode's 2025 GenAI report found that approximately 45% of AI-generated code samples introduced an OWASP Top 10 weakness. These numbers reflect a consistent pattern: AI tools generate code that is functionally correct but not security-reviewed, and the developer workflow that accepts AI output does not naturally include a security checkpoint. The SaaS pre-launch security checklist covers the full manual review; the CI security gate is the automated layer that catches regressions on every subsequent commit after launch.

  • →Secrets in generated code: AI tools occasionally place API keys directly in client-accessible environment variables (NEXT_PUBLIC_ or VITE_ prefixed) that land in the JavaScript bundle, or generate configuration files with real credential values copied from the developer's conversation context. A secrets-scanning gate with full git history scan on first run catches these before they reach production.
  • →Missing Supabase RLS: AI tools generate database migration files that create tables without RLS policies. The table is created, functional tests pass, and the deployment proceeds—with every row in that table visible to any authenticated user. A DeployReady gate catches this before the migration runs in production.
  • →IDOR in generated API routes: AI tools generate CRUD endpoints that check authentication (is the user logged in?) but not authorization (does the user own this specific record?). Semgrep with the p/security-audit ruleset catches some IDOR patterns in common frameworks; a DeployReady check tests the running endpoints for the most common bypass techniques.
  • →Hardcoded credentials in test utilities: AI tools frequently generate test scaffolding with real-looking credential values as placeholders. Even placeholder-formatted strings can match secrets-scanning patterns—and occasionally they are real values copied from the developer's environment. A secrets-scan gate catches both cases.

Tuning Your Gates to Avoid Alert Fatigue

The most common reason security gates get disabled is not that they are technically difficult—it is that they block on too many things, too many of which turn out to be false positives or low-risk findings. A gate that cries wolf on every commit trains developers to treat all gate failures as noise, which means the real critical finding gets dismissed along with the spurious ones. Gate tuning is as important as gate configuration.

  • →Measure your false-positive rate for the first two weeks after enabling the gate. Track the ratio of blocking findings that the team overrides or marks as accepted risk versus findings that result in real code changes. A false-positive rate above 20% means your thresholds are too aggressive and need adjustment.
  • →Use allow-lists for known-safe patterns: Semgrep and gitleaks both support ignore rules for specific file paths, function names, or string patterns that your codebase uses in a known-safe way. A test file that constructs SQL for unit testing does not need to trigger an injection finding. Add a path-scoped ignore rather than raising the global severity threshold.
  • →Separate gate jobs by latency: run secrets scanning and npm audit in one fast job (typically under 30 seconds for most projects) and SAST and DeployReady in a second parallel job. PRs get the fast security signal immediately and the full analysis completes while the developer reviews other feedback.
  • →Track override counts: every time a developer bypasses the gate via a manual exception or workflow dispatch, log it. If override rates are rising, the gate is generating noise that is undermining trust. Address the noise source rather than making exceptions easier to get.

Common Mistakes Teams Make With CI/CD Security Gates

Teams that implement security gates for the first time make predictable configuration mistakes that either make the gate ineffective or make it painful enough that it gets disabled. These are the patterns that come up in almost every security review of a team that claims to have a security gate already in place.

  • →Alert-only mode from day one: running security checks with continue-on-error: true or --warn-only flags means the pipeline surfaces findings but never blocks a deployment. The gate produces a report nobody reads and nothing changes. Gates need to be enforced—block on critical findings from the first deployment, not from some future date after a backlog of findings is cleared.
  • →Only scanning new code, not git history: secrets scanning that runs only on the current diff misses credentials committed months ago that are still in the repository's history. Run a full history scan on the repository before enabling the incremental gate. A secret committed six months ago is as dangerous as one committed today—the credential is still active and exposed.
  • →No branch protection enforcement: a CI check that blocks a workflow but is not set as a required status check can be bypassed by pushing directly to main. The check only protects pull requests. For the gate to be meaningful, it must be a required status check that the repository server enforces—not just a workflow that runs and might fail.
  • →Skipping the application layer: teams that implement SAST and SCA but skip application-layer checks have a gate that covers source code but not what ships. Static analysis tools cannot verify that your Supabase tables have RLS enabled in production or that your deployed app returns the correct security headers.
  • →Single severity threshold across all check types: a critical CVE in a dependency your code actively calls in production is different from a medium-severity SAST finding in a utility function that is never reached. Using one threshold for everything leads to either blocking on noise or not blocking on real issues. Configure per-check thresholds that reflect actual exploitability.

Frequently Asked Questions

What is a security gate in a CI/CD pipeline?

A security gate is a required status check that runs automated security analysis—secrets scanning, SAST, dependency audits, and application-layer checks—against each commit and blocks deployment if critical findings are detected. It is the automated equivalent of a security reviewer catching a problem before it reaches production: the same intent, running automatically on every commit instead of periodically in manual review cycles.

How do you block deployments that have security vulnerabilities?

In GitHub Actions, configure the security checks as jobs that exit with a non-zero exit code on blocking findings, then add the workflow as a required status check under Settings > Branches > Branch protection rules. When the check fails, GitHub prevents merging and blocks the deployment workflow from proceeding. The key is the branch protection rule: a workflow that fails but is not marked as required can be bypassed by pushing directly to main. The required status check enforces the gate at the server level where it cannot be ignored.

What security checks should run before every deploy?

At minimum: secrets scanning (gitleaks or trufflehog covering the full git history on first run, then diffs on subsequent runs), dependency vulnerability scanning (npm audit --audit-level=critical or equivalent for your stack), and an application-layer readiness check (DeployReady). SAST with Semgrep using the security-audit ruleset adds coverage for injection patterns and broken access control. Container image scanning applies if your deployment targets Docker or Kubernetes. Block on critical findings across all categories and warn on high severity without blocking.

How do you add DeployReady to a CI/CD pipeline?

Add a step to your GitHub Actions workflow: run npx deployready --ci from your project root. DeployReady is MIT-licensed, free on npm, and requires no account or API key. In CI mode it outputs structured findings and exits with code 1 if the readiness score falls below threshold or a critical finding is detected. Set the job as a required status check in your branch protection rules. The full documentation and source code are at deployready.dev.

How often should you run a security gate?

On every pull request and every push to main—not on a schedule. The value of a security gate is that it catches a vulnerability in the commit that introduced it, before that commit reaches a wider audience. A weekly or daily schedule catches the same finding days later, after the code may already be in staging or production, and after the developer has context-switched away from the change that caused it. Trigger-based gates also run only when there is new code to check, which is more efficient than scheduled scans of unchanged code.

How Belsoft Helps Teams Ship Securely

A CI security gate catches the deterministic findings—credentials in code, known-CVE dependencies, missing headers, disabled RLS—automatically on every commit. It does not replace a security engineer reviewing your authentication logic, testing your API endpoints for broken object-level authorization, or red-teaming your AI features. Those checks require judgment that static analysis tools cannot replicate. Our security and scalability audit is the manual review layer that covers what the gate cannot: broken access control in your API routes, privilege escalation paths in admin flows, missing rate limiting on authentication endpoints, and AI feature attack surfaces that require adversarial testing rather than pattern matching.

The practical split for most teams: implement the CI gate first to establish a security baseline and prevent regression, then engage a Belsoft audit to surface the authorization and business-logic vulnerabilities the automated tools cannot catch. The gate output gives our engineers a starting point—we can skip the deterministic findings the automated tools already cover and focus the manual review hours where they add the most signal. For teams running on cloud infrastructure managed as code, DeployReady integrates as a CI gate on every Belsoft-managed project, running automatically alongside your other required checks. If you want to understand where your application stands before an enterprise deal or a first enterprise security review, book a scoping call and we will walk through your stack against a typical enterprise buyer security questionnaire.

“A security gate does not make your application secure. It makes security regression visible on every commit—which is the prerequisite for everything else.”

Written by

Marco Silva

Security Engineer, Belsoft Solutions

Ready to partner?

Let's talk about your company.

30 minutes. No pitch. We talk through how you run today and where AI and automation would help.

Book a free audit
logo

Your AI & automation transformation partner: we audit, build, and train your team, then stay embedded as you grow.

Member ofNVIDIA Inception Program

Copyright Ⓒ 2026 BelSoft. All Rights Reserved.

BELSOFT, LDA · NIPC 517893258 · Lisbon, Portugal