Repository navigation
v0.135.0
Added
-
Draugr installs in Claude Code as a plugin.
/plugin marketplace add draugr-dev/draugrthen/plugin install draugr@draugrregisters the Draugr MCP server. Whendraugris not onPATH, the session opens with the command that installs it. -
An assistant can check the feed cache over MCP. The
feeds_statustool reports whether each feed is cached, when it was fetched, its size, digest and staleness, and returns thedraugr feeds updatecommand for any missing or stale feed without fetching anything itself. -
An AI assistant can propose a descriptor for a project that has none. The MCP tool
propose_sagareturns thedraugr.saga.yamlthatdraugr initwould write, one component per directory withperDirectory, and writes nothing. When the directory already holds a descriptor, the output names it. -
An assistant can say why a finding ranks where it does, and who accepted the ones it does not rank. MCP findings carry their exploitability escalation, reachability verdict and the other scanners that found them. Accepted findings come back in their own list, with who decided, why and until when. Each result names a next step, and stale KEV or EPSS copies are marked, in
results.sariftoo. -
A finding a scanner excluded on its own now stays in the report, suppressed. A
gitleaks:allowcomment, a Grypeignore:rule and a.trivyignoreline covering a license or an IaC check are counted underscanner exclusions, withorigin: toolororigin: scanner, the file, and the reason where one was given.
Changed
-
A file at the repository root is scanned only by a component whose
pathsnames it. Components sharing a repository no longer each report the findings in a root lockfile,Dockerfileor committed secret. A component built from the root module names its files, as inpaths: [services/web, go.mod, go.sum]. Scanner configuration such as.trivyignorestays in every scoped checkout. -
Band counts read count first, as
13 P1, indraugr scan,draugr diffand the HTML report, the order the pull-request comment uses.draugr diffstates its gate above the list of changes, in the terminal and in the pull-request comment, so a long list cannot push it out of view. -
draugr diffcounts the unchanged findings by band, so a passing diff still shows the P1s the change inherited. The terminal and the pull-request comment both draw anunchangedstrip under thenewone, leaving out findings suppressed in both scans. -
A key with no value is refused.
config:on its own line,release: null,release: ~and a bare-in a list fail validation with the line named, as they already did in your editor. Delete the key or give it a value. -
draugr mcpoffers thescantool by default, and asks first only when a scan does more than read. The new default,--scan=effects, asks when a scanner probes a live host, sends data to a third party, changes something or needs elevated access, or when a publisher delivers off this machine.--scan=offrestores the previous default.
Fixed
-
A gitleaks history scan stays inside each component's
pathsandignore. Components sharing a repository no longer report the secrets committed under each other's directories; a history finding belongs to the component whose paths held the file when the secret was committed. -
An MCP scan of
tlsorheadersasks for approval before it contacts a host, as adastscan already did. Both scanners now declare thenetworkeffect, sodraugr controlsand the report record the traffic they send to the endpoint. -
Components scoped to different
pathsof one repository each get their own Mend project. Their uploads shared one project and replaced each other's inventory, so both reported whichever finished last. A scoped component's project name now ends in its paths and an 8-character hash, which starts a new project in Mend; an unscoped repository keeps its project. -
draugr controlsgives the right way to enable each opt-in scanner. The footer now writes theconfig.controls.prefix, and marksgovulncheckas a reachability analyzer enabled throughconfig.reachability.analyzers, which is the only key the descriptor accepts for it. -
The dast MEASURED AGAINST line states each fact once.
endpointshows the URL alone, and the spec, the methods and the authentication appear only in their own fields, in the console, the reports andresults.sarif. -
draugr diff,draugr explainand the MCP report tools refuse a file that is not SARIF. Givenreport.json, they used to read it as a scan with no findings, so a diff printed "Nothing changed" and a summary listed nothing to fix. They now stop and nameresults.sarif, which holds the findings. -
draugr init --per-directorykeeps a JavaScript workspace member with its workspace root. A directory named by the rootpackage.jsonworkspacesfield or bypnpm-workspace.yamlis resolved by the root lockfile and gets no component of its own. -
draugr initproposes gosec and govulncheck for a Go module that requires nothing. Ago.modwith norequireblock is enough, and--per-directorywrites a component for such a module. -
draugr initreachesrequirements-dev.txtand every other requirements file Trivy does not open by name. It writessca.trivyFs.filePatternsfor them, naming the files behind the patterns. -
Each component and each Go module gets its own reachability verdict. Two components sharing a repository no longer receive each other's verdict and call path for the same dependency. A module whose packages sit below its root, under
cmd/for example, keeps its verdict on its owngo.modinstead of the root one. -
gosecincludeandexcludeleave the other rules out of the report. A rule outside the selection was listed as a finding the scanner had suppressed, with the justification "Globally suppressed.". It is no longer reported, because the descriptor said the rule does not apply to that code. -
Grype image findings name the package. Each finding carries its package, version, fixing version and purl, so an image scanned by both Trivy and Grype reports one finding with the other scanner listed under it. The same flaw in two images of one component stays two findings.
-
summarize_reportandscancount a flaw two scanners reported once, as the gate does, and name the second scanner on it. -
Messages name
config.controls. The license policy reasons, the "no controls ran" error and the MCP hints give the current key rather than the deprecatedconfig.controllers. -
Components scoped to a nested path are cached. A component whose
paths:name a directory below the repository root, such asservices/api, was re-scanned on every run because its cache entry was never written. A cache write that fails now logs a warning naming the control and the cause. -
--offlinestops Semgrep fetching a rule pack. Withconfig.controls.sast.semgrep.configunset or naming a registry ruleset or URL, thesastcontrol reports that it cannot run offline and names the setting, instead of reachingsemgrep.dev. A rules file or directory on disk runs as before. -
A vulnerability both govulncheck and the manifest scanner find is reported once, whichever job finishes first. When govulncheck finished first, both findings were kept, so one vulnerability appeared twice under two identifiers.
-
results.sarifandreport.jsonmark a finding from the commit history. A gitleaks finding fromhistory: truecarrieshistorical: true, so a consumer of either file can tell a secret in an old commit, at a path the checkout may no longer have, from a secret in the tree. -
A license a scanner block denies stays denied when the
licensescontrol sets its own list. AdenyorwarnundertrivyLicenseormendLicenseswas replaced by the control-level list instead of adding to it. -
Components scoped to different
pathsof one repository each get their own SBOM, and apathsentry the repository does not hold is refused with the entry named. An edit to.trivyignoreor another root file a scoped checkout holds now invalidates that component's cached result. -
The same scan writes the same SARIF file, whichever job finishes first. A license rule now describes only the license, and each result's message states whether its component's policy denied or flagged it.
-
trivyConfig.checksruns withoutnamespaces. Draugr derives the namespaces from each check'spackageline, so a custom Rego check fires withchecksalone.draugr validateprints the derived list and refuses a check with nopackageline or a path holding no.regofile. -
License findings from
trivyLicense.full: truename the file. A license found in a file such asLICENSEopens with the file's path instead of a blank package name, and a package's license finding inpackage-lock.jsonpoints at that package'snode_modules/entry. -
With gitleaks
history: true, a secret still in the tree is reported and counted once. The history copy of a secret with the same rule, path and value as a tree finding is dropped, and the tree finding is kept. A secret at another path, or an older value replaced in place, is still reported from history.