{"id":16827,"plugin_id":"plugins_6a6b9d24410881919783cadcf32c8e37","kind":"skill","collection_source":null,"comparison_source":null,"observed_at":"2026-09-30T23:13:48.779Z","digest":"54a9a01ea4c8f8775ed028dcdc0c22d89a9a09927653f5c0ef7bdfd54e0673d8","against":null,"payload":{"name":"ci-cd-integration","description":"Guide for agents to help users integrate NightVision DAST scanning into CI/CD pipelines. Use when setting up security scans in GitHub Actions, GitLab CI, Azure DevOps, Jenkins, BitBucket, or JFrog pipelines, configuring NightVision tokens, creating targets, running scans, exporting results as SARIF/CSV, or detecting API breaking changes.","included_files":[{"relative_path":"references/ci-platforms.md","size_in_bytes":12215}],"skill_md_contents":"---\nname: ci-cd-integration\ndescription: Guide for agents to help users integrate NightVision DAST scanning into CI/CD pipelines. Use when setting up security scans in GitHub Actions, GitLab CI, Azure DevOps, Jenkins, BitBucket, or JFrog pipelines, configuring NightVision tokens, creating targets, running scans, exporting results as SARIF/CSV, or detecting API breaking changes.\nallowed-tools: Bash\n---\n\n# NightVision CI/CD Integration\n\nUse this skill when helping users add NightVision security scanning to their CI/CD pipelines. NightVision is a white-box-assisted DAST tool that finds exploitable vulnerabilities in web applications and REST APIs. It combines API Discovery (static analysis to extract OpenAPI specs from source code) with dynamic scanning (ZAP + Nuclei engines), and traces vulnerabilities back to exact source code locations (Code Traceback).\n\n## Agent workflow\n\nWhen a user asks to set up NightVision in their pipeline:\n\n1. **Check prerequisites** — verify the NightVision CLI is available (`nightvision --help`). If not installed, see the Installation section below.\n2. **Examine the repo** — look for existing CI configs (`.github/workflows/`, `.gitlab-ci.yml`, `Jenkinsfile`, `bitbucket-pipelines.yml`, `azure-pipelines.yml`) to understand the CI platform and existing pipeline structure\n3. **Ask the user** what you can't determine from the repo:\n   - Target URL (staging/production endpoint to scan)\n   - Target type — web app or API?\n   - Does the app require authentication to scan?\n   - What language is the backend? (needed for API Discovery)\n   - Have they already created a NightVision project, target, and token?\n4. **Tell the user what they must do locally** — some steps require interactive browser sessions that the agent cannot perform (see Prerequisites below)\n5. **Generate the pipeline config** — adapt the patterns below and the platform-specific examples in [references/ci-platforms.md](references/ci-platforms.md) to the user's repo, substituting their target name, language, app startup method, and CI platform conventions\n\n**Related skills:** Use `scan-configuration` for detailed target/auth setup, `api-discovery` for spec extraction details, `scan-triage` for interpreting results.\n\n## Pipeline structure\n\nEvery NightVision CI pipeline follows this pattern:\n\n```\n1. Install the NightVision CLI\n2. Extract API spec from source code (API targets only)\n3. Start the application (private/local targets only)\n4. Run the scan (CLI polls until completion, ~5-15 min)\n5. Export results (SARIF / CSV / GitLab DAST)\n6. Upload to CI platform (GitHub Security, GitLab DAST, Azure Boards, Jenkins Warnings)\n```\n\n## Prerequisites the user must complete\n\nThese steps require interactive sessions (browser login, GUI) that the agent cannot perform. Instruct the user to run these locally before the pipeline will work.\n\n**1. Create an API token** — requires browser-based login:\n```bash\nnightvision login\nnightvision token create                          # no expiry\nnightvision token create --expiry-date 2026-12-31 # with expiry\n```\nTokens can also be created in the NightVision web UI: Profile > Settings > Tokens. The user must store the token as a CI secret named `NIGHTVISION_TOKEN`.\n\n**2. Record authentication** (if the target requires login) — Playwright recording opens a browser:\n```bash\nnightvision auth playwright create my-auth https://myapp.example.com\n# A Chrome window opens — user completes login, then closes the window\n```\nFor API key / bearer token auth, the agent can help construct the command:\n```bash\nnightvision auth headers create my-auth \\\n  -H \"Authorization: Bearer <token>\"\n```\n\n**3. Create the target** — the agent can help with this if `NIGHTVISION_TOKEN` is available:\n```bash\n# Web target\nnightvision target create my-web-app https://staging.example.com --type WEB -p my-project\n\n# API target with local spec\nnightvision target create my-api https://api.example.com --type API -p my-project \\\n  --spec-file openapi-spec.yml\n\n# API target with remote spec URL\nnightvision target create my-api https://api.example.com --type API -p my-project \\\n  --spec-url https://api.example.com/docs/openapi.json\n\n# Idempotent create-or-update (useful in pipelines)\nnightvision target create my-api $URL --type API -p my-project --spec-file spec.yml \\\n  || nightvision target update my-api -p my-project --spec-file spec.yml\n```\n\n## Installation (in the pipeline)\n\n```bash\n# Linux Intel (standard for most CI runners)\ncurl -L https://downloads.nightvision.net/binaries/latest/nightvision_latest_linux_amd64.tar.gz | tar -xz\nsudo mv nightvision /usr/local/bin/\n```\n\nFor Linux ARM runners, substitute `linux_arm64` in the URL.\n\n## Environment variables\n\n| Variable | Required | Purpose |\n|----------|----------|---------|\n| `NIGHTVISION_TOKEN` | Yes | API token (store as CI secret) |\n| `NIGHTVISION_API_URL` | No | API endpoint (default: `https://api.nightvision.net/api/v1/`) |\n\nAll config keys accept env vars with the `NIGHTVISION_` prefix (hyphens become underscores).\n\n## CLI output format\n\nMost `list` and `get` commands default to text output. Use `--format json` (or `-F json`) for machine-parseable output, or `--format table` for tabular display.\n\n## API Discovery (spec extraction from source code)\n\nFor API targets, extract OpenAPI specs via static analysis. Supports Go, Python, Java, Ruby, C#, JavaScript.\n\n```bash\n# Extract and upload to a target\nnightvision swagger extract . -t my-api -p my-project --lang python\n\n# Extract locally without uploading\nnightvision swagger extract . -o openapi-spec.yml --lang java --no-upload\n\n# Compare specs for breaking changes (useful in PR checks)\nnightvision swagger diff old-spec.yml new-spec.yml\n```\n\n**Important CI pattern — extraction fallback:** Extraction can fail if language detection fails. Always use:\n```bash\nnightvision swagger extract . -t $TARGET --lang java || true\nif [ ! -e openapi-spec.yml ]; then cp backup-openapi-spec.yml openapi-spec.yml; fi\n```\n\n### Code Traceback\n\nWhen API Discovery generates the spec, it annotates endpoints with file paths and line numbers. Vulnerabilities found during scanning trace back to exact source locations. This powers the file/line links in GitHub Security Alerts, Azure Boards work items, and similar CI integrations.\n\n## Running scans\n\n```bash\n# Basic scan\nnightvision scan my-target -p my-project\n\n# Authenticated scan\nnightvision scan my-target -p my-project --auth my-auth\n\n# Unauthenticated (explicit, skip any stored credentials)\nnightvision scan my-target -p my-project --no-auth\n\n# Extended duration (default 30 min, max 480 min / 8 hours)\nnightvision scan my-target -p my-project --max-duration-minutes 120\n\n# Engine selection\nnightvision scan my-target -p my-project --no-nuclei   # ZAP only\nnightvision scan my-target -p my-project --no-zap      # Nuclei only\n\n# Verbose logging (recommended for CI debugging)\nnightvision scan my-target -p my-project --verbose\n```\n\n### Capturing the scan ID\n\nIn CI (non-interactive), the CLI prints the scan ID as the first line of stdout. Use this pattern:\n\n```bash\nnightvision scan $TARGET --auth $AUTH > scan-results.txt\nSCAN_ID=$(head -n 1 scan-results.txt)\n```\n\n### Exit codes\n\n| Code | Meaning |\n|------|---------|\n| 0 | Scan completed successfully (`SUCCEEDED`). Vulnerabilities may still have been found. |\n| 1 | Scan failed (`FAILED`, `ABORTED`, `TIMED_OUT`), or other error. |\n\n**Exit code 0 does not mean \"no vulnerabilities.\"** Use export commands to inspect findings.\n\nOn failure (exit code 1), the CLI prints a status-specific error message:\n- **TIMED_OUT** — includes the configured `--max-duration-minutes` value and suggests increasing it\n- **ABORTED** — indicates the scan was aborted (by user or system)\n- **FAILED** — includes a link to the dashboard for investigation\n\nWhen the API provides a failure reason, it is included in the error message and displayed in the TUI dashboard.\n\n### Private / internal targets (Smart Proxy)\n\nNightVision's Smart Proxy automatically tunnels scan traffic through the CLI when the target is not publicly reachable (localhost, Docker, Kubernetes, corporate networks). No configuration needed — it's built into the CLI.\n\nUse `--force-private-scan` to force tunneling when the target appears publicly accessible but isn't from the scanner's perspective.\n\n## Exporting results\n\n```bash\n# SARIF with Code Traceback (API targets — provide the spec used for the scan)\nnightvision export sarif -s \"$SCAN_ID\" --swagger-file openapi-spec.yml -o results.sarif\n\n# SARIF without Code Traceback (WEB targets, or when no spec is available)\nnightvision export sarif -s \"$SCAN_ID\" -o results.sarif\n\n# CSV (for reports, spreadsheets, custom processing)\nnightvision export csv -s \"$SCAN_ID\" -o results.csv\n\n# GitLab DAST report (for the GitLab Vulnerability dashboard)\nnightvision export gitlab -s \"$SCAN_ID\" --swagger-file openapi-spec.yml -o gl-dast-report.json\n\n# Jira tickets (one per finding; severity sets priority; status changes sync back to findings)\n# --jira-token is a classic user API token. For an Atlassian service-account token\n# (always scoped), pass --jira-cloud-id <id> instead of --base-url (scopes: read:jira-work, write:jira-work).\nnightvision export jira -s \"$SCAN_ID\" --project-key SEC \\\n  --base-url https://your-org.atlassian.net --user-email you@example.com --jira-token \"$JIRA_TOKEN\"\n```\n\n`--swagger-file` is optional. When provided, SARIF output includes Code Traceback source annotations (file paths and line numbers linking findings to source code). When omitted, the SARIF is still valid but won't contain source locations. Always provide `--swagger-file` for API targets when the spec is available.\n\n## CI platform quick reference\n\nSee [references/ci-platforms.md](references/ci-platforms.md) for complete, copy-pasteable pipeline configs.\n\n| Platform | Results surface | Upload mechanism |\n|----------|----------------|-----------------|\n| GitHub Actions | Security tab (Code Scanning) | `github/codeql-action/upload-sarif@v3` (needs `permissions: contents: read, security-events: write`) |\n| GitLab CI | Vulnerability dashboard | `nightvision export gitlab`, `artifacts.reports.dast` |\n| Azure DevOps | Azure Boards work items | `sarif-manager azure create-work-items` |\n| Jenkins | Warnings Next Generation | `recordIssues tool: sarif(pattern: 'results.sarif')` |\n| BitBucket | Pipeline artifacts | SARIF as artifact |\n| JFrog | Evidence on Docker packages | `jf evd create` with SARIF predicate |\n\n## Troubleshooting\n\n| Symptom | Cause | Fix |\n|---------|-------|-----|\n| \"login authentication token has expired\" | Token expired or invalid | `nightvision token create`, update CI secret |\n| \"API is unreachable\" | Network/firewall issue | Check `NIGHTVISION_API_URL`, network connectivity |\n| \"SSL certificate error\" | TLS verification failed | Fix certs, or `--skip-tls-verify` (not for production) |\n| Scan `TIMED_OUT` | Exceeded max duration | CLI error message shows the current limit; increase `--max-duration-minutes` (up to 480) |\n| Scan `ABORTED` | Scan was cancelled by user or system | Check the failure reason in the CLI output or dashboard |\n| Scan `FAILED` | Engine error or target unreachable | CLI error includes a dashboard link; also use `--verbose` and verify target is up |\n| 401 Unauthorized during scan | Auth credentials expired | Re-record authentication locally |\n| \"Repository not found\" in checkout | `permissions` block missing `contents: read` | Add `contents: read` alongside `security-events: write` in the workflow permissions |\n"},"changes":[],"summary":"First saved snapshot. No earlier version is available for comparison.","summary_kind":"deterministic","summary_metadata":{}}