GitHub Action for CI/CD Pentesting
Why CI/CD Security Testing Matters
Traditional penetration testing happens periodically - quarterly, annually, or before a major release. But modern development teams push code to production multiple times per day. A vulnerability introduced on Monday morning could be exploited long before a quarterly pentest discovers it.
CI/CD-integrated pentesting closes this gap. By triggering a pentest on every deployment (or every merge to a protected branch), you ensure that no code reaches production without a security assessment.
The TurboPentest GitHub Action
TurboPentest provides an official GitHub Action (integsec/turbopentest-action) that can be added to any GitHub Actions workflow. It authenticates with your TurboPentest API key, launches a pentest against the specified target, and can optionally wait for the result, fail the step if the pentest fails, or fail when findings meet a severity threshold via fail-on.
Basic Workflow Configuration
A minimal workflow file (.github/workflows/pentest.yml) looks like this:
name: Security Pentest
on:
push:
branches: [main]
deployment_status:
jobs:
pentest:
runs-on: ubuntu-latest
if: github.event.deployment_status.state == 'success' || github.event_name == 'push'
steps:
- name: Run TurboPentest
uses: integsec/turbopentest-action@v1
with:
api-key: ${{ secrets.TURBOPENTEST_API_KEY }}
target-url: "https://staging.example.com"
wait-for-results: true
fail-on: highConfiguration Parameters
The action accepts the following inputs:
- api-key (required): Your TurboPentest API key, stored as a GitHub secret
- target-url (required): The URL to pentest. This should point to a staging or preview environment, never production during active user traffic. The domain must be verified in your TurboPentest account.
- repo-url (optional): A GitHub repository URL to enable white-box pentesting (Secret Scanner, Code Scanner, and Dep Scanner run against the source)
- wait-for-results (optional, default
false): Whether the action should poll until the pentest completes (every 30 seconds, up to 2 hours) before continuing. The step fails if the pentest fails. - fail-on (optional, default empty): Fail the workflow when any finding severity meets or exceeds this threshold (
critical,high, ormedium). Empty,off, ornonemeans report-only (exit 0). Severity order is critical > high > medium > low > info, sofail-on: highfails on high or critical. Requireswait-for-results: true(the action errors iffail-onis set without waiting). - api-base-url (optional, default
https://turbopentest.com): Override for testing against a non-production API
The pentest tier is determined by the credit consumed: the API uses your oldest available credit, so keep credits of the tier you want (or launch via the API directly with the tier field for explicit control).
Triggering on Deployment
The most effective pattern triggers the pentest after a successful deployment to a staging environment. This way, the pentest runs against the actual deployed application (not just the code), and deployment failures do not waste pentest credits.
on:
deployment_status:
jobs:
pentest:
if: github.event.deployment_status.state == 'success'For preview environments (Vercel, Netlify, etc.), the deployment URL is available as github.event.deployment_status.target_url:
with:
target-url: ${{ github.event.deployment_status.target_url }}Gating Deployments
With wait-for-results: true, the step fails when the pentest itself fails, which blocks any subsequent steps. To also gate promotion on finding severity, set fail-on to critical, high, or medium. When the pentest completes, the action fetches findings from GET /api/pentests/{id} and exits non-zero (with a ::error:: summary) if any finding meets or exceeds that threshold.
- name: Run TurboPentest
id: pentest
uses: integsec/turbopentest-action@v1
with:
api-key: ${{ secrets.TURBOPENTEST_API_KEY }}
target-url: ${{ env.STAGING_URL }}
wait-for-results: true
fail-on: high
- name: Promote to Production
if: success()
run: ./deploy-production.shIf any high or critical vulnerabilities are found, the action fails and the promotion step is skipped. The pentest URL is printed in the action output for immediate review. fail-on without wait-for-results: true is rejected so misconfigured workflows fail fast instead of silently shipping.
Action Outputs
The action provides outputs for use in subsequent steps:
- pentest-id: The unique identifier for referencing via API
- pentest-url: Direct link to the pentest results in TurboPentest
- status: The final pentest status when
wait-for-resultsis true (complete,failed, ortimeout)
Best Practices
Use staging environments. Never pentest production during peak traffic. The action works best against staging or preview deployments that mirror production configuration.
Store API keys as secrets. Never hardcode your TurboPentest API key in the workflow file. Use GitHub's encrypted secrets feature.
Choose the right tier. Use recon credits for fast feedback on every PR. Use standard or deep for merges to main. Reserve blitz for release candidates.
Set appropriate thresholds. Start by gating only on critical findings and tighten to high as your team remediates existing findings.
Combine with source analysis. Pass repo-url to enable the white-box tools (Secret Scanner, Code Scanner, Dep Scanner) alongside the dynamic pentest, giving you both runtime and code-level coverage.
Course 6: Integration & Automation
Learn how to embed TurboPentest into your development workflows with CI/CD pipelines, AI-assistant integrations, notification systems, REST APIs, and scheduled pentesting.
MCP Server for AI-Assistant-Driven Pentesting
Learn how to use TurboPentest's MCP Server to launch and manage pentests directly from AI-powered code editors and assistants.