Scanning from CI/CD pipelines
A pipeline scans by running the dpndncy CLI against your server. The CLI uploads the checked-out source, waits for the result, and exits with a code that passes or fails the job. Full CLI reference: The dpndncy command line.
#What every pipeline needs
| Need | How |
|---|---|
| The API address of your server | https://api.dpndncy.example.com. Not the console address; the console does not serve the API |
| An API token | The tenant owner creates a service user with the analyst role, signs in as it, and creates a token (Settings, API Tokens). Store it as a secret in your CI system. See Tenants, users and access |
| The CLI | Download it from your own server at the start of the job (below), or bake it into your runner image |
| A project name | --project <name> or DPNDNCY_PROJECT. Many CI systems check out into a folder with a meaningless name, and scans of the same name form one project with its history |
The runner needs outbound HTTPS to the API address and nothing else. If your server uses a certificate from a private CA, give the runner the CA: the CLI is a Node program, so NODE_EXTRA_CA_CERTS=/path/to/ca.pem points it at an extra bundle.
The verdict comes from the tenant's scan policy (Scan policies). The pipeline does not carry thresholds; change the policy in the console and every pipeline follows.
#GitHub Actions
#With the Action
The repository's root action.yml downloads the CLI from your server, scans the workspace and fails the job when the policy fails. It uploads the JSON result as an artifact and writes a summary.
name: dpndncY
on:
pull_request:
push:
branches: [main]
jobs:
scan:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: dpndncY-SCA/[email protected] # pin a release tag
with:
server-url: https://api.dpndncy.example.com
api-token: ${{ secrets.DPNDNCY_TOKEN }}
engines: sca,sast,secrets| Input | Default | Meaning |
|---|---|---|
server-url |
required | The API address |
api-token |
required | The token |
path |
. |
Folder to scan |
engines |
sca |
Comma separated: sca, sast, secrets, ai-risk, attack-paths, all |
project |
repository name | Project name |
fail-on-any |
false |
Ignore the policy, fail on any vulnerability |
upload-results |
true |
Attach the JSON result |
review-dependency-changes |
false |
Also review changed dependency versions in a pull request |
Outputs: exit-code, policy-status, vulnerabilities-found, critical-count, high-count, medium-count, low-count, scan-id.
#With the CLI directly
- name: dpndncY scan
env:
DPNDNCY_SERVER: https://api.dpndncy.example.com
DPNDNCY_TOKEN: ${{ secrets.DPNDNCY_TOKEN }}
DPNDNCY_PROJECT: ${{ github.event.repository.name }}
run: |
curl -fsSL "$DPNDNCY_SERVER/releases/dpndncy-linux" -o dpndncy
chmod +x dpndncy
./dpndncy scan --ci --sca --sast --secrets --output dpndncy-result.json .#GitLab CI
dpndncy-scan:
stage: test
image: debian:stable-slim
variables:
DPNDNCY_SERVER: https://api.dpndncy.example.com
DPNDNCY_PROJECT: $CI_PROJECT_NAME
# DPNDNCY_TOKEN is set as a masked CI/CD variable
before_script:
- apt-get update -qq && apt-get install -y -qq curl ca-certificates
- curl -fsSL "$DPNDNCY_SERVER/releases/dpndncy-linux" -o /usr/local/bin/dpndncy
- chmod +x /usr/local/bin/dpndncy
script:
- dpndncy scan --ci --sca --sast --secrets --output dpndncy-result.json .
artifacts:
when: always
paths: [dpndncy-result.json]#Jenkins
pipeline {
agent any
environment {
DPNDNCY_SERVER = 'https://api.dpndncy.example.com'
DPNDNCY_TOKEN = credentials('dpndncy-token') // a Secret text credential
DPNDNCY_PROJECT = 'billing-api'
}
stages {
stage('dpndncY scan') {
steps {
sh '''
curl -fsSL "$DPNDNCY_SERVER/releases/dpndncy-linux" -o dpndncy
chmod +x dpndncy
./dpndncy scan --ci --sca --sast --secrets --output dpndncy-result.json .
'''
}
post { always { archiveArtifacts artifacts: 'dpndncy-result.json', allowEmptyArchive: true } }
}
}
}#Azure DevOps
steps:
- script: |
curl -fsSL "$(DPNDNCY_SERVER)/releases/dpndncy-linux" -o dpndncy
chmod +x dpndncy
./dpndncy scan --ci --sca --sast --secrets --output $(Build.ArtifactStagingDirectory)/dpndncy-result.json .
displayName: dpndncY scan
env:
DPNDNCY_SERVER: https://api.dpndncy.example.com
DPNDNCY_TOKEN: $(DPNDNCY_TOKEN) # a secret pipeline variable
DPNDNCY_PROJECT: $(Build.Repository.Name)#Bitbucket Pipelines
pipelines:
default:
- step:
name: dpndncY scan
script:
- export DPNDNCY_SERVER=https://api.dpndncy.example.com
- export DPNDNCY_PROJECT=$BITBUCKET_REPO_SLUG
- curl -fsSL "$DPNDNCY_SERVER/releases/dpndncy-linux" -o dpndncy && chmod +x dpndncy
- ./dpndncy scan --ci --sca --sast --secrets . # DPNDNCY_TOKEN is a secured repository variable#Reading the result
--output dpndncy-result.json writes the full result. The fields pipelines usually want:
| Path | Meaning |
|---|---|
.sca.policy.status |
pass or fail |
.sca.policy.violations[] |
why it failed, in words |
.sca.vulnerabilities.total, .severityCounts |
counts by severity |
.metadata.scanId |
the scan's id; open it in the console |
#Other pipeline protections
| Feature | What it does | Documentation |
|---|---|---|
| Dependency admission | Checks a change to dependencies before it merges (dpndncy firewall check) |
Dependency Admission / Firewall Events |
| Pipeline trust firewall | Evaluates the third-party actions a workflow uses | dpndncY Pipeline Trust Firewall |
| Runtime agent | Watches what a CI runner actually does (network, processes, file writes) and signs a trace | dpndncy.com/docs/runtime |
#Troubleshooting
| Symptom | Cause |
|---|---|
| Job fails at the download with 404 | DPNDNCY_SERVER is the console address. Use the API address |
| Exit 4 | The token is wrong, expired, or its user is not an analyst |
| Exit 5 | The runner cannot reach the API address, or does not trust its certificate |
| Exit 1 with "scan policy" | The scan broke the tenant's policy. Read policy.violations, fix, or adjust the policy |
| All repositories appear as one project | Set --project / DPNDNCY_PROJECT |
| Archive too large | Add build output and vendored folders to a .dpndncyignore file at the repository root |