Secretlint Integration with DefectDojo
Secretlint Integration with DefectDojo
Secretlint is an open source, pluggable secret scanner maintained in the secretlint project on GitHub and distributed through npm. It scans the files you point it at (not Git history) for credentials such as cloud provider keys, private keys, database connection strings, package registry and CI tokens, and SaaS API keys. Its rules are npm packages, so teams can combine the recommended preset with their own organization-specific rules. Secretlint masks detected secret values by default and supports several output formatters, including the JSON formatter that DefectDojo imports.
Secretlint Integration with DefectDojo
We use Secretlint because it fits into the Node tooling our teams already run, and writing a custom rule for an internal token format is a small npm package instead of a regex buried in a CI script. On its own, though, a Secretlint failure is a red build and a log line. Importing Secretlint results into DefectDojo gives every detected credential a Finding with the rule, file, and line, an owner who has to rotate it, and a record of when it was removed. The masked value stays masked, and the scanned file contents never reach DefectDojo.
Why Secretlint Matters
Credentials committed to source code are one of the most common ways attackers get from a code leak to a production system. Catching them before merge is cheaper than rotating them after.
- Secretlint scans the working tree, which makes it fast enough to run on every commit or pull request.
- Its rules are packages, so a team can add detection for its own token formats without forking the tool.
secretlint-disablecomments let developers suppress a known test value at the source, and suppressed detections are left out of the report.- Secret values are masked in its messages by default, which keeps scan output from spreading the secret further.
- Finding a secret is only half the job. Someone has to rotate it, and that needs tracking.
Advantages of This Integration
What we gained by sending Secretlint results through DefectDojo:
- Precise location. Each Finding records the file path and line, plus the column in the description, so the owner can go straight to the credential.
- Consistent classification. Every Secretlint Finding carries CWE-798 (Use of Hard-coded Credentials), the same CWE DefectDojo's Gitleaks and Detect-secrets parsers use, so secret Findings can be compared across tools.
- No source content in DefectDojo. A Secretlint JSON report embeds the full content of every scanned file, secret included. The parser does not copy any of it into the Finding.
- Rule-level identity. The tool ID combines the shortened rule name and message ID, such as
aws/AWSSecretAccessKey, which is what deduplication keys on along with file and line. - A rotation lifecycle. Reimporting after a credential is removed mitigates its Finding. If the secret reappears, the Finding is reactivated.
- SLAs and escalation. Secrets import as High by default under the recommended preset, so they fall under your High SLA and can be pushed to Jira for the owning team.
How This Integration Works
DefectDojo imports Secretlint output with the Secretlint Scan scan type. Only the JSON formatter is supported.
1. Configure rules and produce JSON. Secretlint needs a rule set. Commit a .secretlintrc.json that references the recommended preset (@secretlint/secretlint-rule-preset-recommend) and any custom rules, then run:
npx secretlint --format json "**/*" > secretlint.json
Keep the glob in quotes so the pattern reaches Secretlint instead of being expanded by the shell. Secretlint exits with code 1 when it finds a secret, so make sure your CI step still uploads the report in that case.
2. Import it. In the UI, open the Engagement, choose Import Scan Results, select Secretlint Scan, and upload the file. For automation, use the API in Community Edition or DefectDojo Pro:
curl "https://YOUR_INSTANCE/api/v2/import-scan/"
-H "Authorization: Token $DD_API_TOKEN"
-F "scan_type=Secretlint Scan"
-F "file=@secretlint.json"
-F "product_name=web-frontend"
-F "engagement_name=CI"
-F "auto_create_context=true"
DefectDojo Pro users can run the same import with Universal Importer:
universal-importer import
--defectdojo-url "https://YOUR_INSTANCE.cloud.defectdojo.com/"
--scan-type "Secretlint Scan"
--report-path "./secretlint.json"
--product-name "web-frontend"
--engagement-name "CI"
--auto-create-context
3. Reimport on every run. Send later reports to /api/v2/reimport-scan/ against the same Test so removed secrets are mitigated and the history stays together.
Data Granularity: What Gets Imported
| DefectDojo Field | Source in Secretlint Report | Notes |
|---|---|---|
| Title | messageId (or rule) and file base name |
For example "Hard coded AWSSecretAccessKey found in config.js" |
| Severity | messages[].severity |
error is High, warning is Medium, info is Info; High if absent |
| Description | Rule message and metadata | Masked detection text, rule ID, message ID, preset, file, line and column, rule docs URL |
| CWE | Fixed at 798 | Use of Hard-coded Credentials |
| File Path | filePath |
Exactly as reported, which is an absolute path |
| Line | messages[].loc.start.line |
Column is recorded in the description |
| Tool ID (vuln_id_from_tool) | Short rule name and messageId |
For example aws/AWSSecretAccessKey |
| Source content | Not imported | sourceContent is ignored |
| Finding type | Static | |
| Deduplication | Hashcode | File path, line, vuln_id_from_tool |
Within one report, repeated detections of the same rule and message at the same file and line are merged into a single Finding with an occurrence count. Filter-rule entries, which describe ignored ranges rather than secrets, are skipped.
Use Cases
On every pull request: A CI job runs Secretlint on the changed repository and reimports into a Test per repository. A new credential shows up as a new High Finding on the Asset, assigned to the team that owns the code, and the history shows exactly when it was introduced and removed.
With custom rules for internal tokens: A platform team publishes a Secretlint rule for its internal service tokens. Detections from that rule import with their own tool ID, so security can report on how often internal tokens leak compared to cloud keys.
During a credential cleanup: Before open sourcing a repository, a team scans it, imports the results, and works the Findings to zero. Each one is closed by reimport once the secret is removed and rotated, which leaves an audit trail.
Across many repositories: Security leads see secret Findings for every Asset in one place, alongside Gitleaks or Detect-secrets results if other teams use those tools, all under the same CWE.
Operational Tips
- Leave masking on. Running Secretlint with
--no-maskSecretsputs the raw value into the rule message, and that message is imported into the Finding description. - Secretlint reports absolute paths, and file path is part of the hash. Run scans from a consistent checkout path in CI, or the same secret on two different runners can produce two Findings.
- Line number is also in the hash, so a secret that moves to a different line after an edit will appear as a new Finding and the old one will be mitigated on reimport.
- Removing a secret from the file is not the same as rotating it. Keep the Finding open, or add a note, until the credential has actually been revoked.
- Use
secretlint-disablecomments for known test fixtures so they never reach DefectDojo, rather than marking them false positive after every scan. - Custom rules that report
warningorinfoimport as Medium or Info. Set severity in your rules to match how urgently you want those Findings handled.