# Bitbucket Pipelines Integration This guide covers all aspects of integrating Purplemet security analyses into Bitbucket Pipelines. ## Table of Contents - [Prerequisites](#prerequisites) - [Quick Start](#quick-start) - [Installation Methods](#installation-methods) - [Parameters](#parameters) - [Security Gates](#security-gates) - [Artifacts](#artifacts) - [Complete Pipeline Examples](#complete-pipeline-examples) - [Results and Exit Codes](#results-and-exit-codes) - [Advanced Usage](#advanced-usage) - [FAQ / Common Errors](#faq--common-errors) ## Prerequisites ### 1. Purplemet API Token Create a token at [cloud.purplemet.com](https://cloud.purplemet.com/#/tokens/create). ### 2. Repository Variables Add the following variables in **Repository Settings** → **Pipelines** → **Repository variables**: | Variable | Secured | Description | |----------|---------|-------------| | `PURPLEMET_API_TOKEN` | **Yes** | API authentication token — must be secured | | `PURPLEMET_TARGET_URL` | No | URL of the web application to analyze | > **Workspace-level variables:** For multi-repo usage, add variables at the workspace level. ### 3. Network Access Bitbucket Cloud runners can reach the Purplemet API by default. For self-hosted runners, ensure outbound HTTPS access to `api.purplemet.com`. ## Quick Start Add to your `bitbucket-pipelines.yml`: ```yaml pipelines: default: - step: name: Purplemet Security Analysis script: - pipe: docker://ppmsupport/purplemet-analyze-bitbucket:1 variables: PURPLEMET_API_TOKEN: $PURPLEMET_API_TOKEN PURPLEMET_TARGET_URL: "https://your-app.example.com" ``` ## Installation Methods ### Method 1: Bitbucket Pipe (recommended) Uses the official Purplemet pipe. Handles CLI setup, execution, and artifact management. ```yaml - step: name: Purplemet Security Analysis script: - pipe: docker://ppmsupport/purplemet-analyze-bitbucket:1 variables: PURPLEMET_API_TOKEN: $PURPLEMET_API_TOKEN PURPLEMET_TARGET_URL: "https://your-app.example.com" PURPLEMET_FAIL_SEVERITY: "high" ``` ### Method 2: Docker Image Uses the official CLI Docker image directly. Provides more control. ```yaml - step: name: Purplemet Security Analysis image: ppmsupport/purplemet-cli:latest script: - purplemet-cli analyze "$PURPLEMET_TARGET_URL" --json --fail-on-severity high | tee purplemet-report.json artifacts: - purplemet-report.json ``` ### Method 3: Binary Installation Downloads the CLI binary. Works with any base image. ```yaml - step: name: Purplemet Security Analysis script: - curl -sSL https://raw.githubusercontent.com/purplemet/cli/main/scripts/install.sh | sh - purplemet-cli analyze "$PURPLEMET_TARGET_URL" --json --fail-on-severity high | tee purplemet-report.json artifacts: - purplemet-report.json ``` ## Parameters ### Pipe Variables | Variable | Required | Default | Description | |----------|----------|---------|-------------| | `PURPLEMET_API_TOKEN` | **Yes** | — | API authentication token (secured) | | `PURPLEMET_TARGET_URL` | **Yes** | — | URL of the web application to analyze | | `PURPLEMET_FAIL_SEVERITY` | No | `high` | Severity threshold: `critical`, `high`, `medium`, `low`, `info` | | `PURPLEMET_WAIT_TIMEOUT` | No | `1800000` | Polling timeout in milliseconds (30 min, 0 = unlimited) | | `PURPLEMET_FORMAT` | No | `json` | Output format: `json`, `human`, `sarif`, `html` | | `PURPLEMET_BASE_URL` | No | — | API base URL override | | `DEBUG` | No | `false` | Enable debug output | ### Security Gate Variables | Variable | Default | Description | |----------|---------|-------------| | `PURPLEMET_FAIL_SEVERITY` | `high` | Severity threshold | | `PURPLEMET_FAIL_RATING` | — | Rating threshold: `A`–`F` | | `PURPLEMET_FAIL_CVSS` | `0` | CVSS score threshold (e.g. `9.0`) | | `PURPLEMET_FAIL_ON_EOL` | `false` | Block on end-of-life components | | `PURPLEMET_FAIL_ON_SSL` | `false` | Block on SSL/TLS issues | | `PURPLEMET_FAIL_ON_CERT` | `false` | Block on certificate issues | | `PURPLEMET_FAIL_ON_HEADERS` | `false` | Block on HTTP security header issues | | `PURPLEMET_FAIL_ON_COOKIES` | `false` | Block on insecure cookies | | `PURPLEMET_FAIL_ON_UNSAFE` | `false` | Block on unsafe components | | `PURPLEMET_FAIL_ON_KEV` | `false` | Block on CISA Known Exploited Vulnerabilities | | `PURPLEMET_FAIL_ON_EPSS` | `0` | EPSS score threshold (e.g. `0.75`) | | `PURPLEMET_FAIL_ON_ACTIVE_EXPLOITS` | `false` | Block on actively exploited vulnerabilities | | `PURPLEMET_FAIL_ON_OSSF_SCORE` | `0` | Min OpenSSF Scorecard score (e.g. `5.0`) | | `PURPLEMET_FAIL_ON_CERT_EXPIRY` | `0` | Block if certificate expires within N days | | `PURPLEMET_FAIL_ON_ISSUE_COUNT` | `0` | Block if total issues >= threshold | | `PURPLEMET_REQUIRE_WAF` | `false` | Block if no WAF detected | | `PURPLEMET_FAIL_ON_SENSITIVE_SERVICES` | `false` | Block if sensitive services are exposed | | `PURPLEMET_EXCLUDE_TECH` | — | Block if specified technologies detected (comma-separated) | ## Security Gates Multiple gates can be combined — the analysis fails (exit code 1) if **any** gate triggers. ### Example: Strict Security Policy ```yaml - step: name: Security Analysis (Strict) script: - pipe: docker://ppmsupport/purplemet-analyze-bitbucket:1 variables: PURPLEMET_API_TOKEN: $PURPLEMET_API_TOKEN PURPLEMET_TARGET_URL: "https://your-app.example.com" PURPLEMET_FAIL_SEVERITY: "high" PURPLEMET_FAIL_ON_EOL: "true" PURPLEMET_FAIL_ON_KEV: "true" PURPLEMET_FAIL_ON_SSL: "true" PURPLEMET_REQUIRE_WAF: "true" PURPLEMET_FAIL_ON_CERT_EXPIRY: "30" ``` ## Artifacts | File | Description | |------|-------------| | `purplemet-report.json` | Full analysis results in JSON | | `purplemet-stderr.log` | CLI stderr output (warnings/errors) | ## Complete Pipeline Examples ### Analysis on Every Push ```yaml pipelines: default: - step: name: Purplemet Security Analysis script: - pipe: docker://ppmsupport/purplemet-analyze-bitbucket:1 variables: PURPLEMET_API_TOKEN: $PURPLEMET_API_TOKEN PURPLEMET_TARGET_URL: "https://staging.example.com" PURPLEMET_FAIL_SEVERITY: "high" ``` ### Analysis on Pull Requests Only ```yaml pipelines: pull-requests: '**': - step: name: Security Analysis (PR) script: - pipe: docker://ppmsupport/purplemet-analyze-bitbucket:1 variables: PURPLEMET_API_TOKEN: $PURPLEMET_API_TOKEN PURPLEMET_TARGET_URL: "https://staging.example.com" PURPLEMET_FAIL_SEVERITY: "critical" ``` ### Build → Deploy → Analysis Pipeline ```yaml pipelines: default: - step: name: Build script: - npm ci - npm run build - step: name: Deploy to Staging deployment: staging script: - ./deploy.sh staging - step: name: Security Analysis script: - pipe: docker://ppmsupport/purplemet-analyze-bitbucket:1 variables: PURPLEMET_API_TOKEN: $PURPLEMET_API_TOKEN PURPLEMET_TARGET_URL: "https://staging.example.com" PURPLEMET_FAIL_SEVERITY: "high" - step: name: Deploy to Production deployment: production trigger: manual script: - ./deploy.sh production ``` ### Scheduled Nightly Analysis ```yaml pipelines: custom: nightly-analysis: - step: name: Nightly Security Analysis script: - pipe: docker://ppmsupport/purplemet-analyze-bitbucket:1 variables: PURPLEMET_API_TOKEN: $PURPLEMET_API_TOKEN PURPLEMET_TARGET_URL: "https://production.example.com" PURPLEMET_FAIL_SEVERITY: "medium" ``` Configure a schedule in **Repository Settings** → **Pipelines** → **Schedules** pointing to `nightly-analysis`. ### Multi-Site Analysis (Parallel) ```yaml pipelines: default: - parallel: - step: name: Analyze App 1 script: - pipe: docker://ppmsupport/purplemet-analyze-bitbucket:1 variables: PURPLEMET_API_TOKEN: $PURPLEMET_API_TOKEN PURPLEMET_TARGET_URL: "https://app1.example.com" - step: name: Analyze App 2 script: - pipe: docker://ppmsupport/purplemet-analyze-bitbucket:1 variables: PURPLEMET_API_TOKEN: $PURPLEMET_API_TOKEN PURPLEMET_TARGET_URL: "https://app2.example.com" ``` ### Warning Mode (Non-blocking) ```yaml pipelines: default: - step: name: Security Analysis (Non-blocking) image: ppmsupport/purplemet-cli:latest script: - purplemet-cli analyze "$PURPLEMET_TARGET_URL" --json --fail-on-severity high || true after-script: - echo "Analysis completed (exit code $BITBUCKET_EXIT_CODE)" artifacts: - purplemet-report.json ``` ### Full Pipeline with Strict Gates ```yaml pipelines: default: - step: name: Build & Test script: - npm ci - npm test - step: name: Deploy Staging deployment: staging script: - ./deploy.sh - step: name: Security Analysis script: - pipe: docker://ppmsupport/purplemet-analyze-bitbucket:1 variables: PURPLEMET_API_TOKEN: $PURPLEMET_API_TOKEN PURPLEMET_TARGET_URL: "https://staging.example.com" PURPLEMET_FAIL_SEVERITY: "high" PURPLEMET_FAIL_ON_EOL: "true" PURPLEMET_FAIL_ON_KEV: "true" PURPLEMET_FAIL_ON_SSL: "true" PURPLEMET_FAIL_ON_CERT_EXPIRY: "30" PURPLEMET_REQUIRE_WAF: "true" - step: name: Deploy Production deployment: production trigger: manual script: - ./deploy.sh ``` ## Results and Exit Codes ### Exit Codes | Code | Meaning | Pipeline Behavior | |------|---------|-------------------| | **0** | No issues above threshold | Step **passes** | | **1** | Issues found above threshold | Step **fails** | | **2** | Analysis error on Purplemet | Step **fails** | | **3** | Timeout exceeded | Step **fails** | | **4** | Network or API error | Step **fails** | | **5** | Usage error (bad config) | Step **fails** | | **6** | API contract error | Step **fails** | ### Security Rating and Severity Levels Ratings (`A`–`F`) and severity levels (`CRITICAL`/`HIGH`/`MEDIUM`/`LOW`/`INFO`) are computed and defined by the Purplemet platform. See the [official Purplemet documentation](https://cloud.purplemet.com/docs/#/web%20applications/security-rating) for authoritative definitions. ## Advanced Usage ### Pin a Specific Pipe Version ```yaml - pipe: docker://ppmsupport/purplemet-analyze-bitbucket:1.0.0 # exact - pipe: docker://ppmsupport/purplemet-analyze-bitbucket:1 # latest 1.x - pipe: docker://ppmsupport/purplemet-analyze-bitbucket:latest # latest ``` ### Generate HTML Report ```yaml - step: name: Security Analysis + HTML Report image: ppmsupport/purplemet-cli:latest script: - purplemet-cli analyze "$PURPLEMET_TARGET_URL" --format html --output-file purplemet-report.html --fail-on-severity high || true artifacts: - purplemet-report.html ``` ### Custom Exit Code Handling ```yaml - step: name: Security Analysis image: ppmsupport/purplemet-cli:latest script: - set +e - purplemet-cli analyze "$PURPLEMET_TARGET_URL" --json --fail-on-severity high | tee purplemet-report.json - EXIT_CODE=$? - set -e - | case $EXIT_CODE in 0) echo "Analysis passed" ;; 1) echo "WARNING: vulnerabilities found" ;; 2) echo "Analysis error" ;; 3) echo "Timeout" ;; *) echo "Error (code $EXIT_CODE)" ;; esac - exit $EXIT_CODE artifacts: - purplemet-report.json ``` ## FAQ / Common Errors ### `PURPLEMET_API_TOKEN is required` The token variable is missing or empty. **Fix:** Add `PURPLEMET_API_TOKEN` as a secured repository variable: Repository Settings → Pipelines → Repository variables. --- ### `PURPLEMET_TARGET_URL is required` **Fix:** Set the `PURPLEMET_TARGET_URL` variable in the pipe call or as a repository variable. --- ### "Access is not authorized without a valid session" The API token is invalid or expired. **Fix:** 1. Verify: `purplemet-cli auth check` 2. Create a new token at [cloud.purplemet.com](https://cloud.purplemet.com/#/tokens/create) 3. Update the repository variable --- ### Analysis times out (exit code 3) **Fix:** Increase `PURPLEMET_WAIT_TIMEOUT` (default is `1800000` / 30 min): ```yaml PURPLEMET_WAIT_TIMEOUT: "3600000" # 60 minutes ``` Or set to `0` for no limit. --- ### Pipeline fails with exit code 1 but I want it to continue Exit code 1 means vulnerabilities were found above the threshold. **Fix:** Append `|| true` to the analysis command: ```yaml script: - purplemet-cli analyze "$PURPLEMET_TARGET_URL" --json --fail-on-severity high || true ``` Or use `after-script` for post-processing regardless of exit code. --- ### Image pull fails **Fix:** Verify the image exists on Docker Hub: `ppmsupport/purplemet-analyze-bitbucket` or `ppmsupport/purplemet-cli`. --- ### Network error (exit code 4) **Fix:** Ensure Bitbucket runners can reach `api.purplemet.com` on port 443. Set `PURPLEMET_BASE_URL` for custom endpoints. --- ### How do I analyze multiple sites? Use parallel steps (see [Multi-Site Analysis example](#multi-site-analysis-parallel)). --- ### Where can I see the results? 1. **Pipeline log**: Summary in the step output 2. **Artifacts**: Download `purplemet-report.json` from the pipeline page 3. **Purplemet dashboard**: [cloud.purplemet.com](https://cloud.purplemet.com) for detailed results