https://github.com/waftester/waftester-action
GitHub Action for WAFtester — comprehensive WAF security testing in CI/CD pipelines
https://github.com/waftester/waftester-action
devsecops github-actions penetration-testing sarif sast security security-testing waf web-application-firewall
Last synced: 3 months ago
JSON representation
GitHub Action for WAFtester — comprehensive WAF security testing in CI/CD pipelines
- Host: GitHub
- URL: https://github.com/waftester/waftester-action
- Owner: waftester
- License: other
- Created: 2026-02-09T08:46:51.000Z (4 months ago)
- Default Branch: main
- Last Pushed: 2026-03-02T21:01:09.000Z (3 months ago)
- Last Synced: 2026-03-02T23:11:41.660Z (3 months ago)
- Topics: devsecops, github-actions, penetration-testing, sarif, sast, security, security-testing, waf, web-application-firewall
- Language: Shell
- Homepage: https://waftester.com
- Size: 126 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Codeowners: .github/CODEOWNERS
- Security: SECURITY.md
Awesome Lists containing this project
README
# WAFtester Action
Test, fingerprint, and bypass Web Application Firewalls
directly in your GitHub Actions workflows.
[](https://github.com/marketplace/actions/waftester-waf-security-testing)
[](https://waftester.com)
[](https://github.com/waftester/waftester/releases/tag/v2.9.40)
[](LICENSE)
[](https://github.com/waftester/waftester-action/actions/workflows/test-action.yml)
> **This action wraps the
> [WAFtester CLI](https://github.com/waftester/waftester)**
> — the most comprehensive WAF testing platform with 2,800+
> payloads, 197 vendor signatures, and 70+ tamper scripts.
> Results appear in the **Security → Code scanning** tab via
> SARIF integration.
---
## Quick Start
```yaml
permissions:
security-events: write # Required for SARIF upload to Security tab
steps:
- uses: waftester/waftester-action@v1
with:
target: https://app.example.com
```
That's it. The action downloads the binary, runs a scan,
generates a SARIF report, and uploads it to
**Security → Code scanning** automatically.
---
## What It Does
1. **Downloads** the WAFtester Go binary from the latest
[GitHub Release](https://github.com/waftester/waftester/releases).
2. **Verifies** the SHA-256 checksum of the downloaded archive.
3. **Runs** the selected scan type against your target URL.
4. **Generates** a SARIF report with ruleId, CWE, severity,
and location for every finding.
5. **Uploads** the SARIF file to GitHub Code Scanning
(Security tab) — configurable.
6. **Writes** a rich Markdown job summary with findings table,
status emoji, and collapsible remediation guidance.
7. **Sets outputs** (`exit-code`, `bypass-count`, `sarif-file`,
`summary`, `version`) for downstream steps.
Supported on **Linux**, **macOS**, and **Windows** runners
(x86_64 and ARM64).
---
## Usage Examples
### Basic Scan
```yaml
name: WAF Security Scan
on: [push, pull_request]
permissions:
security-events: write
jobs:
waf-scan:
runs-on: ubuntu-latest
steps:
- uses: waftester/waftester-action@v1
with:
target: https://app.example.com
```
### Full Autonomous Assessment
```yaml
- uses: waftester/waftester-action@v1
id: waf
with:
target: https://app.example.com
scan-type: auto
fail-on-bypass: true
- if: steps.waf.outputs.bypass-count != '0'
run: |
echo "::error::${{ steps.waf.outputs.bypass-count }} WAF bypasses found"
echo "${{ steps.waf.outputs.summary }}"
```
### WAF Vendor Detection
```yaml
- uses: waftester/waftester-action@v1
with:
target: https://app.example.com
scan-type: vendor
```
### Specific Attack Categories
```yaml
- uses: waftester/waftester-action@v1
with:
target: https://app.example.com
args: '-types sqli,xss,cmdi --smart'
```
### Bypass Discovery
```yaml
- uses: waftester/waftester-action@v1
with:
target: https://app.example.com
scan-type: bypass
args: '--smart --tamper-auto'
fail-on-bypass: true
```
### API Spec Scanning (v2.9.1)
Scan every endpoint defined in an OpenAPI, Swagger, Postman, HAR, AsyncAPI, gRPC, or GraphQL spec:
```yaml
# OpenAPI / Swagger
- uses: waftester/waftester-action@v1
with:
target: https://api.example.com
args: '--spec openapi.yaml'
# Postman Collection with environment
- uses: waftester/waftester-action@v1
with:
target: https://api.example.com
args: '--spec collection.postman_collection.json --env staging.postman_environment.json'
# HAR recording from DevTools
- uses: waftester/waftester-action@v1
with:
target: https://api.example.com
args: '--spec recording.har --intensity high'
# Dry-run to preview what would be scanned
- uses: waftester/waftester-action@v1
with:
target: https://api.example.com
args: '--spec openapi.yaml --dry-run'
```
### Scheduled Weekly Audit
```yaml
name: Weekly WAF Audit
on:
schedule:
- cron: '0 6 * * 1' # Every Monday 06:00 UTC
permissions:
security-events: write
jobs:
audit:
strategy:
matrix:
include:
- name: app
url: https://app.example.com
- name: api
url: https://api.example.com
runs-on: ubuntu-latest
steps:
- uses: waftester/waftester-action@v1
with:
target: ${{ matrix.url }}
scan-type: assess
sarif-category: 'waf-${{ matrix.name }}'
args: '-fp'
```
### PR Gate with Comment
```yaml
- uses: waftester/waftester-action@v1
id: waf
with:
target: https://staging.example.com
scan-type: auto
fail-on-bypass: true
- if: always() && github.event_name == 'pull_request'
uses: actions/github-script@v7
env:
BYPASS_COUNT: ${{ steps.waf.outputs.bypass-count }}
WAF_SUMMARY: ${{ steps.waf.outputs.summary }}
with:
script: |
const count = process.env.BYPASS_COUNT;
const summary = process.env.WAF_SUMMARY;
const status = count === '0' ? ':white_check_mark:' : ':red_circle:';
github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `## ${status} WAF Scan Results\n\n` +
`**Bypasses:** ${count}\n\n` +
summary
});
```
### JSON Output (No SARIF)
```yaml
- uses: waftester/waftester-action@v1
with:
target: https://app.example.com
format: json
output: results.json
upload-sarif: false
```
### Multi-Target Matrix
```yaml
jobs:
scan:
strategy:
fail-fast: false
matrix:
include:
- target: https://staging.example.com
env: staging
- target: https://prod.example.com
env: production
runs-on: ubuntu-latest
steps:
- uses: waftester/waftester-action@v1
with:
target: ${{ matrix.target }}
sarif-category: 'waf-${{ matrix.env }}'
```
### Informational Only (Never Fails)
```yaml
- uses: waftester/waftester-action@v1
with:
target: https://app.example.com
fail-on-bypass: false
fail-on-error: false
```
---
## Inputs
| Input | Description | Required | Default |
|-------|-------------|----------|---------|
| `target` | Target URL to scan | **Yes** | — |
| `scan-type` | Scan type (see table below) | No | `scan` |
| `version` | WAFtester version to install | No | `latest` |
| `format` | Output format (`sarif`, `json`, `jsonl`, `csv`, `md`, `html`, `pdf`). For JUnit/CycloneDX/SonarQube/GitLab SAST use `args` with dedicated export flags. | No | `sarif` |
| `output` | Output file path | No | `waftester-results.sarif` |
| `args` | Extra CLI flags (e.g., `--smart --tamper-auto -types sqli,xss`) | No | — |
| `fail-on-bypass` | Fail the step when bypasses are found (exit code 1) | No | `false` |
| `fail-on-error` | Fail the step on infrastructure errors (exit codes 2–6) | No | `true` |
| `upload-sarif` | Upload SARIF to GitHub Code Scanning (Security tab) | No | `true` |
| `sarif-category` | Category for SARIF upload — groups results in the Security tab | No | `waftester` |
| `token` | GitHub token for downloading releases and uploading SARIF. The default `GITHUB_TOKEN` is used for API rate limiting on release downloads and SARIF upload. Override with a PAT only if the WAFtester releases repository becomes private or restricted. | No | `${{ github.token }}` |
### Scan Types
| `scan-type` | CLI Command | Description |
|-------------|-------------|-------------|
| `scan` | `waf-tester scan` | Standard payload scan (default) |
| `auto` | `waf-tester auto` | Full autonomous assessment |
| `bypass` | `waf-tester bypass` | Bypass discovery with tampers |
| `assess` | `waf-tester assess` | Enterprise metrics (F1, MCC, FPR) |
| `vendor` | `waf-tester vendor` | WAF fingerprinting (197 signatures) |
| `discover` | `waf-tester discover` | Endpoint discovery & crawl |
| `fuzz` | `waf-tester fuzz` | Content/directory fuzzing |
| `nuclei` | `waf-tester template` | Nuclei-compatible template scan |
| `custom` | (from `args`) | Pass full command via `args` |
---
## Outputs
| Output | Description | Example |
|--------|-------------|---------|
| `exit-code` | WAFtester exit code (see table below) | `0` |
| `bypass-count` | Number of WAF bypasses found | `12` |
| `sarif-file` | Path to the generated SARIF file | `waftester-results.sarif` |
| `summary` | One-line human-readable summary | `WAFtester found 12 WAF bypass(es)...` |
| `version` | Installed WAFtester version | `2.9.40` |
---
## Exit Codes
The action preserves WAFtester's 7 semantic exit codes:
| Code | Meaning | `fail-on-bypass` | `fail-on-error` |
|------|---------|:-:|:-:|
| 0 | Clean — no issues found | Pass | Pass |
| 1 | Bypasses found | **Fail** (if true) | Pass |
| 2 | Too many errors (threshold exceeded) | Pass | **Fail** (if true) |
| 3 | Configuration error | Pass | **Fail** (if true) |
| 4 | Target unreachable | Pass | **Fail** (if true) |
| 5 | Interrupted (timeout/signal) | Pass | **Fail** (if true) |
| 6 | License violation | Pass | **Fail** (if true) |
By default, `fail-on-bypass` is `false` (informational) and
`fail-on-error` is `true` (fail on infra issues). Set both to
`true` for a strict quality gate.
---
## SARIF Integration
When `upload-sarif` is `true` (the default) and `format` is
`sarif`, the action automatically uploads results to
**GitHub Code Scanning** using
[`github/codeql-action/upload-sarif@v4`](https://github.com/github/codeql-action).
Results appear under **Security → Code scanning alerts** with:
- Rule IDs (e.g., `sqli-SQLI003`, `xss-XSS001`)
- CWE references (18 mapped categories)
- Severity levels (error, warning, note)
- Finding locations with request/response excerpts
- Fingerprints for deduplication across runs
### Requirements
- Repository must have **GitHub Advanced Security** enabled
(free for public repos; requires GHAS license for private).
- Workflow must declare `permissions: security-events: write`.
- SARIF file must be under **10 MB**. Large scans
(2,800+ payloads with full response bodies) may exceed
this limit. Mitigate by limiting payload types with
`-types sqli,xss` or using `--smart` mode.
### Authenticated Targets
For targets behind authentication, pass headers via `args`:
```yaml
- uses: waftester/waftester-action@v1
with:
target: https://app.example.com
args: '-H "Authorization: Bearer ${{ secrets.TARGET_TOKEN }}"'
```
> **Note:** Use repository secrets for credentials — never
> hardcode tokens in workflow files.
### Disabling SARIF Upload
```yaml
- uses: waftester/waftester-action@v1
with:
target: https://app.example.com
upload-sarif: false
```
### Without GitHub Code Scanning
SARIF upload requires
[GitHub Advanced Security](https://docs.github.com/en/get-started/learning-about-github/about-github-advanced-security)
(GHAS). Public repos get this free. Private repos need a
GHAS license — without it, SARIF upload silently fails.
**If your repo does NOT have Code Scanning enabled:**
```yaml
- uses: waftester/waftester-action@v1
with:
target: https://app.example.com
upload-sarif: false # disable SARIF upload
format: sarif # still generates the file
fail-on-bypass: true # fail the workflow on bypasses
```
Results are still available through:
- **Job Summary** — always written to the workflow run page
(visible under Actions → run → Summary)
- **SARIF artifact** — download the raw file for local review
or import into third-party tools
- **Output variables** — `exit-code`, `bypass-count`,
`summary` for use in downstream steps
To save the SARIF as a downloadable artifact:
```yaml
- uses: waftester/waftester-action@v1
id: waf
with:
target: https://app.example.com
upload-sarif: false
- uses: actions/upload-artifact@v4
if: always()
with:
name: waf-results
path: ${{ steps.waf.outputs.sarif-file }}
```
---
## Version Pinning
```yaml
# Recommended: floating major tag (gets latest v1.x.x)
- uses: waftester/waftester-action@v1
# Pin to exact action release
- uses: waftester/waftester-action@v1.0.48
# Pin WAFtester binary version (action auto-downloads)
- uses: waftester/waftester-action@v1
with:
version: '2.9.40'
# Pin to commit SHA (highest security)
# Replace with actual SHA from: git rev-parse v1.0.48
- uses: waftester/waftester-action@
```
---
## Supported Runners
| Runner | Architecture | Status |
|--------|-------------|--------|
| `ubuntu-latest` | x86_64 | Fully tested |
| `ubuntu-24.04` | x86_64 | Fully tested |
| `macos-latest` | ARM64 | Fully tested |
| `macos-13` | x86_64 | Supported |
| `windows-latest` | x86_64 | Fully tested |
| Self-hosted Linux | x86_64, ARM64 | Supported |
| Self-hosted macOS | ARM64 | Supported |
| Self-hosted Windows | x86_64 | Supported |
**Requirements:** `bash`, `curl`, `sha256sum` (or `shasum`).
All GitHub-hosted runners include these by default.
---
## Other Installation Methods
This GitHub Action is one of several ways to run WAFtester:
| Method | Command | Best For |
|--------|---------|----------|
| **GitHub Action** | `- uses: waftester/waftester-action@v1` | CI/CD pipelines |
| **npm** | `npx @waftester/cli scan -u URL` | Quick install, MCP server |
| **Docker** | `docker run ghcr.io/waftester/waftester scan -u URL` | Containers |
| **Binary** | [Download from Releases](https://github.com/waftester/waftester/releases) | Direct install |
---
## Links
- [**WAFtester CLI**](https://github.com/waftester/waftester)
— main project with full documentation
- [**Examples**](./examples/) — 6 ready-to-use workflow files
- [**Changelog**](./CHANGELOG.md)
— action release notes and version history
- [**Security Policy**](./SECURITY.md)
— vulnerability reporting
- [**npm Package**](https://www.npmjs.com/package/@waftester/cli)
— `npx @waftester/cli` alternative
---
## License
[BSL 1.1](LICENSE) — see the
[main project](https://github.com/waftester/waftester)
for full license terms. Changes to Apache 2.0 on
January 31, 2030.