CI/CD Integration

CI/CD Integration

The following files were used as context for generating this wiki page:

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

  1. Secret Management: Never commit credentials to repositories. Use GitHub Secrets, GitLab CI/CD variables, or HashiCorp Vault.
  2. Network Isolation: Run WSHawk in isolated networks or VPNs when scanning production systems.
  3. Access Control: Restrict who can trigger security scans using branch protection rules and CODEOWNERS.
  4. 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