Jira Integration

Jira Integration

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

Purpose and Scope

This document describes WSHawk's automated Jira integration system, which enables automatic creation of Jira Software tickets for discovered vulnerabilities. The integration is part of the Integration Collaboration Plane and supports both Jira Cloud and Jira Data Center/Server deployments.

For webhook-based notifications to Slack/Discord/Teams, see Webhook Notifications. For DefectDojo vulnerability management integration, see DefectDojo Integration.


Integration Architecture Overview

WSHawk's Jira integration operates as a post-scan automation step within the resilience-wrapped integration layer. The system converts vulnerability findings into structured Jira issues with complete reproduction details, CVSS scoring, and remediation recommendations.

Jira Integration Data Flow

graph TB
    subgraph "Scanning Phase"
        Scanner["WSHawkV2<br/>scanner_v2.py"]
        Vulnerabilities["vulnerabilities[]<br/>List of Findings"]
    end
    
    subgraph "Configuration Resolution"
        Config["WSHawkConfig<br/>wshawk.yaml"]
        EnvVars["Environment Variables<br/>JIRA_EMAIL<br/>JIRA_API_TOKEN"]
        CLIArgs["CLI Arguments<br/>--jira<br/>--jira-project"]
    end
    
    subgraph "Integration Layer"
        JiraInt["JiraIntegration<br/>jira_connector.py"]
        ResilientSession["ResilientSession<br/>Circuit Breaker<br/>Exponential Backoff"]
    end
    
    subgraph "Jira Platform"
        JiraAPI["Jira REST API v2/v3<br/>/rest/api/2/issue"]
        Project["Project: SEC<br/>Issue Type: Bug/Task"]
    end
    
    subgraph "Ticket Creation"
        Filter["Severity Filter<br/>CRITICAL/HIGH only"]
        Formatter["Ticket Formatter<br/>CVSS + Reproduction<br/>Steps"]
        Tickets["Created Issues<br/>SEC-123, SEC-124"]
    end
    
    Scanner --> Vulnerabilities
    Vulnerabilities --> Filter
    
    Config --> JiraInt
    EnvVars --> JiraInt
    CLIArgs --> JiraInt
    
    Filter --> Formatter
    Formatter --> JiraInt
    JiraInt --> ResilientSession
    ResilientSession --> JiraAPI
    JiraAPI --> Project
    Project --> Tickets
    
    Tickets --> Scanner

Sources: wshawk/scanner_v2.py:807-828, wshawk/advanced_cli.py:251-265


Configuration Methods

The Jira integration supports three configuration methods with hierarchical precedence: CLI flags override environment variables, which override wshawk.yaml settings.

Hierarchical Configuration System

graph LR
    subgraph "Configuration Sources"
        YAML["wshawk.yaml<br/>integrations.jira"]
        Env["Environment Variables<br/>JIRA_EMAIL<br/>JIRA_API_TOKEN"]
        CLI["CLI Flags<br/>--jira<br/>--jira-project"]
    end
    
    subgraph "WSHawkConfig Resolution"
        Loader["WSHawkConfig.load()"]
        Resolver["Secret Resolution<br/>env: prefix"]
        Merge["Hierarchical Merge<br/>CLI > Env > YAML"]
    end
    
    subgraph "Integration Initialization"
        JiraInit["JiraIntegration<br/>__init__"]
        Validation["Credential Validation<br/>URL + Email + Token"]
    end
    
    YAML --> Loader
    Env --> Resolver
    CLI --> Merge
    
    Loader --> Merge
    Resolver --> Merge
    Merge --> JiraInit
    JiraInit --> Validation

Sources: README.md:137-150, wshawk/advanced_cli.py:86-98

Configuration via wshawk.yaml

The recommended method for persistent configuration is wshawk.yaml. Generate a template configuration:

python3 -m wshawk.config --generate

Edit the generated wshawk.yaml file:

integrations:
  jira:
    enabled: true
    url: "https://yourcompany.atlassian.net"
    email: "env:JIRA_EMAIL"         # Resolves from environment variable
    api_token: "env:JIRA_API_TOKEN" # Resolves from environment variable
    project_key: "SEC"
    auto_create: true
    severity_filter:
      - "CRITICAL"
      - "HIGH"

Secret Resolution: The env: prefix indicates that the value should be resolved from an environment variable, preventing credential exposure in version control.

Sources: README.md:137-150, docs/V3_COMPLETE_GUIDE.md:337-340

Configuration via Environment Variables

For CI/CD pipelines and containerized deployments, use environment variables:

export JIRA_EMAIL="security-team@example.com"
export JIRA_API_TOKEN="your-api-token-here"
export JIRA_PROJECT="SEC"

Sources: wshawk/advanced_cli.py:252-255

Configuration via CLI Flags

For ad-hoc scans, override configuration with CLI flags:

# Basic Jira integration
wshawk-advanced ws://target.com \
  --jira https://yourcompany.atlassian.net \
  --jira-project SEC

# With environment credentials
export JIRA_EMAIL="user@example.com"
export JIRA_API_TOKEN="token"
wshawk-advanced ws://target.com --jira https://jira.company.com

CLI Arguments:

| Flag | Description | Default | |------|-------------|---------| | --jira URL | Jira instance base URL | None (disabled) | | --jira-project KEY | Project key for ticket creation | SEC |

Sources: wshawk/advanced_cli.py:62-65


Authentication System

WSHawk uses API token authentication for Jira Cloud and Basic Auth for Jira Data Center/Server. This section describes the authentication flow and credential management.

API Token Generation

For Jira Cloud:

  1. Navigate to: https://id.atlassian.com/manage-profile/security/api-tokens
  2. Click "Create API token"
  3. Label: "WSHawk Security Scanner"
  4. Copy the generated token
  5. Store securely in environment variables or secrets manager

For Jira Data Center/Server:

  1. Use username/password or personal access tokens (PAT)
  2. Configure in the same way as Jira Cloud credentials

Authentication Flow

sequenceDiagram
    participant CLI as "wshawk-advanced CLI"
    participant Config as "WSHawkConfig"
    participant JiraInt as "JiraIntegration"
    participant Resilient as "ResilientSession"
    participant JiraAPI as "Jira REST API"
    
    CLI->>Config: Load configuration
    Config->>Config: Resolve env:JIRA_EMAIL
    Config->>Config: Resolve env:JIRA_API_TOKEN
    Config->>JiraInt: Initialize(url, email, token)
    
    JiraInt->>JiraInt: Validate credentials
    JiraInt->>Resilient: Wrap HTTP session
    
    Note over JiraInt: Scan completes
    
    JiraInt->>Resilient: POST /rest/api/2/issue
    Resilient->>Resilient: Apply exponential backoff
    Resilient->>JiraAPI: Authorization: Basic base64(email:token)
    JiraAPI-->>Resilient: 201 Created + issue key
    Resilient-->>JiraInt: Issue created: SEC-123
    JiraInt-->>CLI: Success: 3 tickets created

Authentication Header: WSHawk constructs Basic Authentication headers as base64(email:api_token) for Jira Cloud, following Atlassian's authentication standards.

Sources: wshawk/advanced_cli.py:251-265, RELEASE_SUMMARY.md:32


JiraIntegration Class

The JiraIntegration class is the core component responsible for ticket creation. It resides in wshawk/integrations/jira_connector.py and provides a high-level interface for converting vulnerability findings into Jira issues.

Class Architecture

classDiagram
    class JiraIntegration {
        -url: str
        -email: str
        -api_token: str
        -project_key: str
        -session: ResilientSession
        +__init__(url, email, api_token, project_key)
        +create_tickets(vulnerabilities, scan_info) List~str~
        -_format_issue_description(vuln, scan_info) str
        -_calculate_priority(cvss_score) str
        -_create_single_ticket(issue_data) str
    }
    
    class ResilientSession {
        +post(url, json, headers)
        +get(url, headers)
    }
    
    class WSHawkV2 {
        +vulnerabilities: List
        +run_heuristic_scan()
    }
    
    JiraIntegration --> ResilientSession: "wraps HTTP calls"
    WSHawkV2 --> JiraIntegration: "calls after scan"

Sources: wshawk/advanced_cli.py:257-263

Key Methods

| Method | Purpose | Return Type | |--------|---------|-------------| | __init__() | Initialize with Jira credentials and project | None | | create_tickets() | Convert vulnerabilities to Jira issues | List[str] (issue keys) | | _format_issue_description() | Format vulnerability details as Jira markdown | str | | _calculate_priority() | Map CVSS score to Jira priority (Blocker/Critical/Major) | str |

Sources: wshawk/advanced_cli.py:258-265


Automatic Ticket Creation Workflow

WSHawk automatically creates Jira tickets at the end of a scan if the integration is enabled. The workflow includes severity filtering, deduplication, and resilient API calls.

Ticket Creation Pipeline

graph TB
    subgraph "Scan Completion"
        Complete["Scan Complete<br/>vulnerabilities[]"]
    end
    
    subgraph "Integration Check"
        Enabled{"Jira Enabled?<br/>args.jira or<br/>config.jira.enabled"}
        CredsCheck{"Credentials Valid?<br/>JIRA_EMAIL +<br/>JIRA_API_TOKEN"}
    end
    
    subgraph "Vulnerability Processing"
        Filter["Severity Filter<br/>CRITICAL/HIGH only"]
        Dedupe["Deduplication<br/>by payload hash"]
        Format["Format Issue Data<br/>Summary + Description"]
    end
    
    subgraph "Resilient API Calls"
        Circuit{"Circuit Breaker<br/>State?"}
        Backoff["Exponential Backoff<br/>on 429/5xx"]
        Create["POST /rest/api/2/issue"]
    end
    
    subgraph "Result Handling"
        Success["Ticket Created<br/>SEC-123"]
        Log["Logger.success<br/>3 tickets created"]
    end
    
    Complete --> Enabled
    Enabled -->|Yes| CredsCheck
    Enabled -->|No| Skip["Skip Integration"]
    CredsCheck -->|Valid| Filter
    CredsCheck -->|Invalid| Error["Logger.error<br/>Missing credentials"]
    
    Filter --> Dedupe
    Dedupe --> Format
    Format --> Circuit
    
    Circuit -->|CLOSED| Create
    Circuit -->|OPEN| Backoff
    Backoff --> Circuit
    
    Create -->|201| Success
    Create -->|429| Backoff
    Create -->|4xx| Error
    
    Success --> Log

Sources: wshawk/advanced_cli.py:251-265, wshawk/scanner_v2.py:807-828

Invocation Points

The Jira integration is invoked in two primary contexts:

  1. CLI Scan Completion - wshawk/advanced_cli.py:251-265

    if args.jira and vuln_list:
        # ... credential validation ...
        jira = JiraIntegration(url, email, api_token, project_key)
        tickets = await jira.create_tickets(vuln_list, scan_info)
        Logger.success(f"Jira: {len(tickets)} tickets created")
    
  2. Scanner Auto-Integration - wshawk/scanner_v2.py:807-828

    • After report generation, if configured via wshawk.yaml

Sources: wshawk/advanced_cli.py:251-265, wshawk/scanner_v2.py:807-828


Ticket Content Structure

Jira tickets created by WSHawk follow a standardized format that includes all information necessary for security teams to reproduce, assess, and remediate vulnerabilities.

Ticket Field Mapping

| Jira Field | Source Data | Example | |------------|-------------|---------| | Project | project_key config | SEC | | Issue Type | Hardcoded | Bug or Security | | Summary | vuln['type'] + target | SQL Injection on ws://api.example.com | | Priority | CVSS score mapping | Blocker (9.0-10.0), Critical (7.0-8.9) | | Description | Formatted vulnerability details | See below | | Labels | ['wshawk', 'websocket', 'automated'] | wshawk, sqli, high |

Description Template

The ticket description follows this structure:

h2. Vulnerability Details

*Type:* SQL Injection
*Severity:* HIGH
*Confidence:* HIGH
*CVSS v3.1 Score:* 8.6 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:L)

h2. Target Information

*WebSocket URL:* ws://vulnerable.example.com/api/chat
*Protocol:* WebSocket (RFC 6455)
*Scan Date:* 2024-01-15 14:32:10 UTC

h2. Reproduction Steps

1. Connect to WebSocket endpoint: ws://vulnerable.example.com/api/chat
2. Send authentication handshake (if required)
3. Inject payload into message field:
   {code:json}
   {"action": "query", "user": "admin' OR '1'='1"}
   {code}
4. Observe SQL error message in response:
   {code}
   {"error": "SQL syntax error near 'admin' OR '1'='1'"}
   {code}

h2. Evidence

*Payload:* {code}admin' OR '1'='1{code}
*Response Snippet:* {code}SQL syntax error near 'admin'{code}

h2. Remediation

Use parameterized queries (prepared statements) to prevent SQL injection:
- For Python: Use `cursor.execute("SELECT * FROM users WHERE name=?", (user_input,))`
- For Node.js: Use parameterized queries with libraries like `pg` or `mysql2`
- Validate and sanitize all WebSocket message inputs
- Implement input length restrictions
- Apply principle of least privilege for database connections

h2. References

- OWASP WebSocket Security Cheat Sheet
- CWE-89: SQL Injection
- WSHawk Report: wshawk_report_20240115_143210.html

Sources: RELEASE_SUMMARY.md:32, docs/V3_COMPLETE_GUIDE.md:337-340


CVSS to Jira Priority Mapping

WSHawk maps CVSS v3.1 severity scores to Jira priorities using the following scheme:

graph LR
    subgraph "CVSS Score Ranges"
        Critical["CRITICAL<br/>9.0 - 10.0"]
        High["HIGH<br/>7.0 - 8.9"]
        Medium["MEDIUM<br/>4.0 - 6.9"]
        Low["LOW<br/>0.1 - 3.9"]
    end
    
    subgraph "Jira Priority"
        Blocker["Blocker<br/>P1"]
        CriticalP["Critical<br/>P2"]
        Major["Major<br/>P3"]
        Minor["Minor<br/>P4"]
    end
    
    Critical --> Blocker
    High --> CriticalP
    Medium --> Major
    Low --> Minor

Default Severity Filter: By default, only CRITICAL and HIGH severity vulnerabilities generate Jira tickets to reduce noise. This is configurable via wshawk.yaml:

integrations:
  jira:
    severity_filter:
      - "CRITICAL"
      - "HIGH"
      - "MEDIUM"  # Uncomment to include MEDIUM severity

Sources: RELEASE_SUMMARY.md:32


Integration with ResilientSession

All Jira API calls are wrapped in ResilientSession to handle network failures, rate limiting, and API throttling gracefully. This ensures that temporary Jira outages or rate limits do not cause scan failures.

Resilience Features

stateDiagram-v2
    [*] --> Closed: "Initial State"
    
    Closed --> Attempt: "Create Ticket"
    Attempt --> Success: "201 Created"
    Attempt --> Retry: "429 Rate Limited"
    Attempt --> Retry: "5xx Server Error"
    Attempt --> Open: "Max Retries Exceeded"
    Attempt --> Failed: "4xx Client Error"
    
    Retry --> Backoff: "Calculate Delay"
    Backoff --> Attempt: "Wait Complete"
    
    Open --> Cooldown: "60s Wait"
    Cooldown --> HalfOpen: "Test Recovery"
    HalfOpen --> Closed: "Success"
    HalfOpen --> Open: "Still Failing"
    
    Success --> [*]
    Failed --> [*]

Circuit Breaker Behavior:

  • CLOSED: Normal operation, requests proceed immediately
  • OPEN: Jira is experiencing issues, fail fast for 60 seconds
  • HALF_OPEN: Test if Jira has recovered with a single request

Exponential Backoff Formula:

Wait = min(60s, 2s * 2^attempt) + random(0, 1s)

Sources: RELEASE_SUMMARY.md:9-13, docs/V3_COMPLETE_GUIDE.md:134-173


Configuration Examples

Example 1: Basic Jira Integration

Minimal configuration for automated ticket creation:

# wshawk.yaml
integrations:
  jira:
    enabled: true
    url: "https://company.atlassian.net"
    email: "env:JIRA_EMAIL"
    api_token: "env:JIRA_API_TOKEN"
    project_key: "SEC"
    auto_create: true
# Environment setup
export JIRA_EMAIL="security-scanner@company.com"
export JIRA_API_TOKEN="ATATxxxxxxxxxxxxxx"

# Run scan with automatic Jira integration
wshawk-advanced ws://target.com --full

Sources: README.md:137-150, wshawk/advanced_cli.py:251-265

Example 2: CLI-Only Integration

Override configuration entirely via CLI flags:

export JIRA_EMAIL="pentester@company.com"
export JIRA_API_TOKEN="token-here"

wshawk-advanced ws://vulnerable-app.com \
  --jira https://jira.company.com \
  --jira-project PENTEST \
  --smart-payloads \
  --playwright

This creates tickets in the PENTEST project instead of the default SEC project.

Sources: wshawk/advanced_cli.py:251-265

Example 3: CI/CD Pipeline Integration

GitHub Actions workflow with Jira integration:

name: WebSocket Security Scan
on: [push]

jobs:
  security-scan:
    runs-on: ubuntu-latest
    steps:
      - name: Run WSHawk with Jira
        run: |
          docker run --rm \
            -e JIRA_EMAIL="${{ secrets.JIRA_EMAIL }}" \
            -e JIRA_API_TOKEN="${{ secrets.JIRA_API_TOKEN }}" \
            rothackers/wshawk \
            wshawk-advanced ws://staging.example.com \
              --jira https://company.atlassian.net \
              --jira-project STAGING \
              --format sarif
      
      - name: Upload SARIF
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: wshawk_report.sarif

Secrets Configuration:

  • JIRA_EMAIL: Service account email
  • JIRA_API_TOKEN: Scoped API token with "Create Issues" permission

Sources: docs/V3_COMPLETE_GUIDE.md:362-376

Example 4: Custom Severity Filtering

Only create tickets for CRITICAL vulnerabilities:

# wshawk.yaml
integrations:
  jira:
    enabled: true
    url: "https://company.atlassian.net"
    email: "env:JIRA_EMAIL"
    api_token: "env:JIRA_API_TOKEN"
    project_key: "SEC"
    auto_create: true
    severity_filter:
      - "CRITICAL"  # Only create tickets for critical issues
    
    # Optional: Custom issue type
    issue_type: "Security Vulnerability"

Sources: README.md:137-150


Troubleshooting

Common Issues and Solutions

| Issue | Cause | Solution | |-------|-------|----------| | Set JIRA_EMAIL and JIRA_API_TOKEN environment variables | Missing credentials | Export both environment variables before running scan | | Jira: 401 Unauthorized | Invalid API token or email | Regenerate API token at id.atlassian.com | | Jira: 404 Not Found | Invalid Jira URL or project | Verify base URL and project key existence | | Jira: 0 tickets created | No HIGH/CRITICAL findings | Check severity filter or reduce filter threshold | | Circuit Breaker OPEN | Jira API rate limit exceeded | Wait 60s for cooldown, or reduce scan frequency |

Validation Steps

Verify Jira integration configuration:

# Test credentials
curl -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
  https://company.atlassian.net/rest/api/2/myself

# Verify project exists
curl -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
  https://company.atlassian.net/rest/api/2/project/SEC

# Test ticket creation manually
wshawk-advanced ws://echo.websocket.org \
  --jira https://company.atlassian.net \
  --jira-project TEST

Sources: wshawk/advanced_cli.py:252-265


Security Considerations

Credential Management

Best Practices:

  1. Never commit credentials to wshawk.yaml - use env: prefix for secret resolution
  2. Use dedicated service accounts with minimal permissions (create issues only)
  3. Rotate API tokens every 90 days
  4. Store tokens in secrets managers (AWS Secrets Manager, HashiCorp Vault, etc.)
  5. Audit Jira API access regularly via Atlassian access logs

Permission Requirements

The Jira service account requires these minimum permissions:

  • Browse Projects - View project details
  • Create Issues - Create new issues/bugs
  • Add Comments - (Optional) Add follow-up comments

Sources: README.md:137-150


Performance and Rate Limiting

Jira API Rate Limits

Atlassian enforces the following rate limits:

| Jira Type | Rate Limit | WSHawk Behavior | |-----------|------------|-----------------| | Cloud (Free/Standard) | 300 req/min | Circuit breaker opens at threshold | | Cloud (Premium) | 1000 req/min | Exponential backoff on 429 | | Data Center | Varies by config | Respects Retry-After header |

Optimization Strategies

Batch Processing: WSHawk processes all vulnerabilities before making Jira API calls, minimizing connection overhead.

Deduplication: Identical vulnerabilities (same type + payload + target) are deduplicated to avoid creating duplicate tickets.

Async Operations: Jira ticket creation is asynchronous and non-blocking; scan reports are generated immediately even if Jira is slow.

Sources: RELEASE_SUMMARY.md:9-13


Sources