@exploitq/cli
v1.0.3
Published
ExploitQ CLI — SAST, SCA, API security, and secrets scanning for CI/CD pipelines
Downloads
239
Maintainers
Readme
ExploitQ CLI
Developer-first application security scanner — SAST, SCA, and API security scanning with exploitability-based prioritization. Block builds on findings that are actively being exploited in the wild, not just theoretical vulnerabilities.
Table of Contents
- Installation
- Quick Start
- GitHub Actions
- Jenkins Shared Library
- Bitbucket Pipelines
- Configuration File
- CLI Reference
- Environment Variables
- Policy Modes
- Outputs
Installation
Global npm install (Node.js 20+):
npm install -g @exploitq/cli
exploitq --versionDocker:
docker pull ghcr.io/exploitq/exploitq-cli:latest
docker run --rm -v "$(pwd):/workspace" \
-e EXPLOITQ_API_URL=https://app.exploitqsecurity.com \
-e EXPLOITQ_TOKEN=ek_... \
ghcr.io/exploitq/exploitq-cli:latest \
scan --path /workspace --uploadQuick Start
# Scan current directory (SAST + SCA + API security)
exploitq scan
# Scan with policy enforcement — fail the build on critical/high findings
exploitq scan --policy-mode hard_fail --fail-on CRITICAL,HIGH
# Upload results to the ExploitQ dashboard
EXPLOITQ_API_URL=https://app.exploitqsecurity.com \
EXPLOITQ_TOKEN=ek_your_token_here \
exploitq scan --upload
# Output SARIF for IDE integration or GitHub Security tab
exploitq scan --format sarif --output ./resultsGitHub Actions
Add ExploitQ to any workflow. Results appear inline on PR diffs and in the GitHub Security → Code Scanning tab.
Minimal setup
name: Security Scan
on:
pull_request:
push:
branches: [main]
jobs:
exploitq:
name: ExploitQ Security Scan
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write # required for SARIF upload
steps:
- uses: actions/checkout@v4
- uses: exploitq/exploitq@v1
with:
api-url: ${{ secrets.EXPLOITQ_API_URL }}
api-token: ${{ secrets.EXPLOITQ_TOKEN }}Full configuration
- uses: exploitq/exploitq@v1
with:
# ExploitQ platform connection
api-url: ${{ secrets.EXPLOITQ_API_URL }}
api-token: ${{ secrets.EXPLOITQ_TOKEN }}
# Scan configuration
path: .
scan-types: sast,sca,api # comma-separated
# Policy enforcement
policy-mode: hard_fail # advisory | soft_fail | hard_fail
fail-on: CRITICAL,HIGH # comma-separated severities
# Reporting
upload-results: true # upload to dashboard
upload-sarif: true # upload to GitHub Security tab
output-dir: exploitq-results # where to write JSON + SARIF
# Miscellaneous
cli-version: latest # pin to e.g. 1.2.3
verbose: falseUsing outputs
- uses: exploitq/exploitq@v1
id: scan
with:
api-url: ${{ secrets.EXPLOITQ_API_URL }}
api-token: ${{ secrets.EXPLOITQ_TOKEN }}
policy-mode: advisory
- name: Print scan summary
run: |
echo "Policy result : ${{ steps.scan.outputs.policy-result }}"
echo "Total findings : ${{ steps.scan.outputs.finding-count }}"
echo "Critical : ${{ steps.scan.outputs.critical-count }}"
echo "High : ${{ steps.scan.outputs.high-count }}"
echo "Dashboard : ${{ steps.scan.outputs.dashboard-url }}"| Output | Description |
|---|---|
| policy-result | pass, fail, or advisory |
| finding-count | Total findings across all engines |
| critical-count | Critical-severity findings |
| high-count | High-severity findings |
| sarif-file | Path to the generated SARIF file |
| dashboard-url | Link to the scan report in the ExploitQ dashboard |
Jenkins Shared Library
1. Register the shared library
In Manage Jenkins → Configure System → Global Pipeline Libraries, add:
| Field | Value |
|---|---|
| Name | exploitq |
| Default version | main |
| Retrieval method | Modern SCM → Git |
| Project repository | https://github.com/exploitq/exploitq.git |
| Library path | artifacts/cli/jenkins |
2. Add to any Jenkinsfile
@Library('exploitq') _
pipeline {
agent any
environment {
EXPLOITQ_API_URL = credentials('EXPLOITQ_API_URL')
EXPLOITQ_TOKEN = credentials('EXPLOITQ_TOKEN')
}
stages {
stage('Checkout') {
steps { checkout scm }
}
stage('Security Scan') {
steps {
exploitqScan(
apiUrl: env.EXPLOITQ_API_URL,
token: env.EXPLOITQ_TOKEN,
path: '.',
scanTypes: 'sast,sca,api',
policyMode: 'hard_fail',
failOn: 'CRITICAL,HIGH',
upload: true,
uploadSarif: true,
)
}
}
stage('Build') {
steps { sh 'npm run build' }
}
}
post {
always {
cleanWs(patterns: [[pattern: 'exploitq-results/**', type: 'INCLUDE']])
}
}
}Jenkins shared library parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| apiUrl | String | '' | ExploitQ platform URL |
| token | String | '' | API token (use Jenkins Credentials) |
| path | String | '.' | Repository path to scan |
| scanTypes | String | 'sast,sca,api' | Comma-separated scan engines |
| policyMode | String | 'advisory' | advisory | soft_fail | hard_fail |
| failOn | String | 'CRITICAL,HIGH' | Severity thresholds |
| upload | Boolean | true | Upload results to dashboard |
| uploadSarif | Boolean | true | Archive SARIF as build artifact |
| outputDir | String | 'exploitq-results' | Result output directory |
| cliVersion | String | 'latest' | npm package version to install |
| verbose | Boolean | false | Verbose CLI output |
| nodeVersion | String | '22' | Node.js version on the agent |
Tip: If the Warnings Next Generation plugin is installed, SARIF results are automatically published as inline diff annotations in the build. Without the plugin, SARIF is archived as a build artifact.
Bitbucket Pipelines
Add the pipe to bitbucket-pipelines.yml
image: node:22
pipelines:
pull-requests:
'**':
- step:
name: ExploitQ Security Scan
script:
- pipe: ghcr.io/exploitq/exploitq-pipe:latest
variables:
EXPLOITQ_API_URL: $EXPLOITQ_API_URL
EXPLOITQ_TOKEN: $EXPLOITQ_TOKEN
SCAN_TYPES: sast,sca,api
POLICY_MODE: hard_fail
FAIL_ON: CRITICAL,HIGH
UPLOAD_RESULTS: "true"
branches:
main:
- step:
name: ExploitQ Security Scan (advisory)
script:
- pipe: ghcr.io/exploitq/exploitq-pipe:latest
variables:
EXPLOITQ_API_URL: $EXPLOITQ_API_URL
EXPLOITQ_TOKEN: $EXPLOITQ_TOKEN
POLICY_MODE: advisoryStore EXPLOITQ_API_URL and EXPLOITQ_TOKEN as masked Bitbucket Repository Variables (Settings → Repository variables).
Bitbucket pipe variables
| Variable | Required | Default | Description |
|---|---|---|---|
| EXPLOITQ_API_URL | No | — | ExploitQ platform URL |
| EXPLOITQ_TOKEN | No | — | API token (mask this variable) |
| SCAN_PATH | No | . | Path to scan |
| SCAN_TYPES | No | sast,sca,api | Comma-separated engines |
| POLICY_MODE | No | advisory | advisory | soft_fail | hard_fail |
| FAIL_ON | No | CRITICAL,HIGH | Severity thresholds |
| UPLOAD_RESULTS | No | true | Upload to dashboard |
| OUTPUT_DIR | No | exploitq-results | Output directory |
| VERBOSE | No | false | Verbose output |
| DEBUG | No | false | Enable set -x in the pipe script |
Configuration File
Create .exploitq.yml in your repository root to set project-level defaults. CLI flags and CI/CD variables override config file values.
version: 1
scan:
types: [sast, sca, api]
paths:
include:
- src/
- lib/
exclude:
- "**/__tests__/**"
- "**/node_modules/**"
- "**/vendor/**"
api:
spec_paths:
- openapi.yml
- docs/api.yaml
policy:
mode: hard_fail # advisory | soft_fail | hard_fail
fail_on: [CRITICAL, HIGH]
block_on_actively_exploited: true # block even MEDIUM if KEV/CISA listed
epss_threshold: 0.5 # block if EPSS score > 50 %
reporting:
formats: [json, sarif]
upload: true
metadata:
service: payments-api
team: platform-securityCLI Reference
exploitq scan
Run SAST, SCA, and API security scans.
Options:
--path <dir> Path to scan (default: ".")
--scan-types <types> Comma-separated engines: sast,sca,api (default: "sast,sca,api")
--provider <p> CI/CD provider: github|gitlab|ado|bitbucket|jenkins|local (default: "local")
--repo <repo> Repository full name (e.g. org/repo)
--commit <sha> Git commit SHA
--branch <branch> Branch name
--pr <number> Pull / merge request number
--format <formats> Output formats: json,sarif (default: "json")
--output <dir> Output directory (default: "./exploitq-results")
--upload Upload results to ExploitQ API
--policy-mode <mode> Policy mode: advisory|soft_fail|hard_fail
--config <file> Path to .exploitq.yml config file
--verbose Verbose outputExit codes:
| Code | Meaning |
|---|---|
| 0 | Scan complete, policy passed (or advisory mode) |
| 1 | Policy gate failed (hard_fail + findings above threshold) |
| 3 | Invalid path or config file error |
| 4 | Upload error in non-advisory mode |
exploitq upload
Upload a pre-existing results.json to the ExploitQ dashboard.
Options:
--file <path> Path to results.json (default: "./exploitq-results/results.json")
--verbose Verbose outputexploitq policy-check
Re-evaluate the policy for a results.json without re-scanning.
Options:
--file <path> Path to results.json (default: "./exploitq-results/results.json")
--policy-mode <mode> Policy mode override
--fail-on <sevs> Severity threshold override
--verbose Verbose outputEnvironment Variables
| Variable | Description |
|---|---|
| EXPLOITQ_API_URL | ExploitQ platform URL (e.g. https://app.exploitqsecurity.com) |
| EXPLOITQ_TOKEN | API token — generate one in Settings → API Keys |
Policy Modes
| Mode | Behavior |
|---|---|
| advisory | Record all findings. Never fail the build. Best for initial rollout. |
| soft_fail | Print a warning when findings exceed the threshold but exit 0. |
| hard_fail | Exit 1 when findings exceed the threshold. Blocks merges and deployments. |
Secrets setup checklist
- Generate an API token in ExploitQ → Settings → API Keys.
- Add it as a repository secret:
- GitHub Actions:
EXPLOITQ_TOKEN+EXPLOITQ_API_URL - Jenkins: Jenkins Credentials store (Secret Text) with IDs
EXPLOITQ_TOKENandEXPLOITQ_API_URL - Bitbucket: Repository variables (enable Masked)
- GitHub Actions:
- Start with
policy-mode: advisoryuntil the finding baseline is understood, then tighten tosoft_fail→hard_fail.
License
Proprietary — exploitq.com
