KDT is an open-source command line interface for Invicti ASPM, an Application Security Posture Management (ASPM) platform. Written in Go, KDT interacts with the Invicti ASPM engine through its public API.
With KDT, you can list projects and their scans in Invicti ASPM, trigger scans with specific application security tools, import scan results, manage SBOM files, and break releases if scan results don't meet specified release criteria. KDT is designed to seamlessly integrate with CI/CD pipelines for automated DevSecOps workflows.
Invicti ASPM is an Application Security Posture Management (ASPM) platform that helps you centralize and automate your entire AppSec vulnerability management process. It provides:
- Centralized security health monitoring for applications
- DevSecOps pipeline integration
- Automated AppSec workflow orchestration
- Release criteria enforcement
- SBOM management
You can install KDT using several methods:
With sudo (installs system-wide):
curl -sSL https://cli.kondukto.io | sudo shWithout sudo (user installation):
curl -sSL https://cli.kondukto.io | shDownload the latest kdt-cli.exe from Releases.
If you have a Go environment:
go get github.com/kondukto-io/kdtgit clone https://github.com/kondukto-io/kdt.git
cd kdt
go build . -o kdtOr simply:
make allKDT requires an Invicti ASPM host URL and an API token for authentication. API tokens can be created under Integrations > API Tokens in the Invicti ASPM UI.
export INVICTI_ASPM_HOST=https://your-invicti-aspm-instance.com
export INVICTI_ASPM_TOKEN=your_api_token_hereFor persistence, add these to your shell profile (~/.bashrc, ~/.zshrc, ~/.profile).
Note: The legacy environment variables
KONDUKTO_HOSTandKONDUKTO_TOKENare still supported for backward compatibility but are deprecated. If you use them, you will see a deprecation warning. Please migrate toINVICTI_ASPM_HOSTandINVICTI_ASPM_TOKEN.
Default location: $HOME/.kdt.yaml
host: https://your-invicti-aspm-instance.com
token: your_api_token_here
insecure: false
verbose: falseYou can specify a custom config file:
kdt --config=/path/to/config.yaml list projectskdt --host https://your-invicti-aspm-instance.com --token your_api_token list projectsConfiguration Priority: Command line flags > Environment variables > Configuration file
These flags can be used with any KDT command:
| Flag | Description | Default |
|---|---|---|
--config |
Path to configuration file | $HOME/.kdt.yaml |
--host |
Invicti ASPM server host URL | - |
--token |
Invicti ASPM API token | - |
--insecure |
Skip TLS certificate verification (not recommended for production) | false |
-v, --verbose |
Enable verbose logging for debugging | false |
--exit-code |
Override the exit code | 0 |
Example:
kdt --config=prod-config.yaml --verbose scan -p MyProject -t semgrep -b mainTest connectivity to Invicti ASPM service:
kdt pingVerify that your API token is valid:
kdt ping -aThe scan command is the primary command for triggering security scans and importing scan results.
| Flag | Short | Description | Default |
|---|---|---|---|
--async |
- | Run scan asynchronously (non-blocking) | false |
--project |
-p |
Project name or ID | - |
--tool |
-t |
Scanner tool name | - |
--scan-id |
-s |
Scan ID to restart | - |
--branch |
-b |
Branch name | - |
--file |
-f |
Scan result file to import | - |
--image |
-I |
Container image to scan | - |
--agent |
-a |
Agent name for agent-based scanners | - |
--meta |
-m |
Metadata | - |
--scan-tag |
- | Tag for the scan | - |
--env |
- | Environment: production, staging, develop, feature |
- |
--timeout |
- | Minutes to wait for scan completion (0 = no timeout) | 0 |
--release-timeout |
- | Minutes to wait for release criteria check | 5 |
| Flag | Short | Description |
|---|---|---|
--merge-target |
-M |
Target branch for PR scans |
--pr-number |
- | PR number for decoration |
--pr-decoration-scanner-types |
- | Scanner types for PR decoration (e.g., all, sast, dast, sca) |
--override |
- | Override old analysis results for PR scans |
--no-decoration |
- | Disable PR decoration (deprecated) |
Note: For pull request scans, the target branch (specified with
--merge-target) must be scanned at least once before triggering PR scans. This baseline scan is required for comparison.
| Flag | Short | Description |
|---|---|---|
--fork-scan |
-B |
Enable fork scan based on default branch |
--fork-source |
- | Source branch for fork scans |
--override-fork-source |
- | Override project's fork source branch |
Note: For fork scans, the source branch (specified with
--fork-sourceor the project's default branch) must be scanned at least once before triggering fork scans. This establishes the baseline for comparison.
Break the build if vulnerabilities exceed thresholds:
| Flag | Description |
|---|---|
--threshold-crit |
Maximum critical vulnerabilities |
--threshold-high |
Maximum high vulnerabilities |
--threshold-med |
Maximum medium vulnerabilities |
--threshold-low |
Maximum low vulnerabilities |
--threshold-risk |
Fail if risk score increases |
--break-by-scanner-type |
Only break for specific scanner type |
Automatically create projects during scan:
| Flag | Short | Description |
|---|---|---|
--create-project |
- | Create project if not found |
--project-name |
- | Name for new project |
--repo-id |
-r |
Repository URL or ID |
--alm-tool |
- | ALM tool name (e.g., github, gitlab) |
--team |
-T |
Team name |
--labels |
-l |
Comma-separated labels |
--product-name |
-P |
Product name |
--default-branch |
- | Default branch |
--disable-clone |
- | Disable repository cloning |
--criticality-level |
- | Business criticality: 4=Major, 3=High, 2=Medium, 1=Low, 0=None, -1=Auto |
--feature-branch-retention |
- | Days to retain feature branches |
--feature-branch-infinite-retention |
- | Never delete feature branches |
--scope-include-empty |
- | Include vulnerabilities with no path |
--scope-included-paths |
- | Comma-separated paths for mono-repo scoping |
--scope-included-files |
- | Comma-separated file names for scoping |
| Flag | Description |
|---|---|
--params |
Custom scanner parameters (format: key:value) |
--incremental-scan |
-i |
1. Restart an existing scan by scan ID:
kdt scan -s 5da6cafa5ab6e436faf643dc2. Trigger scan with project and tool:
kdt scan -p MyProject -t semgrep -b main3. Import scan results from file:
kdt scan -p MyProject -t checkmarx -b develop -f results.xml4. Scan with thresholds (break build):
kdt scan -p MyProject -t trivy -b main \
--threshold-crit 0 \
--threshold-high 5 \
--threshold-med 105. Async scan (non-blocking):
kdt scan -p MyProject -t gosec -b main --async6. Container image scan:
kdt scan -p MyProject -t trivy \
--image myapp:latest \
-b main7. Pull request scan:
kdt scan -p MyProject -t semgrep \
-b feature/new-feature \
-M main \
--pr-number 1238. Fork scan (feature branch vs default):
kdt scan -p MyProject -t semgrep \
-b feature/test \
--fork-scan \
--env feature9. Create project and scan:
kdt scan -p NewProject -t semgrep -b main \
--create-project \
--repo-id https://github.com/org/repo \
--alm-tool github \
--team security10. Custom parameters:
kdt scan -p MyProject -t semgrep -b develop \
--params=ruleset_type:2 \
--params=ruleset_options.ruleset:/custom/rules/11. Risk threshold (prevent regression):
kdt scan -p MyProject -t sonarqube -b main --threshold-risk12. Incremental scan (Semgrep):
kdt scan -p MyProject -t semgrep -b main \
-f semgrep-results.json \
--incremental-scanCheck if a project passes release criteria.
| Flag | Short | Description |
|---|---|---|
--project |
-p |
Project name or ID (required) |
--branch |
-b |
Branch name (default: project's default branch) |
--timeout |
- | Minutes to wait for criteria check |
--sast |
- | Check SAST criteria |
--dast |
- | Check DAST criteria |
--sca |
- | Check SCA criteria |
--iac |
- | Check IaC criteria |
--cs |
- | Check Code Security criteria |
--iast |
- | Check IAST criteria |
--pentest |
- | Check Penetration Testing criteria |
--mast |
- | Check MAST criteria |
--sbom |
- | Check SBOM criteria |
1. Check all release criteria:
kdt release -p MyProject -b main2. Check specific criteria only:
kdt release -p MyProject -b main --sast --sca3. With verbose output:
kdt -v release -p MyProject -b main --sast --dast4. With custom timeout:
kdt release -p MyProject -b main --timeout 10kdt list projectsFlags:
-p, --project: Project name or ID (required)
Example:
kdt list scans -p MyProjectView all available scanners:
kdt list scannersExample output:
Name ID Type Trigger Labels
---- -- ---- ------- ------
gosec 60eec8a83e9e5e6e2ae52d06 sast new scan docker,kdt
semgrep 60eec8a53e9e5e6e2ae52d05 sast rescan template,docker,kdt
trivy 60eec8a73e9e5e6e2ae52d07 sca new scan docker,kdt,container
kdt list agentskdt list productsFlags:
| Flag | Short | Description |
|---|---|---|
--repo-id |
-r |
Repository URL or ID (required) |
--project-name |
- | Project name |
--alm-tool |
-a |
ALM tool name |
--team |
-t |
Team name |
--labels |
-l |
Comma-separated labels |
--product-name |
-P |
Product name |
--force-create |
- | Create with suffix if name exists |
--overwrite |
-w |
Overwrite existing project |
--default-branch |
- | Default branch |
--disable-clone |
- | Disable repository cloning |
--fork-source |
- | Source branch for feature branches |
--criticality-level |
- | Business criticality (0-4, -1=Auto) |
--feature-branch-retention |
- | Days to retain feature branches |
--feature-branch-infinite-retention |
- | Never delete feature branches |
--scope-include-empty |
- | Include vulnerabilities with no path |
--scope-included-paths |
- | Paths for mono-repo scoping |
--scope-included-files |
- | File names for scoping |
Examples:
1. Create project from repository:
kdt create project \
--repo-id https://github.com/kondukto-io/kdt \
--alm-tool github \
--labels GDPR,Internal \
--team security2. Create with custom name:
kdt create project \
--repo-id https://gitlab.com/org/app \
--project-name MyCustomName \
--alm-tool gitlab \
--default-branch develop3. Create with product:
kdt create project \
--repo-id https://github.com/org/repo \
--alm-tool github \
--product-name "Mobile_Apps" \
--criticality-level 44. Mono-repo with scoping:
kdt create project \
--repo-id https://github.com/org/monorepo \
--project-name backend-api \
--alm-tool github \
--scope-included-paths "services/api,shared/common" \
--scope-included-files "package.json,go.mod"Flags:
-n, --name: Team name (required)-r, --responsible: Responsible user name
Example:
kdt create team --name "security-team" --responsible "john.doe"Flags:
-n, --name: Label name (required)-c, --color: Label color in hex format (default:000000)
Examples:
# Create label with default color
kdt create label --name "GDPR"
# Create label with custom color
kdt create label --name "Critical" --color "FF0000"Flags:
-n, --name: Product name (required)-p, --projects: Comma-separated project names or IDs
Examples:
# Create empty product
kdt create product --name "mobile-apps"
# Create product with projects
kdt create product --name "web-services" --projects "api-service,web-app,auth-service"Import Software Bill of Materials (CycloneDX format).
Flags:
| Flag | Short | Description |
|---|---|---|
--file |
-f |
SBOM file path (JSON format, required) |
--project |
-p |
Project name or ID |
--repo-id |
-r |
Repository URL or ID |
--branch |
-b |
Branch name |
--sbom-type |
-s |
Type: source_dir, image, application, os, container |
--allow-empty |
-a |
Allow empty components |
Examples:
1. Import SBOM for project:
kdt sbom import \
-f cyclonedx-sbom.json \
-p MyProject \
-b main2. Import with specific type:
kdt sbom import \
-f sbom.json \
-p MyProject \
-b main \
--sbom-type image3. Import using repository ID:
kdt sbom import \
-f sbom.json \
--repo-id https://github.com/org/repo \
-b mainImport API endpoint definitions (Swagger/OpenAPI).
Flags:
| Flag | Short | Description |
|---|---|---|
--file |
-f |
Endpoint file path (required) |
--project |
-p |
Project name or ID (required) |
Example:
kdt endpoint import -f swagger.json -p MyProjectQuery project status and vulnerability counts.
Flags:
| Flag | Short | Description |
|---|---|---|
--project |
-p |
Project name or ID |
--branch |
-b |
Branch name |
--event |
-e |
Event ID |
--threshold-crit |
- | Critical threshold |
--threshold-high |
- | High threshold |
--threshold-med |
- | Medium threshold |
--threshold-low |
- | Low threshold |
--threshold-risk |
- | Risk threshold |
Examples:
1. Get project status:
kdt status -p MyProject -b main2. Check status with thresholds:
kdt status -p MyProject -b main \
--threshold-crit 0 \
--threshold-high 53. Query by event ID:
kdt status -e 5da6cafa5ab6e436faf643dcCheck if a project exists in ALM.
Flags:
| Flag | Short | Description |
|---|---|---|
--alm-tool |
-a |
ALM tool name |
--repo-id |
-r |
Repository URL or ID |
Example:
kdt project available \
--alm-tool github \
--repo-id https://github.com/kondukto-io/kdtReturns exit code 0 if available, -1 (255) if not.
- name: Run Security Scan
run: |
kdt scan \
-p ${{ github.event.repository.name }} \
-t semgrep \
-b ${{ github.ref_name }} \
--threshold-crit 0 \
--threshold-high 10security_scan:
script:
- kdt scan -p ${CI_PROJECT_NAME} -t trivy -b ${CI_COMMIT_BRANCH} --threshold-crit 0stage('Security Scan') {
steps {
sh '''
kdt scan \
-p ${JOB_NAME} \
-t checkmarx \
-b ${GIT_BRANCH} \
--threshold-crit 0 \
--threshold-high 5
'''
}
}# Import scan results from local tool
kdt scan -p MyProject -t fortify -f results.fpr -b develop \
--threshold-crit 0 --threshold-high 0
# Check release criteria
kdt release -p MyProject -b develop --sast --sca --dast# Scan container image
kdt scan -p MyProject -t trivy \
--image myapp:${VERSION} \
-b main \
--threshold-crit 0
# Import SBOM
kdt sbom import -f sbom.json -p MyProject -b main --sbom-type container# Trigger PR scan
kdt scan -p MyProject -t semgrep \
-b feature/new-feature \
-M main \
--pr-number ${PR_NUMBER} \
--pr-decoration-scanner-types all# Development
kdt scan -p MyProject -t semgrep -b develop --env develop
# Staging
kdt scan -p MyProject -t sonarqube -b staging --env staging \
--threshold-high 10
# Production
kdt scan -p MyProject -t checkmarx -b main --env production \
--threshold-crit 0 --threshold-high 0 \
--release-timeout 10# Semgrep with custom rules
kdt scan -p MyProject -t semgrep -b main \
--params=ruleset_type:2 \
--params=ruleset_options.ruleset:/custom/rules/ \
--params=ruleset_options.config:auto
# Container scan with custom registry
kdt scan -p MyProject -t trivy \
--image registry.example.com/myapp:latest \
--params=registry.username:user \
--params=registry.password:passKDT uses the following exit codes:
| Code | Meaning |
|---|---|
0 |
Success |
1 |
General error |
2 |
Warning |
100 |
Not authorized |
-1 (255) |
Negative response (e.g., project not available) |
KDT supports all scanners enabled in your Invicti ASPM instance. To view available scanners:
kdt list scannerskdt -v scan -p MyProject -t semgrep -b mainkdt ping
kdt ping -a # With authentication# Check if host and token are set
echo $INVICTI_ASPM_HOST
echo $INVICTI_ASPM_TOKEN
# Or use a test command
kdt list projectsContributions to KDT are welcome! Here's how you can contribute:
Create an issue in the GitHub repository with:
- Clear description of the issue
- Steps to reproduce
- Expected vs actual behavior
- KDT version (
kdt version)
- Fork the repository
- Create a feature/bugfix branch following Git Flow:
- Features:
feature/example-feature - Bugfixes:
bugfix/example-bugfix
- Features:
- Write idiomatic Go code
- Document exported functions
- Write detailed PR description
- Ensure tests pass
git clone https://github.com/kondukto-io/kdt.git
cd kdt
go mod download
go build -o kdt
./kdt --helpSee the LICENSE file for details.
- Documentation: https://docs.kondukto.io
- Issues: GitHub Issues
- Website: https://kondukto.io
