Skip to main content

Production-grade CLI for managing DefectDojo

Project description

dd-cli

PyPI Python CI Docs License

A production-grade CLI for managing DefectDojo — list / create / update / delete every resource the API exposes, plus a fully backward-compatible import path for users coming from the original dd-import tool (now archived).

pip install dd-cli
$ dd --help

 Usage: dd [OPTIONS] COMMAND [ARGS]...

 Production-grade CLI for managing DefectDojo.

 Commands:
   configure          Interactively create or update a profile.
   ping               Verify connectivity and authentication against DefectDojo.
   config             Manage dd-cli profiles and on-disk configuration.
   products           List and get DefectDojo products.
   product-types      List and get DefectDojo product types.
   engagements        List and get DefectDojo engagements.
   tests              List and get DefectDojo tests.
   findings           List and get DefectDojo findings.
   users              List and get DefectDojo users.
   dojo-groups        List and get DefectDojo authorization groups.
   jira-instances     List and get DefectDojo Jira instance configurations.
   risk-acceptances   List and get DefectDojo risk acceptances.
   metadata           List and get DefectDojo metadata entries.
   endpoints          List and get DefectDojo endpoints.
   finding-templates  List and get DefectDojo finding templates.
   import             Import scanner findings or language data into DefectDojo.

Why dd-cli

  • Complete API coverage. Every read and write across 12 DefectDojo resource types — products, product-types, engagements, tests, findings, users, dojo-groups, jira-instances, risk-acceptances, metadata, endpoints, finding-templates — driven from a typed client generated from DefectDojo's OpenAPI spec.
  • Drop-in replacement for dd-import. Existing CI pipelines that invoke dd-reimport-findings or dd-import-languages with DD_* env vars keep working unchanged. The legacy console scripts are wired as thin shims over the new workflow code.
  • Pleasant interactive use. Rich tables, JSON / YAML output for piping, profiles for switching between DefectDojo instances, dd configure interactive setup, dd <resource> edit <id> opens the resource as YAML in $EDITOR, action verbs like dd findings close, risk-accept, dd engagements close/reopen.
  • Safe writes. --dry-run previews every mutation without sending HTTP. --yes/-y skips the destructive-op confirmation prompt for scripts. Typed exit codes (auth=3, not-found=5, etc.) so CI can branch on what went wrong.
  • Board-ready reports. dd report generate --product 42 emits a polished Markdown + HTML report with SLA aging, KEV exposure, EPSS, scan-over-scan deltas, and formal risk-acceptance — fields the built-in DefectDojo report doesn't surface. Open the HTML in any browser → Save as PDF.
  • Validated against real DefectDojo. 24 integration tests run against a live instance per release, including a full Trivy-report import round-trip.

Install

From PyPI (recommended)

pip install dd-cli
# or, for an isolated install of the CLI:
pipx install dd-cli

dd, dd-reimport-findings, and dd-import-languages go on PATH.

From source

git clone https://github.com/OsamaMahmood/dd-cli.git
cd dd-cli
pip install -e ".[dev,test]"

Docker

podman run --rm \
  -e DD_URL=https://defectdojo.example.com \
  -e DD_API_KEY= \
  ghcr.io/osamamahmood/dd-cli:latest \
  ping     # or any other dd subcommand

Docker images are published to ghcr.io/osamamahmood/dd-cli (GitHub Container Registry) and m4rkm3n/dd-cli (Docker Hub) on each tag.

Quickstart

# 1. Set up a profile (writes ~/.config/dd-cli/config.toml)
dd configure
# Profile name [default]: default
# DefectDojo URL: https://defectdojo.example.com
# API key (hidden): …
# Verify TLS certificates? [Y/n]: Y

# 2. Confirm it works
dd ping
# {"ok": true, "user": "alice", "url": "https://defectdojo.example.com"}

# 3. Browse
dd products list --output json | jq
dd findings list --severity Critical --active --output json | jq

# 4. Manage
dd findings close 42 --note "Fixed in v2.1.0" --yes
dd findings risk-accept 51 --until 2026-12-31 --reason "Compensating WAF rule"
dd engagements close 12 --yes
dd users deactivate alice --yes

# 5. Import a scanner report
dd import findings \
  --file trivy.json \
  --scanner "Trivy Scan" \
  --product-type "Web Apps" \
  --product "Payments" \
  --auto-create

# 6. Generate a polished Markdown + HTML report for a product
dd report generate --product 42 --detailed --with-history

Configuration

dd-cli resolves settings in this order (later wins):

  1. Built-in defaults
  2. The active profile in ~/.config/dd-cli/config.toml (or $DD_CLI_CONFIG_DIR/config.toml)
  3. DD_* environment variables (legacy contract, see migration)
  4. DD_CLI_* environment variables (modern names, take precedence over DD_*)
  5. Explicit CLI flags

API tokens are stored as pydantic.SecretStr and masked in dd config show output unless you pass --show-secrets to dd config get api_key.

Profiles

Switch between multiple DefectDojo instances with named profiles:

dd configure --profile prod
dd configure --profile staging
dd config use prod          # default profile when --profile isn't given
dd --profile staging products list

Output formats

Every read command supports --output table|json|yaml (default: table). YAML and JSON are stable and pipe-friendly:

dd findings list --severity High --output json | jq '.[] | {id, title, severity}'

Importing scanner findings

The new ergonomic form:

dd import findings \
  --file trivy.json \
  --scanner "Trivy Scan" \
  --product-type "Web Apps" \
  --product "Payments" \
  --engagement "Q4 Release" \
  --test-name "Trivy" \
  [--auto-create | --traditional] \
  [--minimum-severity Medium] \
  [--push-to-jira] [--close-old-findings] \
  [--dry-run] [--yes] [--output table|json|yaml]

Two modes:

  • --auto-create (recommended) — single API call. DefectDojo creates the product, engagement, and test as needed.
  • --traditional — find-or-create each resource explicitly, then upload. Useful when DefectDojo's auto-create logic disagrees with what you want.

Either mode reads the same DD_* env vars the legacy tool used; CLI flags override env vars.

From CI/CD

# GitHub Actions
- name: Trivy
  run: trivy fs --format json -o trivy.json .

- name: Upload to DefectDojo
  env:
    DD_URL: ${{ secrets.DD_URL }}
    DD_API_KEY: ${{ secrets.DD_API_KEY }}
  run: |
    pip install dd-cli
    dd import findings \
      --file trivy.json \
      --scanner "Trivy Scan" \
      --product-type "Web Apps" \
      --product "${{ github.repository }}" \
      --engagement "${{ github.ref_name }}" \
      --test-name "Trivy" \
      --auto-create \
      --yes
# GitLab CI
upload_findings:
  image: dd-cli:latest
  variables:
    DD_PRODUCT_TYPE_NAME: "Web Apps"
    DD_PRODUCT_NAME: "$CI_PROJECT_NAME"
    DD_ENGAGEMENT_NAME: "$CI_COMMIT_REF_SLUG"
    DD_TEST_NAME: "Trivy"
    DD_TEST_TYPE_NAME: "Trivy Scan"
    DD_FILE_NAME: "trivy.json"
    DD_AUTO_CREATE_CONTEXT: "true"
  script:
    - dd-reimport-findings    # legacy console script — still works

Importing language statistics

cloc JSON output for a product:

cloc src --json --out cloc.json
dd import languages --file cloc.json --product-type "Web Apps" --product "Payments"

Migrating from dd-import

dd-cli is a drop-in replacement. Existing pipelines work unchanged — install dd-cli, the legacy console scripts and all DD_* env vars stay valid:

Legacy Replacement Status
dd-reimport-findings dd-reimport-findings (shim) or dd import findings (new) both work; DD_* env vars unchanged
dd-import-languages dd-import-languages (shim) or dd import languages (new) both work; DD_* env vars unchanged
pip install dd-import pip install dd-cli new package name
osamamahmood/dd-import:latest (Docker) ghcr.io/osamamahmood/dd-cli:latest swap image, no other changes

Recommended migration path:

  1. Today: swap the install command (pip install dd-cli) or the Docker image. Pipelines keep working.
  2. When convenient: migrate to the new ergonomic commands (dd import findings --file …) for --dry-run, typed exit codes, profile support.

The new and legacy entry points have one deliberate difference:

  • dd-reimport-findings exits 1 on any failure (legacy contract — pipelines that grep $? keep working)
  • dd import findings exits with typed codes: 3 (auth), 5 (not found), 6 (validation), 7 (API), 8 (network), 9 (config). Useful for branching CI logic.

A full DD_* env-var reference lives in the Configuration guide and is pinned by a 9-test @pytest.mark.compat suite in tests/compat/.

Documentation

  • Documentation site — install, quickstart, configuration, CLI reference, reporting, CI recipes, migration guide
  • RELEASING.md — how releases are cut and published
  • CLAUDE.md + .claude/ — contributor + agent ramp-up docs (architecture, conventions, workflows, decisions)

Development

git clone https://github.com/OsamaMahmood/dd-cli.git
cd dd-cli
pip install -e ".[dev,test]"
make test           # 257 unit tests + 12 snapshots
make lint           # ruff
make typecheck      # mypy --strict
make smoke          # 24 integration tests against a live DD (env vars required)

The typed API client in src/dd_cli/_client/ is generated from dd-api.json (DefectDojo's OpenAPI spec). Regenerate after a DefectDojo upgrade:

make install-all    # adds openapi-python-client
make generate-client
# review the diff before committing

License

3-Clause BSD — same as the upstream dd-import project.

Acknowledgments

dd-cli builds on dd-import by Stefan Fleckenstein at MaibornWolff GmbH, now archived. The original tool's DD_* env-var contract is preserved exactly so existing CI pipelines migrate without changes.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dd_cli-2.1.1.tar.gz (510.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dd_cli-2.1.1-py3-none-any.whl (1.6 MB view details)

Uploaded Python 3

File details

Details for the file dd_cli-2.1.1.tar.gz.

File metadata

  • Download URL: dd_cli-2.1.1.tar.gz
  • Upload date:
  • Size: 510.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dd_cli-2.1.1.tar.gz
Algorithm Hash digest
SHA256 f3048e4d54565d8841c158cc7155ffed4d347a57a29a6b55296fac7f8d534077
MD5 fb9196bca6dc22ea3a35c3da693b28e7
BLAKE2b-256 2fa31232dea2cccd58759795735b188d32a889499fd90d63b3014fc59862acf8

See more details on using hashes here.

Provenance

The following attestation bundles were made for dd_cli-2.1.1.tar.gz:

Publisher: release.yml on OsamaMahmood/dd-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dd_cli-2.1.1-py3-none-any.whl.

File metadata

  • Download URL: dd_cli-2.1.1-py3-none-any.whl
  • Upload date:
  • Size: 1.6 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dd_cli-2.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 aca813831fd50870fdb1a4d5c79b23edb9d52436cc7463cbf5920b7e180e43bd
MD5 68213d270ff0c3f8f7829ad587352c7e
BLAKE2b-256 09bea034abe8a0e2dcae37d175b5b426e10b22400224f33aae67fbed4f057f7a

See more details on using hashes here.

Provenance

The following attestation bundles were made for dd_cli-2.1.1-py3-none-any.whl:

Publisher: release.yml on OsamaMahmood/dd-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page