GitHub Action v1 MIT License

Penetrify GitHub Action

AI-driven autonomous penetration testing in your CI/CD pipeline. Scan your application for real-world vulnerabilities and report findings directly in GitHub's Security tab — in minutes, not days.

Penetrify covers SQL injection, XSS, authentication flaws, broken access control, API security issues, and more. No agents to install. No configuration files required to get started.

Quick start

Add this step to any GitHub Actions workflow. Results appear in Security → Code scanning within minutes.

Minimal setup

Two inputs required: your API key and target URL.

# .github/workflows/security.yml
- name: Run Penetrify Scan
  uses: penetrify/penetrify-action@v1
  with:
    api-key: ${{ secrets.PENETRIFY_API_KEY }}
    target: 'https://staging.your-app.com'
  1. Sign up at app.penetrify.cloud and create an API key under Settings → API Keys.
  2. Add the key as a GitHub Secret: Settings → Secrets and variables → Actions → New secret. Name it PENETRIFY_API_KEY.
  3. Add the workflow step above to your pipeline.
  4. Push — findings appear in your repository's Security → Code scanning tab.
💡

The action requires permissions: security-events: write on your job to upload SARIF results to GitHub. See the full example below.

How it works

The action integrates Penetrify's AI scanning engine into your workflow in four steps:

  1. Triggers a scan against your target URL via the Penetrify API using your API key.
  2. Polls for results until the scan completes or the configured timeout is reached.
  3. Generates a SARIF report from the findings and uploads it to GitHub Code Scanning.
  4. Fails the build if any finding meets or exceeds your configured severity-threshold.

Scans run entirely on Penetrify's infrastructure — your workflow runner only needs outbound HTTPS access to the Penetrify API. Nothing is installed on your application's servers.

Inputs

Input Required Default Description
api-key ✅ Yes Your Penetrify API key. Always store as a GitHub Secret — never hardcode.
target ✅ Yes Full URL of the application to scan. Must be reachable from Penetrify's scanners.
scan-type ❌ No full Scan depth: full, quick, api, or web. Use quick on PRs for faster feedback.
severity-threshold ❌ No high Fail the build when a finding at this severity or above is detected. Options: critical, high, medium, low.
wait-for-results ❌ No true Wait for scan completion. Set to false for fire-and-forget — the action exits immediately after triggering the scan.
timeout ❌ No 1800 Maximum seconds to wait for scan completion. Scans exceeding this are marked timeout.
upload-sarif ❌ No true Upload SARIF results to GitHub Code Scanning. Requires security-events: write permission.
config-file ❌ No Path to a Penetrify JSON config file in your repository for advanced scan configuration.

Outputs

Access outputs in subsequent steps via ${{ steps.<step-id>.outputs.<name> }}.

scan-id
Unique identifier for the scan. Use to retrieve results later via the API.
status
Final scan status: completed, failed, or timeout.
findings-count
Total number of findings across all severity levels.
critical-count
Number of critical severity findings.
high-count
Number of high severity findings.
report-url
Direct link to the full report on penetrify.cloud.
sarif-file
Filesystem path to the generated SARIF file on the runner.
Using outputs in a subsequent step
- name: Run Penetrify Scan
  id: penetrify
  uses: penetrify/penetrify-action@v1
  with:
    api-key: ${{ secrets.PENETRIFY_API_KEY }}
    target: 'https://staging.myapp.com'

- name: Post scan summary
  run: |
    echo "Scan ID: ${{ steps.penetrify.outputs.scan-id }}"
    echo "Findings: ${{ steps.penetrify.outputs.findings-count }}"
    echo "Critical: ${{ steps.penetrify.outputs.critical-count }}"
    echo "Report: ${{ steps.penetrify.outputs.report-url }}"

Severity levels

The severity-threshold input controls when the action fails the build. Setting it to a level will fail on that level and above.

LevelFails build when…Recommended for
critical Only critical findings present PR checks — keep the bar high to avoid blocking merges
high High or critical findings present Default — good balance for production deploys
medium Medium, high, or critical findings present Scheduled audits or compliance-sensitive applications
low Any finding present Maximum strictness — use with care

Examples

Scan on push to main common

Full scan triggered on every push to the main branch. Fails the build if high or critical vulnerabilities are found.

.github/workflows/security.yml
name: Security Scan
on:
  push:
    branches: [main]

jobs:
  scan:
    runs-on: ubuntu-latest
    permissions:
      security-events: write
      contents: read
    steps:
      - uses: actions/checkout@v4
      - uses: penetrify/penetrify-action@v1
        with:
          api-key: ${{ secrets.PENETRIFY_API_KEY }}
          target: 'https://staging.myapp.com'
          severity-threshold: 'high'
Quick scan on pull requests common

A lighter quick scan runs on every PR targeting main. Only fails on critical findings so development isn't unnecessarily blocked.

.github/workflows/pr-security.yml
name: PR Security Check
on:
  pull_request:
    branches: [main]

jobs:
  quick-scan:
    runs-on: ubuntu-latest
    permissions:
      security-events: write
      contents: read
    steps:
      - uses: actions/checkout@v4
      - uses: penetrify/penetrify-action@v1
        with:
          api-key: ${{ secrets.PENETRIFY_API_KEY }}
          target: 'https://preview-${{ github.event.pull_request.number }}.myapp.com'
          scan-type: 'quick'
          severity-threshold: 'critical'
Scheduled weekly audit scheduled

A full scan runs every Monday at 06:00 UTC against production. Extends the timeout to 60 minutes for deep scanning.

.github/workflows/weekly-audit.yml
name: Weekly Security Audit
on:
  schedule:
    - cron: '0 6 * * 1'

jobs:
  audit:
    runs-on: ubuntu-latest
    permissions:
      security-events: write
      contents: read
    steps:
      - uses: actions/checkout@v4
      - uses: penetrify/penetrify-action@v1
        with:
          api-key: ${{ secrets.PENETRIFY_API_KEY }}
          target: 'https://app.mycompany.com'
          scan-type: 'full'
          severity-threshold: 'medium'
          timeout: '3600'
Fire-and-forget (async) async

Triggers a scan without waiting for results. Useful in deployment pipelines where you don't want to block on scan time but still want a scan to run.

Async step
- uses: penetrify/penetrify-action@v1
  with:
    api-key: ${{ secrets.PENETRIFY_API_KEY }}
    target: 'https://staging.myapp.com'
    wait-for-results: false
ℹ️

In fire-and-forget mode, upload-sarif is automatically disabled and the build will not fail on findings. Check your Penetrify dashboard for results.

GitHub Security integration

When upload-sarif is enabled (default), findings are uploaded in SARIF format and appear natively throughout GitHub:

FeatureWhat you get
Security → Code scanning alerts Browse, filter, and manage all findings. Dismiss false positives, add notes, track fix status.
Pull request annotations New vulnerabilities introduced by a PR appear inline in the files changed view.
PR check status The PR status check reflects the build pass/fail based on your severity-threshold.
Alert management Assign findings to team members, link to issues, and track resolution over time.
⚠️

Required permission: Your workflow job must declare permissions: security-events: write for SARIF upload to succeed. Without it, the upload step will fail with a 403 error.

API key setup

  1. Sign up or log in at app.penetrify.cloud.
  2. Navigate to Settings → API Keys and create a new key. Give it a descriptive name like github-actions.
  3. Copy the key immediately — it won't be shown again.
  4. In your GitHub repository, go to Settings → Secrets and variables → Actions → New repository secret.
  5. Name the secret PENETRIFY_API_KEY and paste your key as the value.
💡

For organization-wide usage, add the secret at the organization level and share it across repositories via Settings → Secrets → Actions at the org level.

Troubleshooting

SARIF upload fails with 403

Add permissions: security-events: write to your job definition. See the basic example.

Scan times out

Increase the timeout input (default: 1800 seconds). For large applications with many endpoints, full scans can take 30–60 minutes. Alternatively, use scan-type: quick for faster results.

Target is not reachable

Penetrify's scanners connect to your target over the public internet. Ensure your staging environment is publicly accessible during the scan, or use a tunnel/VPN if your environment is private. IP allowlisting for Penetrify's scanner IPs is available on the Enterprise plan.

Build fails on false positives

Dismiss findings in the GitHub Security tab — dismissed findings do not count toward the threshold on subsequent scans. You can also raise the severity-threshold or use a config-file to exclude specific paths or checks.

Invalid API key error

Verify the secret name matches exactly: PENETRIFY_API_KEY. Check the key is still active in Settings → API Keys on penetrify.cloud. Keys can be rotated from the dashboard at any time.

Still stuck?

Open an issue on GitHub or email support@penetrify.cloud.