GuardDog Integration with DefectDojo
GuardDog Integration with DefectDojo
GuardDog is an open source command line tool from Datadog that inspects third-party packages for signs of malicious behavior. It runs Semgrep rules over a package's source code and applies heuristics to its metadata, looking for patterns like network calls or process execution during installation, obfuscated code, and typosquatted names. GuardDog started with PyPI and npm and has since added other ecosystems. It writes results as JSON, which DefectDojo imports with the GuardDog Scan type.
GuardDog Integration with DefectDojo
We added GuardDog because CVE-based dependency scanning doesn't catch a package that was malicious from its first release. There's no advisory yet, just a setup script that phones home. GuardDog finds those behaviors, and DefectDojo is where we decide what to do about them. Each rule match becomes a Finding with the package, the file and line, and the matched code, on the Asset that pulled the package in. Our reviewers mark expected capabilities as accepted once, and only new behavior shows up the next time.
Why GuardDog Matters
Supply chain attacks through public registries rarely look like vulnerabilities. They look like ordinary packages doing slightly unusual things.
- It inspects package code and metadata directly, so it can flag a package before any advisory exists.
- Its rules separate threat behaviors (suspicious in a package, such as network activity in an install script) from capabilities (things the package is able to do, such as spawning processes).
- A risk engine correlates rule matches into scored risks with MITRE tactics, which adds context on why a match matters.
- It is free and runs locally or in CI against a package name or a downloaded source path.
- Its output is a per-run report. Without somewhere to record decisions, the same benign capability gets reviewed again on every run.
Advantages of This Integration
What DefectDojo adds on top of GuardDog's output:
- Reviewed once, not every run. Findings deduplicate on rule ID, package, file path, and line, so a capability you already reviewed is matched on the next import and keeps its status.
- Severity that respects the rule family. Correlated risks keep GuardDog's high, medium, or low rating. Uncorrelated
threat-*matches land as Medium and uncorrelatedcapability-*matches as Info, so observations don't flood the High queue. - Code context on the finding. The matched snippet, rule message, risk category, and MITRE tactics are in the description, so a reviewer can decide without rerunning the tool.
- Package-level risk in view. GuardDog's overall package
risk_scorelabel and score are recorded on each finding's description. - Workflow. Findings can be assigned, risk-accepted with an expiry, marked false positive, or pushed to Jira, and they count toward the same SLAs and metrics as other SCA results.
How This Integration Works
DefectDojo imports GuardDog results with the GuardDog Scan scan type.
1. Produce a JSON report. Scan a package by name or a local path and write JSON:
guarddog pypi scan <package-or-path> --output-format json > guarddog.json
The same pattern works for npm with guarddog npm scan. The parser reads a single-package report: a JSON object with package, results (keyed by rule name), risk_score, and risks. GuardDog lists every rule it ran, including ones with no matches. Only rules with at least one match become findings.
2. Import it. In the UI, open the Engagement, choose Import Scan Results, select GuardDog Scan, and upload the file. To automate it in Community Edition or DefectDojo Pro:
curl "https://YOUR_INSTANCE/api/v2/import-scan/"
-H "Authorization: Token $DD_API_TOKEN"
-F "scan_type=GuardDog Scan"
-F "file=@guarddog.json"
-F "product_name=billing-service"
-F "engagement_name=Dependency Review"
-F "test_title=guarddog requests"
-F "auto_create_context=true"
DefectDojo Pro users can do the same with Universal Importer:
universal-importer import
--defectdojo-url "https://YOUR_INSTANCE.cloud.defectdojo.com/"
--scan-type "GuardDog Scan"
--report-path "./guarddog.json"
--product-name "billing-service"
--engagement-name "Dependency Review"
--auto-create-context
3. Reimport for repeat checks. When you rescan the same package (for example after a version bump), reimport into its existing Test with /api/v2/reimport-scan/ so removed matches are mitigated and new ones are added.
Data Granularity: What Gets Imported
| DefectDojo Field | Source in GuardDog Report | Notes |
|---|---|---|
| Title | Rule ID and package |
<rule> in <package>, or the rule ID alone |
| Severity | Correlated risk severity, else rule family |
Risk high/medium/low map directly; uncorrelated threat-* is Medium, capability-* is Info |
| Description | Match message, rule, package, matched text, risk details, package risk, code | Risk details include threat description, category, and MITRE tactics |
| File Path | Match location |
Part before the colon |
| Line | Match location |
Part after the colon, when numeric |
| Component Name | package |
The scanned package or path |
| Vuln ID from Tool | Rule ID | For example threat-setup-network-in-install |
| Finding type | Static | Static analysis of package contents |
| Deduplication | Hashcode | Vuln ID from tool, component name, file path, line |
Each match is its own finding, so a rule that matches in three places produces three findings.
Use Cases
Gating new dependencies: A platform team requires a GuardDog scan before any new PyPI or npm package is approved. The report is imported into a Test named for the package, and a reviewer clears or rejects it in DefectDojo, leaving a record of who approved what.
Rechecking on upgrades: When a dependency bump arrives, CI scans the new version and reimports it. Capabilities that were already reviewed match existing findings, and only new behavior, such as a fresh install hook, appears as new work.
Incident response: After news of a compromised package, the security team scans the versions in use and imports the results. Threat matches are triaged at Medium or higher, and the findings carry the file and line needed to confirm the behavior.
Reporting on supply chain risk: Because findings sit on the Asset that consumes each package, a security lead can report open malicious-indicator findings by team alongside CVE-based SCA results.
Operational Tips
- Expect many Info findings from
capability-*rules. Setminimum_severity=Lowon import if your reviewers only want threats and correlated risks. - Line numbers are part of the dedupe hash. When a package version changes and code shifts, the same match can appear as a new finding, so review version bumps as a fresh pass.
- Use one Test per package (set
test_title) so reimports stay scoped and closure history is clean. - Tag imports with the package version, for example
tags=requests,2.32.3, so findings can be filtered by release. - Risk-accept capabilities you have reviewed and expect, such as a networking library that makes outbound requests, rather than marking them false positive. They are real capabilities, just acceptable ones.
- The parser expects a single-package report object. Run one scan per package and import each report rather than combining several into one file.