CI/CD Integration
CI/CD Integration
The following files were used as context for generating this wiki page:
- .dockerignore
- .github/workflows/docker-build.yml
- .github/workflows/ghcr-publish.yml
- README.md
- RELEASE_3.0.0.md
- RELEASE_SUMMARY.md
- docker-compose.yml
- docs/V3_COMPLETE_GUIDE.md
Purpose and Scope
This document covers integrating WSHawk into Continuous Integration and Continuous Deployment (CI/CD) pipelines. It includes both WSHawk's internal build automation system and examples for incorporating WSHawk scans into external CI/CD workflows (GitHub Actions, GitLab CI, Jenkins, etc.).
For Docker image usage patterns, see Docker Usage Guide. For Kubernetes-based deployment at scale, see Kubernetes Deployment. For SARIF export and report formats, see Report Formats and Export.
WSHawk's Internal CI/CD Architecture
WSHawk uses GitHub Actions to automate multi-architecture Docker image builds and publish to multiple container registries. This system ensures consistent, production-ready releases on every push and tag.
CI/CD Trigger Strategy
graph TB
subgraph "Trigger Events"
PushMain["Push to main branch"]
PushTag["Push tags (v*)"]
PR["Pull Request"]
Manual["workflow_dispatch"]
end
subgraph "Workflows"
DockerBuild["docker-build.yml<br/>Multi-Registry Build"]
GHCRPublish["ghcr-publish.yml<br/>GHCR-Only Build"]
end
subgraph "Actions Taken"
BuildTest["Build + Test"]
BuildPush["Build + Push"]
NoAction["Build Only (No Push)"]
end
subgraph "Target Registries"
DockerHub["Docker Hub<br/>rothackers/wshawk"]
GHCR["GitHub Container Registry<br/>ghcr.io/regaan/wshawk"]
end
PushMain --> DockerBuild
PushTag --> DockerBuild
PushTag --> GHCRPublish
PR --> DockerBuild
Manual --> DockerBuild
Manual --> GHCRPublish
DockerBuild -->|"event != PR"| BuildPush
DockerBuild -->|"event == PR"| NoAction
GHCRPublish --> BuildPush
BuildPush --> DockerHub
BuildPush --> GHCR
Sources: .github/workflows/docker-build.yml:3-12, .github/workflows/ghcr-publish.yml:3-9
Multi-Architecture Build Pipeline
WSHawk builds Docker images for both linux/amd64 and linux/arm64 architectures using QEMU emulation. This ensures compatibility with both traditional x86 servers and ARM-based infrastructure (AWS Graviton, Apple Silicon, Raspberry Pi).
Build Pipeline Flow:
graph LR
subgraph "Setup Phase"
Checkout["actions/checkout@v4"]
QEMU["docker/setup-qemu-action@v3<br/>ARM64 Emulation"]
Buildx["docker/setup-buildx-action@v3<br/>Multi-Arch Builder"]
end
subgraph "Authentication Phase"
VerifySecrets["Verify DOCKER_USERNAME<br/>DOCKER_PASSWORD"]
LoginDH["docker/login-action@v3<br/>Docker Hub"]
LoginGHCR["docker/login-action@v3<br/>GHCR"]
end
subgraph "Metadata Phase"
ExtractMeta["docker/metadata-action@v5<br/>Generate Tags & Labels"]
end
subgraph "Build Phase"
BuildPush["docker/build-push-action@v5<br/>platforms: linux/amd64,linux/arm64"]
end
subgraph "Validation Phase"
TestImage["docker pull latest<br/>docker run --help<br/>wshawk-defensive --help"]
end
Checkout --> QEMU
QEMU --> Buildx
Buildx --> VerifySecrets
VerifySecrets --> LoginDH
VerifySecrets --> LoginGHCR
LoginDH --> ExtractMeta
LoginGHCR --> ExtractMeta
ExtractMeta --> BuildPush
BuildPush --> TestImage
Sources: .github/workflows/docker-build.yml:25-88
Image Tagging Strategy
WSHawk uses semantic versioning with intelligent tag generation via docker/metadata-action@v5:
| Event Type | Generated Tags | Example |
|------------|---------------|---------|
| Push to main | latest | rothackers/wshawk:latest |
| Tag v3.0.0 | 3.0.0, 3.0, 3, latest | rothackers/wshawk:3.0.0 |
| Tag v3.1.0-rc1 | 3.1.0-rc1 | rothackers/wshawk:3.1.0-rc1 |
| PR #42 | pr-42 | (build only, not pushed) |
| Branch feature/xyz | feature-xyz | rothackers/wshawk:feature-xyz |
Sources: .github/workflows/docker-build.yml:56-69
Build Optimization
The workflow uses GitHub Actions cache to speed up subsequent builds:
cache-from: type=gha
cache-to: type=gha,mode=max
This caches Docker layers between runs, reducing build times from ~10 minutes to ~2 minutes for incremental changes.
Sources: .github/workflows/docker-build.yml:78-79
Integrating WSHawk into External CI/CD Pipelines
WSHawk is designed to run in non-interactive CI/CD environments. It supports headless execution, structured output formats (JSON, SARIF), and meaningful exit codes.
Exit Code Conventions
| Exit Code | Meaning | Use Case |
|-----------|---------|----------|
| 0 | Scan completed, no critical/high vulnerabilities | Safe to deploy |
| 1 | Scan failed (connection error, invalid target) | Pipeline should fail |
| 2 | Critical or High severity vulnerability found | Block deployment |
GitHub Actions Integration
Basic Scan Example
name: WebSocket Security Scan
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
wshawk-scan:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run WSHawk scan
run: |
docker run --rm \
-v ${{ github.workspace }}/reports:/app/reports \
rothackers/wshawk:latest \
ws://staging.example.com/api \
--rate 5
- name: Upload scan report
if: always()
uses: actions/upload-artifact@v3
with:
name: wshawk-report
path: reports/*.html
Sources: docs/V3_COMPLETE_GUIDE.md:363-377
SARIF Integration with GitHub Security Tab
WSHawk exports SARIF (Static Analysis Results Interchange Format) for integration with GitHub's Security tab:
name: WebSocket Security Scan with SARIF
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
wshawk-sarif:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- name: Run WSHawk and generate SARIF
run: |
docker run --rm \
-v ${{ github.workspace }}/reports:/app/reports \
rothackers/wshawk:latest \
ws://staging.example.com/api \
--output-format sarif \
--output-file /app/reports/wshawk.sarif
- name: Upload SARIF to GitHub Security
uses: github/codeql-action/upload-sarif@v2
if: always()
with:
sarif_file: reports/wshawk.sarif
category: websocket-security
Sources: README.md:52, RELEASE_SUMMARY.md:53-54, docs/V3_COMPLETE_GUIDE.md:363-377
Advanced Configuration with Secrets
name: Full WSHawk Scan with Integrations
on:
schedule:
- cron: '0 2 * * 1' # Weekly Monday 2 AM
workflow_dispatch:
jobs:
wshawk-advanced:
runs-on: ubuntu-latest
steps:
- name: Run advanced scan with integrations
env:
WSHAWK_WEB_PASSWORD: ${{ secrets.WSHAWK_PASSWORD }}
JIRA_API_TOKEN: ${{ secrets.JIRA_TOKEN }}
DEFECTDOJO_API_KEY: ${{ secrets.DEFECTDOJO_KEY }}
run: |
docker run --rm \
-e WSHAWK_WEB_PASSWORD \
-e JIRA_API_TOKEN \
-e DEFECTDOJO_API_KEY \
-v ${{ github.workspace }}/reports:/app/reports \
-v ${{ github.workspace }}/wshawk.yaml:/app/wshawk.yaml \
rothackers/wshawk:latest \
wshawk-advanced ws://production.example.com/api \
--smart-payloads \
--playwright \
--full
- name: Notify on failure
if: failure()
uses: slackapi/slack-github-action@v1
with:
webhook: ${{ secrets.SLACK_WEBHOOK }}
payload: |
{
"text": "WSHawk security scan failed - Critical vulnerabilities found"
}
Sources: README.md:122-126, README.md:146-150
GitLab CI Integration
Create a .gitlab-ci.yml file:
stages:
- security
websocket-security-scan:
stage: security
image: docker:latest
services:
- docker:dind
variables:
SCAN_TARGET: "ws://staging.example.com/api"
script:
- docker pull rothackers/wshawk:latest
- |
docker run --rm \
-v $CI_PROJECT_DIR/reports:/app/reports \
-e WSHAWK_WEB_PASSWORD=$WSHAWK_PASSWORD \
rothackers/wshawk:latest \
$SCAN_TARGET \
--output-format json \
--output-file /app/reports/wshawk.json
artifacts:
when: always
paths:
- reports/
expire_in: 30 days
only:
- main
- merge_requests
Jenkins Pipeline Integration
pipeline {
agent any
environment {
SCAN_TARGET = 'ws://staging.example.com/api'
WSHAWK_IMAGE = 'rothackers/wshawk:latest'
}
stages {
stage('WebSocket Security Scan') {
steps {
script {
docker.image(env.WSHAWK_IMAGE).inside('-v $WORKSPACE/reports:/app/reports') {
sh '''
wshawk ${SCAN_TARGET} \
--rate 5 \
--output-format json \
--output-file /app/reports/wshawk.json
'''
}
}
}
}
stage('Process Results') {
steps {
publishHTML([
reportDir: 'reports',
reportFiles: '*.html',
reportName: 'WSHawk Security Report'
])
}
}
}
post {
always {
archiveArtifacts artifacts: 'reports/**', fingerprint: true
}
}
}
Docker Compose for CI/CD Testing
For local CI/CD pipeline development, use docker-compose.yml to spin up WSHawk alongside a test server:
Docker Compose Configuration
graph TB
subgraph "docker-compose.yml Services"
WSHawk["wshawk service<br/>network_mode: host<br/>volumes: ./reports"]
VulnServer["vulnerable-server service<br/>ports: 8765:8765<br/>Python test server"]
end
subgraph "Network Configuration"
HostNet["Host Network<br/>(for wshawk)"]
BridgeNet["wshawk-network Bridge<br/>(for vulnerable-server)"]
end
subgraph "Mounted Volumes"
Reports["./reports → /app/reports"]
Examples["./examples → /app"]
end
WSHawk --> HostNet
VulnServer --> BridgeNet
WSHawk --> Reports
VulnServer --> Examples
Usage:
# Start vulnerable test server
docker-compose up -d vulnerable-server
# Run WSHawk scan in interactive mode
docker-compose run --rm wshawk wshawk ws://localhost:8765
# Run advanced scan
docker-compose run --rm wshawk wshawk-advanced ws://localhost:8765 --full
# Clean up
docker-compose down
Sources: docker-compose.yml:1-36
Environment Variables for CI/CD
WSHawk supports environment-based configuration for secrets and operational parameters:
| Environment Variable | Purpose | Example |
|---------------------|---------|---------|
| WSHAWK_WEB_PASSWORD | Web dashboard authentication | export WSHAWK_WEB_PASSWORD='secure-pass' |
| WSHAWK_API_KEY | API key for programmatic access | export WSHAWK_API_KEY='api-key-123' |
| JIRA_API_TOKEN | Jira integration authentication | export JIRA_API_TOKEN='jira-token' |
| DEFECTDOJO_API_KEY | DefectDojo integration | export DEFECTDOJO_API_KEY='dd-key' |
| WSHAWK_RATE_LIMIT | Override default rate limit | export WSHAWK_RATE_LIMIT=5 |
| PYTHONUNBUFFERED | Force unbuffered output for logs | export PYTHONUNBUFFERED=1 |
These can be resolved in wshawk.yaml using the env: prefix:
integrations:
jira:
api_token: "env:JIRA_API_TOKEN"
project: "SEC"
defectdojo:
api_key: "env:DEFECTDOJO_API_KEY"
url: "https://defectdojo.company.com"
Sources: README.md:122-150, docker-compose.yml:17-18
Optimization for CI/CD Environments
Build Cache Strategy
WSHawk's Docker build uses .dockerignore to exclude unnecessary files from the build context, reducing build time and image size:
Excluded Artifacts:
- Python artifacts:
__pycache__/,*.pyc,dist/,*.egg-info/ - Virtual environments:
venv/,env/,wshawk_venv/ - Testing artifacts:
.pytest_cache/,.coverage,.hypothesis/ - Reports and logs:
reports/,*.html,*.log - Documentation:
docs/(except README.md) - CI/CD configs:
.github/,.gitlab-ci.yml
Sources: .dockerignore:1-72
Non-Interactive Mode
WSHawk automatically detects CI/CD environments and disables interactive prompts. Use explicit flags to ensure deterministic behavior:
# Force non-interactive scan with explicit options
wshawk ws://target.com \
--rate 10 \
--timeout 30 \
--output-format json \
--output-file /app/reports/scan.json \
--no-color
Parallel Scanning in CI/CD
For scanning multiple endpoints, use matrix builds:
strategy:
matrix:
target:
- ws://api1.example.com
- ws://api2.example.com
- wss://secure.example.com/ws
jobs:
parallel-scan:
runs-on: ubuntu-latest
steps:
- name: Scan ${{ matrix.target }}
run: |
docker run --rm \
-v ${{ github.workspace }}/reports:/app/reports \
rothackers/wshawk:latest \
${{ matrix.target }} \
--output-file /app/reports/$(echo "${{ matrix.target }}" | sed 's/[:/]/-/g').json
SARIF Schema Mapping
WSHawk maps vulnerability types to SARIF format for GitHub Security integration:
graph LR
subgraph "WSHawk Vulnerability Types"
SQLi["SQL Injection"]
XSS["Cross-Site Scripting"]
XXE["XML External Entity"]
SSRF["Server-Side Request Forgery"]
CSWSH["Cross-Site WebSocket Hijacking"]
end
subgraph "SARIF Result Object"
RuleID["ruleId: 'WSH-001'"]
Level["level: 'error'"]
Message["message: {text: '...'}"]
Location["locations: [{physicalLocation: ...}]"]
CVSS["properties: {cvss: '9.1', ...}"]
end
subgraph "GitHub Security Tab"
Alert["Security Alert"]
Severity["Critical/High/Medium/Low"]
Details["Full Vulnerability Details"]
end
SQLi --> RuleID
XSS --> RuleID
XXE --> RuleID
SSRF --> RuleID
CSWSH --> RuleID
RuleID --> Alert
Level --> Severity
Message --> Details
Location --> Details
CVSS --> Details
SARIF Rule ID Mapping:
| Vulnerability Type | SARIF Rule ID | CVSS Range |
|-------------------|---------------|------------|
| SQL Injection | WSH-001 | 8.0-10.0 |
| XSS | WSH-002 | 6.1-9.6 |
| XXE | WSH-003 | 7.5-9.1 |
| SSRF | WSH-004 | 6.5-9.1 |
| CSWSH | WSH-005 | 7.4-9.3 |
| Command Injection | WSH-006 | 9.0-10.0 |
| NoSQL Injection | WSH-007 | 7.0-9.1 |
| Path Traversal | WSH-008 | 5.3-8.1 |
| LDAP Injection | WSH-009 | 6.5-8.6 |
| SSTI | WSH-010 | 8.0-9.8 |
Sources: RELEASE_SUMMARY.md:53-54, README.md:52
Continuous Security Monitoring Pattern
For production environments, implement continuous WebSocket security monitoring:
graph TB
subgraph "Scheduled CI/CD Job"
Cron["Cron Schedule<br/>Daily/Weekly"]
Trigger["Workflow Trigger"]
end
subgraph "WSHawk Execution"
Scan["Full Security Scan<br/>--smart-payloads --playwright"]
Results["Generate Reports<br/>HTML + JSON + SARIF"]
end
subgraph "Integration Actions"
SARIF["Upload SARIF<br/>GitHub Security"]
Jira["Create Jira Tickets<br/>Critical/High only"]
DD["Push to DefectDojo<br/>Engagement tracking"]
Webhook["Send Slack/Discord<br/>Notification"]
end
subgraph "Decision Logic"
Check{"Vulnerabilities<br/>Found?"}
BlockDeploy["Block Deployment"]
AllowDeploy["Allow Deployment"]
end
Cron --> Trigger
Trigger --> Scan
Scan --> Results
Results --> SARIF
Results --> Jira
Results --> DD
Results --> Webhook
Results --> Check
Check -->|"Critical/High"| BlockDeploy
Check -->|"None/Low/Medium"| AllowDeploy
Implementation Example:
name: Continuous WebSocket Security
on:
schedule:
- cron: '0 3 * * *' # Daily at 3 AM UTC
jobs:
security-monitor:
runs-on: ubuntu-latest
steps:
- name: Scan production endpoints
id: scan
continue-on-error: true
run: |
docker run --rm \
-e JIRA_API_TOKEN=${{ secrets.JIRA_TOKEN }} \
-e DEFECTDOJO_API_KEY=${{ secrets.DD_KEY }} \
-v ${{ github.workspace }}/reports:/app/reports \
-v ${{ github.workspace }}/wshawk.yaml:/app/wshawk.yaml \
rothackers/wshawk:latest \
wshawk-advanced wss://production.example.com/api \
--smart-payloads \
--playwright \
--full \
--output-format sarif
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v2
if: always()
with:
sarif_file: reports/wshawk.sarif
- name: Check for critical findings
if: steps.scan.outcome == 'failure'
run: |
echo "::error::Critical WebSocket vulnerabilities detected"
exit 1
Sources: docs/V3_COMPLETE_GUIDE.md:363-377, RELEASE_SUMMARY.md:30-34
Best Practices for CI/CD Integration
Resource Management
| Practice | Recommendation | Rationale |
|----------|---------------|-----------|
| Rate Limiting | --rate 5 for staging, --rate 2 for production | Prevents service disruption |
| Timeout | --timeout 300 (5 minutes) | Ensures pipeline doesn't hang |
| Concurrent Jobs | Limit to 1-2 parallel scans | Avoids overwhelming target servers |
| Scan Frequency | Daily for staging, weekly for production | Balances coverage and resource usage |
Security Considerations
- Secret Management: Never commit credentials to repositories. Use GitHub Secrets, GitLab CI/CD variables, or HashiCorp Vault.
- Network Isolation: Run WSHawk in isolated networks or VPNs when scanning production systems.
- Access Control: Restrict who can trigger security scans using branch protection rules and CODEOWNERS.
- Audit Logging: Enable detailed logging and archive all scan reports for compliance.
Failure Handling
# Fail pipeline only on critical/high findings
- name: Check severity threshold
run: |
CRITICAL_COUNT=$(jq '.results[] | select(.level == "error") | .ruleId' reports/wshawk.sarif | wc -l)
if [ $CRITICAL_COUNT -gt 0 ]; then
echo "::error::Found $CRITICAL_COUNT critical vulnerabilities"
exit 1
fi
Sources: README.md:193-197, docs/V3_COMPLETE_GUIDE.md:363-377