@vyuhlabs/dxkit 2.5.2 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +218 -13
- package/README.md +220 -369
- package/dist/allowlist/categories.d.ts +120 -0
- package/dist/allowlist/categories.d.ts.map +1 -0
- package/dist/allowlist/categories.js +194 -0
- package/dist/allowlist/categories.js.map +1 -0
- package/dist/allowlist/cli.d.ts +95 -0
- package/dist/allowlist/cli.d.ts.map +1 -0
- package/dist/allowlist/cli.js +454 -0
- package/dist/allowlist/cli.js.map +1 -0
- package/dist/allowlist/diff.d.ts +67 -0
- package/dist/allowlist/diff.d.ts.map +1 -0
- package/dist/allowlist/diff.js +147 -0
- package/dist/allowlist/diff.js.map +1 -0
- package/dist/allowlist/file.d.ts +249 -0
- package/dist/allowlist/file.d.ts.map +1 -0
- package/dist/allowlist/file.js +497 -0
- package/dist/allowlist/file.js.map +1 -0
- package/dist/allowlist/gather.d.ts +61 -0
- package/dist/allowlist/gather.d.ts.map +1 -0
- package/dist/allowlist/gather.js +143 -0
- package/dist/allowlist/gather.js.map +1 -0
- package/dist/allowlist/hint.d.ts +80 -0
- package/dist/allowlist/hint.d.ts.map +1 -0
- package/dist/allowlist/hint.js +271 -0
- package/dist/allowlist/hint.js.map +1 -0
- package/dist/allowlist/inline.d.ts +149 -0
- package/dist/allowlist/inline.d.ts.map +1 -0
- package/dist/allowlist/inline.js +306 -0
- package/dist/allowlist/inline.js.map +1 -0
- package/dist/analyzers/bom/discovery.d.ts +3 -4
- package/dist/analyzers/bom/discovery.d.ts.map +1 -1
- package/dist/analyzers/bom/discovery.js +3 -4
- package/dist/analyzers/bom/discovery.js.map +1 -1
- package/dist/analyzers/bom/types.d.ts +1 -1
- package/dist/analyzers/dashboard/index.d.ts.map +1 -1
- package/dist/analyzers/dashboard/index.js +42 -5
- package/dist/analyzers/dashboard/index.js.map +1 -1
- package/dist/analyzers/quality/detailed.d.ts +8 -1
- package/dist/analyzers/quality/detailed.d.ts.map +1 -1
- package/dist/analyzers/quality/detailed.js +43 -10
- package/dist/analyzers/quality/detailed.js.map +1 -1
- package/dist/analyzers/security/detailed.d.ts +8 -1
- package/dist/analyzers/security/detailed.d.ts.map +1 -1
- package/dist/analyzers/security/detailed.js +14 -1
- package/dist/analyzers/security/detailed.js.map +1 -1
- package/dist/analyzers/tests/detailed.d.ts +8 -1
- package/dist/analyzers/tests/detailed.d.ts.map +1 -1
- package/dist/analyzers/tests/detailed.js +26 -7
- package/dist/analyzers/tests/detailed.js.map +1 -1
- package/dist/analyzers/tools/cloc.js +3 -3
- package/dist/analyzers/tools/cloc.js.map +1 -1
- package/dist/analyzers/tools/exclusions.d.ts +12 -12
- package/dist/analyzers/tools/exclusions.d.ts.map +1 -1
- package/dist/analyzers/tools/exclusions.js +27 -13
- package/dist/analyzers/tools/exclusions.js.map +1 -1
- package/dist/analyzers/tools/graphify.d.ts +39 -5
- package/dist/analyzers/tools/graphify.d.ts.map +1 -1
- package/dist/analyzers/tools/graphify.js +609 -45
- package/dist/analyzers/tools/graphify.js.map +1 -1
- package/dist/analyzers/tools/nuget-package-reference.d.ts +4 -4
- package/dist/analyzers/tools/nuget-package-reference.js +4 -4
- package/dist/analyzers/tools/osv-scanner-fix.d.ts +4 -5
- package/dist/analyzers/tools/osv-scanner-fix.d.ts.map +1 -1
- package/dist/analyzers/tools/osv-scanner-fix.js +4 -5
- package/dist/analyzers/tools/osv-scanner-fix.js.map +1 -1
- package/dist/analyzers/tools/parallel.d.ts.map +1 -1
- package/dist/analyzers/tools/parallel.js +7 -0
- package/dist/analyzers/tools/parallel.js.map +1 -1
- package/dist/analyzers/tools/vendored-advisor.d.ts.map +1 -1
- package/dist/analyzers/tools/vendored-advisor.js +3 -4
- package/dist/analyzers/tools/vendored-advisor.js.map +1 -1
- package/dist/analyzers/xlsx/licenses.d.ts +7 -7
- package/dist/analyzers/xlsx/licenses.js +7 -7
- package/dist/baseline/baseline-file.d.ts +7 -0
- package/dist/baseline/baseline-file.d.ts.map +1 -1
- package/dist/baseline/baseline-file.js +22 -1
- package/dist/baseline/baseline-file.js.map +1 -1
- package/dist/baseline/check-renderers.d.ts +13 -1
- package/dist/baseline/check-renderers.d.ts.map +1 -1
- package/dist/baseline/check-renderers.js +67 -1
- package/dist/baseline/check-renderers.js.map +1 -1
- package/dist/baseline/check.d.ts +33 -7
- package/dist/baseline/check.d.ts.map +1 -1
- package/dist/baseline/check.js +90 -64
- package/dist/baseline/check.js.map +1 -1
- package/dist/baseline/create.d.ts +35 -7
- package/dist/baseline/create.d.ts.map +1 -1
- package/dist/baseline/create.js +43 -5
- package/dist/baseline/create.js.map +1 -1
- package/dist/baseline/entry-to-located.d.ts +6 -1
- package/dist/baseline/entry-to-located.d.ts.map +1 -1
- package/dist/baseline/entry-to-located.js +20 -2
- package/dist/baseline/entry-to-located.js.map +1 -1
- package/dist/baseline/finding-identity.d.ts.map +1 -1
- package/dist/baseline/finding-identity.js +15 -13
- package/dist/baseline/finding-identity.js.map +1 -1
- package/dist/baseline/modes.d.ts +140 -0
- package/dist/baseline/modes.d.ts.map +1 -0
- package/dist/baseline/modes.js +179 -0
- package/dist/baseline/modes.js.map +1 -0
- package/dist/baseline/policy.d.ts +64 -0
- package/dist/baseline/policy.d.ts.map +1 -1
- package/dist/baseline/policy.js +102 -1
- package/dist/baseline/policy.js.map +1 -1
- package/dist/baseline/producers/health.d.ts +2 -2
- package/dist/baseline/producers/health.d.ts.map +1 -1
- package/dist/baseline/producers/health.js.map +1 -1
- package/dist/baseline/producers/index.d.ts +11 -5
- package/dist/baseline/producers/index.d.ts.map +1 -1
- package/dist/baseline/producers/index.js +12 -9
- package/dist/baseline/producers/index.js.map +1 -1
- package/dist/baseline/producers/quality.d.ts +3 -3
- package/dist/baseline/producers/quality.d.ts.map +1 -1
- package/dist/baseline/producers/quality.js.map +1 -1
- package/dist/baseline/producers/secret-hmac.d.ts +2 -2
- package/dist/baseline/producers/secret-hmac.d.ts.map +1 -1
- package/dist/baseline/producers/secret-hmac.js.map +1 -1
- package/dist/baseline/producers/security.d.ts +2 -2
- package/dist/baseline/producers/security.d.ts.map +1 -1
- package/dist/baseline/producers/security.js.map +1 -1
- package/dist/baseline/producers/stale-allow.d.ts +70 -0
- package/dist/baseline/producers/stale-allow.d.ts.map +1 -0
- package/dist/baseline/producers/stale-allow.js +111 -0
- package/dist/baseline/producers/stale-allow.js.map +1 -0
- package/dist/baseline/producers/tests.d.ts +2 -2
- package/dist/baseline/producers/tests.d.ts.map +1 -1
- package/dist/baseline/producers/tests.js.map +1 -1
- package/dist/baseline/ref-baseline.d.ts +114 -0
- package/dist/baseline/ref-baseline.d.ts.map +1 -0
- package/dist/baseline/ref-baseline.js +260 -0
- package/dist/baseline/ref-baseline.js.map +1 -0
- package/dist/baseline/sanitize.d.ts +80 -0
- package/dist/baseline/sanitize.d.ts.map +1 -0
- package/dist/baseline/sanitize.js +91 -0
- package/dist/baseline/sanitize.js.map +1 -0
- package/dist/baseline/show.d.ts.map +1 -1
- package/dist/baseline/show.js +9 -3
- package/dist/baseline/show.js.map +1 -1
- package/dist/baseline/types.d.ts +73 -26
- package/dist/baseline/types.d.ts.map +1 -1
- package/dist/baseline/types.js +7 -1
- package/dist/baseline/types.js.map +1 -1
- package/dist/baseline/visibility.d.ts +61 -0
- package/dist/baseline/visibility.d.ts.map +1 -0
- package/dist/baseline/visibility.js +121 -0
- package/dist/baseline/visibility.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +168 -6
- package/dist/cli.js.map +1 -1
- package/dist/dashboard/graph-adapter.d.ts +151 -0
- package/dist/dashboard/graph-adapter.d.ts.map +1 -0
- package/dist/dashboard/graph-adapter.js +415 -0
- package/dist/dashboard/graph-adapter.js.map +1 -0
- package/dist/dashboard/graph-tab.d.ts +109 -0
- package/dist/dashboard/graph-tab.d.ts.map +1 -0
- package/dist/dashboard/graph-tab.js +297 -0
- package/dist/dashboard/graph-tab.js.map +1 -0
- package/dist/dashboard/vendor/vis-network.min.js +34 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +106 -16
- package/dist/doctor.js.map +1 -1
- package/dist/explore/cli/api-surface.d.ts +12 -0
- package/dist/explore/cli/api-surface.d.ts.map +1 -0
- package/dist/explore/cli/api-surface.js +57 -0
- package/dist/explore/cli/api-surface.js.map +1 -0
- package/dist/explore/cli/communities.d.ts +10 -0
- package/dist/explore/cli/communities.d.ts.map +1 -0
- package/dist/explore/cli/communities.js +47 -0
- package/dist/explore/cli/communities.js.map +1 -0
- package/dist/explore/cli/context.d.ts +16 -0
- package/dist/explore/cli/context.d.ts.map +1 -0
- package/dist/explore/cli/context.js +118 -0
- package/dist/explore/cli/context.js.map +1 -0
- package/dist/explore/cli/entry-points.d.ts +12 -0
- package/dist/explore/cli/entry-points.d.ts.map +1 -0
- package/dist/explore/cli/entry-points.js +85 -0
- package/dist/explore/cli/entry-points.js.map +1 -0
- package/dist/explore/cli/feature.d.ts +16 -0
- package/dist/explore/cli/feature.d.ts.map +1 -0
- package/dist/explore/cli/feature.js +89 -0
- package/dist/explore/cli/feature.js.map +1 -0
- package/dist/explore/cli/file.d.ts +12 -0
- package/dist/explore/cli/file.d.ts.map +1 -0
- package/dist/explore/cli/file.js +139 -0
- package/dist/explore/cli/file.js.map +1 -0
- package/dist/explore/cli/hot-files.d.ts +11 -0
- package/dist/explore/cli/hot-files.d.ts.map +1 -0
- package/dist/explore/cli/hot-files.js +63 -0
- package/dist/explore/cli/hot-files.js.map +1 -0
- package/dist/explore/context-hook.d.ts +42 -0
- package/dist/explore/context-hook.d.ts.map +1 -0
- package/dist/explore/context-hook.js +131 -0
- package/dist/explore/context-hook.js.map +1 -0
- package/dist/explore/finding-context.d.ts +69 -0
- package/dist/explore/finding-context.d.ts.map +1 -0
- package/dist/explore/finding-context.js +102 -0
- package/dist/explore/finding-context.js.map +1 -0
- package/dist/explore/format.d.ts +64 -0
- package/dist/explore/format.d.ts.map +1 -0
- package/dist/explore/format.js +99 -0
- package/dist/explore/format.js.map +1 -0
- package/dist/explore/load.d.ts +50 -0
- package/dist/explore/load.d.ts.map +1 -0
- package/dist/explore/load.js +197 -0
- package/dist/explore/load.js.map +1 -0
- package/dist/explore/queries.d.ts +413 -0
- package/dist/explore/queries.d.ts.map +1 -0
- package/dist/explore/queries.js +855 -0
- package/dist/explore/queries.js.map +1 -0
- package/dist/explore/types.d.ts +130 -0
- package/dist/explore/types.d.ts.map +1 -0
- package/dist/explore/types.js +28 -0
- package/dist/explore/types.js.map +1 -0
- package/dist/explore-cli.d.ts +45 -0
- package/dist/explore-cli.d.ts.map +1 -0
- package/dist/explore-cli.js +213 -0
- package/dist/explore-cli.js.map +1 -0
- package/dist/generator.d.ts.map +1 -1
- package/dist/generator.js +19 -0
- package/dist/generator.js.map +1 -1
- package/dist/issue-cli.d.ts +62 -0
- package/dist/issue-cli.d.ts.map +1 -0
- package/dist/issue-cli.js +252 -0
- package/dist/issue-cli.js.map +1 -0
- package/dist/languages/csharp.d.ts.map +1 -1
- package/dist/languages/csharp.js +32 -11
- package/dist/languages/csharp.js.map +1 -1
- package/dist/languages/go.d.ts.map +1 -1
- package/dist/languages/go.js +5 -0
- package/dist/languages/go.js.map +1 -1
- package/dist/languages/index.d.ts +27 -0
- package/dist/languages/index.d.ts.map +1 -1
- package/dist/languages/index.js +35 -0
- package/dist/languages/index.js.map +1 -1
- package/dist/languages/java.d.ts.map +1 -1
- package/dist/languages/java.js +5 -0
- package/dist/languages/java.js.map +1 -1
- package/dist/languages/kotlin.d.ts.map +1 -1
- package/dist/languages/kotlin.js +5 -0
- package/dist/languages/kotlin.js.map +1 -1
- package/dist/languages/python.d.ts.map +1 -1
- package/dist/languages/python.js +5 -0
- package/dist/languages/python.js.map +1 -1
- package/dist/languages/ruby.d.ts.map +1 -1
- package/dist/languages/ruby.js +5 -0
- package/dist/languages/ruby.js.map +1 -1
- package/dist/languages/rust.d.ts.map +1 -1
- package/dist/languages/rust.js +5 -0
- package/dist/languages/rust.js.map +1 -1
- package/dist/languages/types.d.ts +79 -0
- package/dist/languages/types.d.ts.map +1 -1
- package/dist/languages/typescript.d.ts.map +1 -1
- package/dist/languages/typescript.js +6 -1
- package/dist/languages/typescript.js.map +1 -1
- package/package.json +2 -1
- package/templates/.claude/skills/dxkit-action/SKILL.md +126 -12
- package/templates/.claude/skills/dxkit-onboard/SKILL.md +31 -3
- package/templates/.claude/skills/dxkit-reports/SKILL.md +3 -1
- package/templates/AGENTS.md.template +8 -1
- package/dist/baseline/producers/licenses.d.ts +0 -23
- package/dist/baseline/producers/licenses.d.ts.map +0 -1
- package/dist/baseline/producers/licenses.js +0 -46
- package/dist/baseline/producers/licenses.js.map +0 -1
|
@@ -11,7 +11,7 @@ This skill takes a dxkit report and drives the fix loop with the user. Reach for
|
|
|
11
11
|
|
|
12
12
|
```
|
|
13
13
|
[1] Read the report → understand what's flagged
|
|
14
|
-
[2] Prioritize → severity + reachability + cost
|
|
14
|
+
[2] Prioritize → severity + reachability + blast radius + cost
|
|
15
15
|
[3] Plan → ordered list of edits
|
|
16
16
|
[4] Execute → fix one finding at a time
|
|
17
17
|
[5] Verify → re-run the analyzer, confirm score moved
|
|
@@ -20,6 +20,14 @@ This skill takes a dxkit report and drives the fix loop with the user. Reach for
|
|
|
20
20
|
|
|
21
21
|
Don't skip [5]. Re-running the analyzer is the only way to confirm the fix landed correctly.
|
|
22
22
|
|
|
23
|
+
For the richest input, read the **detailed** report with graph context attached:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npx vyuh-dxkit vulnerabilities --detailed --graph-context # or test-gaps / quality
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
`--graph-context` adds a "Graph context" column (the module a finding lives in + its blast radius — how many files call into it) so you can plan the fix without separately discovering structure. It's a structural HINT, not ground truth — read "Graph context" below for how to use it safely.
|
|
30
|
+
|
|
23
31
|
## Priority order
|
|
24
32
|
|
|
25
33
|
Walk findings in this order (highest to lowest):
|
|
@@ -33,6 +41,18 @@ Walk findings in this order (highest to lowest):
|
|
|
33
41
|
|
|
34
42
|
Skip items where reachability is "no" (graphify can't find a call path) UNLESS the finding is a secret leak (those don't depend on reachability).
|
|
35
43
|
|
|
44
|
+
## Graph context (structural blast radius)
|
|
45
|
+
|
|
46
|
+
When the report was generated with `--graph-context`, each finding carries a "Graph context" cell: the module/role it belongs to and its **blast radius** (`role · N caller files`) — how many other files call into the finding's file. Use it to sharpen prioritization and planning, under three hard rules.
|
|
47
|
+
|
|
48
|
+
**1. Additive only — it never overrides severity or reachability.** Blast radius is a tie-breaker between findings of similar severity, not a re-ranking of the priority list above. Among two HIGH findings, fix the one with the larger blast radius first (more depends on it). A LOW finding never jumps a HIGH one because its blast radius is bigger.
|
|
49
|
+
|
|
50
|
+
**2. A blank or zero blast radius is NOT "safe to change".** The cell reads `blast radius n/a (call graph)` for languages whose call graph the analyzer can't resolve (C# is the known case — cross-assembly references aren't followed, so heavily-used files look like they have zero callers). Treat n/a — and even a literal `0 caller files` — as **unknown**, never as evidence the file is safe to edit freely. When blast radius is n/a, fall back to the module/role label (that part is reliable) and verify callers the normal way (grep / read) before a risky edit. Do **not** deprioritize a real finding just because its blast radius is empty.
|
|
51
|
+
|
|
52
|
+
**3. Confirm the symbol before you act on it.** The context may name an enclosing symbol (the function the finding sits in). It's a best-effort guess (the graph stores declaration lines, not end lines), so open the file and confirm the finding is actually inside that symbol before editing or writing a test against it.
|
|
53
|
+
|
|
54
|
+
Used within those rules, the win is concrete: a high blast radius tells you which caller files to re-check and re-test in step [5] after the fix, and the module label orients you fast. Same-name symbols can inflate the count — a suspiciously huge number is usually conflation, not reality.
|
|
55
|
+
|
|
36
56
|
## Common fix recipes
|
|
37
57
|
|
|
38
58
|
### Secret in code
|
|
@@ -47,15 +67,17 @@ npx vyuh-dxkit vulnerabilities --json | jq '.summary.findings'
|
|
|
47
67
|
|
|
48
68
|
Don't try to redact the secret in place — the git history still has it. Rotation is the only true fix.
|
|
49
69
|
|
|
70
|
+
If the "secret" is actually a placeholder in test code (e.g., `"sk_test_xxxxxxxxxxxx"` with no real credential value), confirm with the developer and allowlist via `dxkit-allow:test-fixture` — see "Allowlisting (when fix is not viable)" below.
|
|
71
|
+
|
|
50
72
|
### SAST finding (semgrep)
|
|
51
73
|
|
|
52
74
|
```bash
|
|
53
75
|
# 1. Read the finding's rule + line range from the report
|
|
54
76
|
# 2. Open the file, understand why semgrep flagged it
|
|
55
|
-
# 3. Either FIX (preferred) or
|
|
77
|
+
# 3. Either FIX (preferred) or ALLOWLIST (carefully — see below)
|
|
56
78
|
```
|
|
57
79
|
|
|
58
|
-
|
|
80
|
+
If the finding is a true false positive or intentional pattern (test fixture, mitigated externally), suppress via dxkit's allowlist — NOT via semgrep's `// nosemgrep:`. The dxkit allowlist is the canonical surface (single source of truth across every scanner), carries a typed category + reason, and is audit-trackable through `vyuh-dxkit allowlist audit`. See "Allowlisting (when fix is not viable)" below.
|
|
59
81
|
|
|
60
82
|
### Dependency vulnerability
|
|
61
83
|
|
|
@@ -70,6 +92,8 @@ For peer-dep conflicts: `npm install <pkg>@<patched-version> --legacy-peer-deps`
|
|
|
70
92
|
|
|
71
93
|
For Python: `pip install --upgrade <pkg>=<patched>` then re-pip-freeze. For Go: `go get <pkg>@<patched>` then `go mod tidy`. For Ruby: edit Gemfile, `bundle update <pkg>`. For Rust: `cargo update -p <pkg> --precise <patched>`.
|
|
72
94
|
|
|
95
|
+
If no patched version exists OR the upgrade breaks other constraints AND the risk is mitigated externally (network policy, WAF, runtime guard), allowlist with `category=mitigated-externally` and a reason describing the mitigation. If the team is accepting the risk while waiting on a fix, `category=accepted-risk` + an expiry tied to the fix deadline.
|
|
96
|
+
|
|
73
97
|
### Test gap
|
|
74
98
|
|
|
75
99
|
```bash
|
|
@@ -93,6 +117,88 @@ Don't write tests that just import the module — write tests that exercise beha
|
|
|
93
117
|
|
|
94
118
|
If the finding is a false positive, add `// slop-ok: <reason>` on the offending line (or `# slop-ok` for non-JS).
|
|
95
119
|
|
|
120
|
+
## Allowlisting (when fix is not viable)
|
|
121
|
+
|
|
122
|
+
**Fix first.** The allowlist is the SECOND option, not the first. When you reach for it, choose deliberately — every allowlist entry is a future maintenance burden the customer's team will revisit.
|
|
123
|
+
|
|
124
|
+
Five typed categories signal WHY the suppression is in place:
|
|
125
|
+
|
|
126
|
+
| Category | Meaning | Where it lives |
|
|
127
|
+
|---|---|---|
|
|
128
|
+
| `false-positive` | Scanner is wrong about this code | Inline annotation OR file-level |
|
|
129
|
+
| `test-fixture` | Intentional pattern in a fixture / test file | Inline annotation OR file-level |
|
|
130
|
+
| `mitigated-externally` | Real risk but neutralized at runtime (WAF, env, etc.) | Inline annotation OR file-level |
|
|
131
|
+
| `accepted-risk` | Real risk, accepted by the team, signed off | File-level only (needs expiry + acknowledged severity) |
|
|
132
|
+
| `deferred` | Real, will fix later, tracked work | File-level only (needs expiry) |
|
|
133
|
+
|
|
134
|
+
`accepted-risk` and `deferred` require an `expiresAt` date because they describe assertions that should age out — by default the CLI sets 90 days. `false-positive`, `test-fixture`, and `mitigated-externally` describe assertions that don't naturally stale; they may omit expiry.
|
|
135
|
+
|
|
136
|
+
### The two surfaces
|
|
137
|
+
|
|
138
|
+
**Inline annotation** is the natural fit for source-anchored findings (secrets, code, config, dep-vuln, hygiene) with an inline-compatible category. The annotation lives next to the line it suppresses:
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
api_key = "sk_test_xxxx" # dxkit-allow:test-fixture reason="placeholder in unit test"
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Or, for long source lines, above:
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
// dxkit-allow:false-positive reason="regex matches intentional placeholder"
|
|
148
|
+
const apiKey = "sk_test_xxxx";
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
The grammar is uniform across every language; only the comment marker varies (`#` for python/ruby, `//` for typescript/go/rust/csharp/kotlin/java). Don't type it by hand — let dxkit insert it for you (see CLI below).
|
|
152
|
+
|
|
153
|
+
**File-level allowlist** lives at `.dxkit/allowlist.json` and is the surface for:
|
|
154
|
+
|
|
155
|
+
- Cross-file or whole-file findings (duplication, coverage-gap, test-gap, god-file, large-file, stale-file)
|
|
156
|
+
- Findings with no stable single-line attachment (dep-vuln, secret-hmac)
|
|
157
|
+
- Any `accepted-risk` or `deferred` suppression regardless of kind
|
|
158
|
+
|
|
159
|
+
### Add an allowlist entry (canonical path)
|
|
160
|
+
|
|
161
|
+
Don't hand-edit the annotation comment or the JSON file — let the CLI insert it correctly:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
# Inline annotation at file:line — for source-anchored findings
|
|
165
|
+
# with an inline-compatible category
|
|
166
|
+
npx vyuh-dxkit allowlist add src/auth/oauth.ts:42 \
|
|
167
|
+
--category=test-fixture --reason="placeholder in unit test"
|
|
168
|
+
|
|
169
|
+
# File-level entry — for everything else (kind + fingerprint required;
|
|
170
|
+
# both come straight from the guardrail check's output)
|
|
171
|
+
npx vyuh-dxkit allowlist add --fingerprint=a3f9c0e8b7d2e1f4 \
|
|
172
|
+
--kind=dep-vuln --category=accepted-risk \
|
|
173
|
+
--reason="WAF rule X mitigates this CVE" --expires=2026-08-22
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
The guardrail's block message gives you the exact command to paste for every blocked finding — file path + line for inline-compatible kinds, fingerprint + kind for everything else. Just copy-paste.
|
|
177
|
+
|
|
178
|
+
### When the finding only carries an id (sanitized / ref-based baseline)
|
|
179
|
+
|
|
180
|
+
If you're seeing a blocked finding labelled `<sanitized>` (in `baseline show` output) OR with no `file`/`line` columns in the PR-comment table, the repo's baseline mode is `committed-sanitized` or `ref-based` and the human-readable locator was stripped at write time. Two options:
|
|
181
|
+
|
|
182
|
+
- **Inspect the finding in the current scan.** The fingerprint pairs against the live scan's output, which is rich (always). Re-run the matching analyzer (`vyuh-dxkit vulnerabilities`, `vyuh-dxkit health`, etc.) and grep the JSON output for the fingerprint — that finding has full file:line context.
|
|
183
|
+
- **Allowlist by fingerprint anyway.** File-level allowlist entries only need fingerprint + kind, both of which the guardrail message still provides. The category + reason apply regardless of whether the locator is visible at baseline time.
|
|
184
|
+
|
|
185
|
+
The fingerprint contract is preserved across all three modes — `committed-full`, `committed-sanitized`, `ref-based` all produce the same identity bytes for the same finding. Sanitization only strips the human-readable rendering; it doesn't change which findings pair across runs.
|
|
186
|
+
|
|
187
|
+
### Review what's allowlisted
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
npx vyuh-dxkit allowlist list # all entries (text)
|
|
191
|
+
npx vyuh-dxkit allowlist show <fingerprint> # one entry's full detail
|
|
192
|
+
npx vyuh-dxkit allowlist audit # expired / soon-to-expire / missing-rationale
|
|
193
|
+
npx vyuh-dxkit allowlist prune # remove expired entries
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Run `audit` periodically — `accepted-risk` and `deferred` entries that pass their expiry should either be re-justified (renew expiry) or pruned (remove the entry; the underlying finding will re-flag on the next scan).
|
|
197
|
+
|
|
198
|
+
### Stale annotations
|
|
199
|
+
|
|
200
|
+
If the underlying finding is fixed but the inline annotation lingers, the next scan emits a `stale-allow` finding pointing at the orphaned comment. The remediation is always to remove the annotation — dxkit refuses to allowlist a stale-allow finding (allowlisting the warning that an annotation is stale would defeat the entire model).
|
|
201
|
+
|
|
96
202
|
## Verification — never skip
|
|
97
203
|
|
|
98
204
|
After each fix:
|
|
@@ -111,14 +217,19 @@ If the finding's still there: the fix didn't work, try again.
|
|
|
111
217
|
|
|
112
218
|
## Baseline decisions
|
|
113
219
|
|
|
114
|
-
Once a finding is fixed
|
|
220
|
+
Once a finding is processed (fixed, allowlisted, or accepted), the workflow depends on which path you took:
|
|
115
221
|
|
|
116
222
|
| Scenario | Action |
|
|
117
223
|
|---|---|
|
|
118
|
-
| Fix landed via a code change | Commit the code. Baseline
|
|
224
|
+
| Fix landed via a code change | Commit the code. Baseline + allowlist are unchanged. Future scans confirm the fix held. |
|
|
225
|
+
| Genuine false positive OR intentional pattern | `vyuh-dxkit allowlist add` with `category=false-positive` or `test-fixture`. Commit the annotation / allowlist file. Baseline is unchanged. |
|
|
226
|
+
| Real risk neutralized externally (WAF, runtime guard) | `vyuh-dxkit allowlist add` with `category=mitigated-externally` + a reason describing the mitigation. Baseline unchanged. |
|
|
227
|
+
| Real risk, accepted by team, won't fix | `vyuh-dxkit allowlist add` with `category=accepted-risk` + `--expires=YYYY-MM-DD` (defaults 90 days). Acknowledged-severity required for high/critical. |
|
|
228
|
+
| Real risk, will fix later (tracked work) | `vyuh-dxkit allowlist add` with `category=deferred` + `--expires=YYYY-MM-DD`. The expiry forces re-review when the deadline passes. |
|
|
119
229
|
| Fix landed via a config change (e.g., new entry in `.dxkit-ignore`) | Re-baseline: `npx vyuh-dxkit baseline create --force`. Commit both `.dxkit-ignore` and the new baseline. |
|
|
120
|
-
|
|
|
121
|
-
|
|
230
|
+
| Brownfield acceptance (the whole CURRENT state is known mess; future regressions must be net-new) | Re-baseline with an explicit reason in the commit message. Reserve this for the deliberate "draw a line here" moment, not per-finding suppression. |
|
|
231
|
+
|
|
232
|
+
**Prefer the allowlist over re-baselining for per-finding decisions.** The allowlist carries a typed category + reason + (when relevant) expiry; the baseline carries only "this finding was here." Future maintainers reading `vyuh-dxkit allowlist show <fingerprint>` see WHY the suppression is in place; reading the baseline file shows only that the finding existed at capture time. Per-finding decisions belong in the allowlist; codebase-wide brownfield acceptance belongs in the baseline.
|
|
122
233
|
|
|
123
234
|
**Never** re-baseline a finding silently — the commit message should explain why the regression is accepted. Future maintainers reading `git log .dxkit/baselines/` should see the rationale.
|
|
124
235
|
|
|
@@ -134,17 +245,20 @@ Exit 0 = your fixes didn't introduce any net-new regressions (you only removed/f
|
|
|
134
245
|
|
|
135
246
|
## When fixes get expensive
|
|
136
247
|
|
|
137
|
-
Sometimes the right call is: don't fix,
|
|
248
|
+
Sometimes the right call is: don't fix, allowlist (or re-baseline if it's brownfield-wide).
|
|
138
249
|
|
|
139
250
|
Examples:
|
|
140
|
-
- Legacy code on a deprecation path (sunset > fix)
|
|
141
|
-
- A SAST finding in vendored code you don't maintain
|
|
142
|
-
- A test gap on a one-off script that doesn't merit tests
|
|
251
|
+
- Legacy code on a deprecation path (sunset > fix) → `accepted-risk` with expiry matching the sunset date
|
|
252
|
+
- A SAST finding in vendored code you don't maintain → `mitigated-externally` if the vendor patches separately, else `accepted-risk`
|
|
253
|
+
- A test gap on a one-off script that doesn't merit tests → `accepted-risk`
|
|
254
|
+
- An import line flagged by a scanner that you've reviewed and confirmed safe → `false-positive` inline annotation at the import
|
|
143
255
|
|
|
144
|
-
In those cases:
|
|
256
|
+
In those cases: `vyuh-dxkit allowlist add` is the right tool for per-finding decisions (typed reason + expiry where relevant). Reserve "accept as baseline" for the deliberate one-shot brownfield moment ("this entire current state is known mess; today's findings are the new baseline"). The two surfaces complement each other — allowlist for individual judgment calls, baseline for the codebase-wide line in the sand.
|
|
145
257
|
|
|
146
258
|
## Hand-offs
|
|
147
259
|
|
|
148
260
|
- For ignore-file edits as part of a fix → `dxkit-config` skill
|
|
149
261
|
- For hook-related issues during a fix push → `dxkit-hooks` skill
|
|
150
262
|
- For re-running reports between fixes → `dxkit-reports` skill
|
|
263
|
+
- For broken dxkit install (hooks not firing, vyuh-dxkit not on PATH) → `dxkit-fix` skill
|
|
264
|
+
- For allowlist management beyond the per-finding `add` path (auditing existing entries, pruning expired ones, reviewing the team's overall suppression posture) → run `npx vyuh-dxkit allowlist audit` / `list` / `prune` directly; no separate skill yet
|
|
@@ -113,7 +113,19 @@ Don't auto-execute baseline capture here — step 5 has a values-laden warning t
|
|
|
113
113
|
|
|
114
114
|
This is the step with permanent consequences. The baseline records the fingerprint of every finding currently in the repo and tells future scans "these are pre-existing — don't block on them."
|
|
115
115
|
|
|
116
|
-
Before running `baseline create` on a fresh customer:
|
|
116
|
+
Before running `baseline create` on a fresh customer, ASK about disclosure posture (the baseline file is committed to git):
|
|
117
|
+
|
|
118
|
+
> **About to capture the first baseline. One quick choice first — which posture fits this repo?**
|
|
119
|
+
>
|
|
120
|
+
> The baseline file lives at `.dxkit/baselines/main.json`. Three modes trade disclosure for diagnostic richness:
|
|
121
|
+
>
|
|
122
|
+
> - **`committed-full`** (default for private repos) — Rich entries with file paths, package names, advisory IDs. Best diagnostic quality. Fine when only your team reads the repo.
|
|
123
|
+
> - **`committed-sanitized`** (compliance-conscious private) — Stripped to fingerprint + kind only. Hides location detail; matching still works. Good when many people have repo read access.
|
|
124
|
+
> - **`ref-based`** (default for public repos) — No baseline file at all. Each guardrail check recomputes the prior side from a git ref (e.g. `origin/main`). Zero disclosure.
|
|
125
|
+
>
|
|
126
|
+
> Auto-pick: run `vyuh-dxkit baseline create` and dxkit picks the right default by probing `gh repo view`. Or pin explicitly via `--mode=<X>` or `.dxkit/policy.json`.
|
|
127
|
+
|
|
128
|
+
Then the standard "lock-in" warning:
|
|
117
129
|
|
|
118
130
|
> **About to capture the first baseline.**
|
|
119
131
|
>
|
|
@@ -125,14 +137,30 @@ Before running `baseline create` on a fresh customer:
|
|
|
125
137
|
|
|
126
138
|
If they want to triage first, hand off to `dxkit-action` — that skill prioritizes findings before baseline lock-in. Come back to step 5 after triage.
|
|
127
139
|
|
|
128
|
-
If they confirm baseline:
|
|
140
|
+
If they confirm baseline (and they're happy with auto-picked mode):
|
|
129
141
|
|
|
130
142
|
```bash
|
|
131
143
|
npx vyuh-dxkit baseline create
|
|
132
|
-
git add .dxkit/baselines/
|
|
144
|
+
git add .dxkit/baselines/ # only if mode wrote a file (committed-*)
|
|
133
145
|
git commit -m "chore: capture dxkit baseline"
|
|
134
146
|
```
|
|
135
147
|
|
|
148
|
+
If they want to PIN the mode explicitly (so every developer + CI run agrees), write `.dxkit/policy.json`:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
mkdir -p .dxkit
|
|
152
|
+
cat > .dxkit/policy.json <<'JSON'
|
|
153
|
+
{
|
|
154
|
+
"baseline": {
|
|
155
|
+
"mode": "ref-based",
|
|
156
|
+
"ref": "origin/main"
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
JSON
|
|
160
|
+
git add .dxkit/policy.json
|
|
161
|
+
git commit -m "chore: pin baseline mode in policy.json"
|
|
162
|
+
```
|
|
163
|
+
|
|
136
164
|
### 6. Pre-commit ASK
|
|
137
165
|
|
|
138
166
|
Pre-commit is opt-in even under `--full` because it re-runs every analyzer on every commit (~1-3 min on 500+ file repos). Most teams skip it.
|
|
@@ -19,7 +19,9 @@ This skill runs dxkit analyzers and reads their output back to the user. It's th
|
|
|
19
19
|
| "License inventory" | `npx vyuh-dxkit licenses` | Every dependency's declared license |
|
|
20
20
|
| "Bill of materials" | `npx vyuh-dxkit bom` | Licenses + dep vulnerabilities joined (15-col XLSX-ready output) |
|
|
21
21
|
| "Run everything" | `npx vyuh-dxkit report` | Every analyzer in one shot, ~3-5 min |
|
|
22
|
-
| "Show me the dashboard" | `npx vyuh-dxkit dashboard` | Single HTML view of all reports — opens at `.dxkit/reports/dashboard.html
|
|
22
|
+
| "Show me the dashboard" | `npx vyuh-dxkit dashboard` | Single HTML view of all reports — opens at `.dxkit/reports/dashboard.html`, incl. an interactive **Graph** tab (code structure) |
|
|
23
|
+
| "What does this repo do / where is X" | `npx vyuh-dxkit explore <sub>` | Query the code graph: entry-points / hot-files / communities / file / feature / api-surface |
|
|
24
|
+
| "Token-efficient context for a query" | `npx vyuh-dxkit context <query>` | Slim structural slice for an LLM (also a fix-time hint via `--graph-context`) |
|
|
23
25
|
|
|
24
26
|
## Where output lands
|
|
25
27
|
|
|
@@ -114,12 +114,19 @@ Reach for the relevant skill when working in this repo. They wrap the `vyuh-dxki
|
|
|
114
114
|
| Test coverage gaps | `npx vyuh-dxkit test-gaps` |
|
|
115
115
|
| Code quality + slop | `npx vyuh-dxkit quality` |
|
|
116
116
|
| Bill of materials | `npx vyuh-dxkit bom` |
|
|
117
|
-
| Dashboard (HTML) | `npx vyuh-dxkit dashboard` |
|
|
117
|
+
| Dashboard (HTML, incl. interactive Graph tab) | `npx vyuh-dxkit dashboard` |
|
|
118
|
+
| What does this repo do / where does X live | `npx vyuh-dxkit explore <sub>` |
|
|
119
|
+
| Token-efficient structural context for a query | `npx vyuh-dxkit context <query>` |
|
|
118
120
|
| Guardrail check (baseline diff) | `npx vyuh-dxkit guardrail check` |
|
|
119
121
|
| Doctor (verify setup) | `npx vyuh-dxkit doctor` |
|
|
120
122
|
|
|
121
123
|
The pre-push hook runs `guardrail check` automatically — blocks net-new regressions before they leave your machine.
|
|
122
124
|
|
|
125
|
+
When fixing findings, run the detailed report with `--graph-context`
|
|
126
|
+
(e.g. `npx vyuh-dxkit vulnerabilities --detailed --graph-context`) — it
|
|
127
|
+
attaches each finding's module + blast radius so you can navigate by the
|
|
128
|
+
code graph instead of repeated whole-file reads.
|
|
129
|
+
|
|
123
130
|
## Security rules — never violate
|
|
124
131
|
|
|
125
132
|
1. **Never output, log, or commit secrets** — no API keys, tokens, passwords, or credentials in code, commits, or files Claude writes
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Licenses → baseline-entry producer.
|
|
3
|
-
*
|
|
4
|
-
* One kind: `license` — per-package license attribution.
|
|
5
|
-
* `(package, version, licenseType)` is the identity tuple, so a
|
|
6
|
-
* re-licensing event on the same pinned version (compliance teams'
|
|
7
|
-
* canonical concern) registers as a fresh finding even when no
|
|
8
|
-
* version bump happened.
|
|
9
|
-
*
|
|
10
|
-
* Reads from `CapabilityReport.licenses.findings` — already in the
|
|
11
|
-
* cached `AnalysisResult`, no extra gather work needed. Pure
|
|
12
|
-
* function over its input.
|
|
13
|
-
*/
|
|
14
|
-
import type { BaselineEntry } from '../types';
|
|
15
|
-
import type { LicensesResult } from '../../languages/capabilities/types';
|
|
16
|
-
/**
|
|
17
|
-
* Build `license` entries from a licenses capability envelope.
|
|
18
|
-
* Findings with an empty `licenseType` are emitted with the literal
|
|
19
|
-
* `'UNKNOWN'` so identity stays stable across runs even when the
|
|
20
|
-
* underlying tool can't resolve the SPDX id.
|
|
21
|
-
*/
|
|
22
|
-
export declare function licensesToBaselineEntries(licenses: LicensesResult | undefined): BaselineEntry[];
|
|
23
|
-
//# sourceMappingURL=licenses.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"licenses.d.ts","sourceRoot":"","sources":["../../../src/baseline/producers/licenses.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAwB,MAAM,UAAU,CAAC;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEzE;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,cAAc,GAAG,SAAS,GAAG,aAAa,EAAE,CAoB/F"}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Licenses → baseline-entry producer.
|
|
4
|
-
*
|
|
5
|
-
* One kind: `license` — per-package license attribution.
|
|
6
|
-
* `(package, version, licenseType)` is the identity tuple, so a
|
|
7
|
-
* re-licensing event on the same pinned version (compliance teams'
|
|
8
|
-
* canonical concern) registers as a fresh finding even when no
|
|
9
|
-
* version bump happened.
|
|
10
|
-
*
|
|
11
|
-
* Reads from `CapabilityReport.licenses.findings` — already in the
|
|
12
|
-
* cached `AnalysisResult`, no extra gather work needed. Pure
|
|
13
|
-
* function over its input.
|
|
14
|
-
*/
|
|
15
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
-
exports.licensesToBaselineEntries = licensesToBaselineEntries;
|
|
17
|
-
const finding_identity_1 = require("../finding-identity");
|
|
18
|
-
/**
|
|
19
|
-
* Build `license` entries from a licenses capability envelope.
|
|
20
|
-
* Findings with an empty `licenseType` are emitted with the literal
|
|
21
|
-
* `'UNKNOWN'` so identity stays stable across runs even when the
|
|
22
|
-
* underlying tool can't resolve the SPDX id.
|
|
23
|
-
*/
|
|
24
|
-
function licensesToBaselineEntries(licenses) {
|
|
25
|
-
if (!licenses)
|
|
26
|
-
return [];
|
|
27
|
-
const out = [];
|
|
28
|
-
for (const f of licenses.findings) {
|
|
29
|
-
const licenseType = f.licenseType.length > 0 ? f.licenseType : 'UNKNOWN';
|
|
30
|
-
const input = {
|
|
31
|
-
kind: 'license',
|
|
32
|
-
package: f.package,
|
|
33
|
-
version: f.version,
|
|
34
|
-
licenseType,
|
|
35
|
-
};
|
|
36
|
-
out.push({
|
|
37
|
-
id: (0, finding_identity_1.identityFor)(input),
|
|
38
|
-
kind: 'license',
|
|
39
|
-
package: f.package,
|
|
40
|
-
version: f.version,
|
|
41
|
-
licenseType,
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
return out;
|
|
45
|
-
}
|
|
46
|
-
//# sourceMappingURL=licenses.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"licenses.js","sourceRoot":"","sources":["../../../src/baseline/producers/licenses.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;;AAYH,8DAoBC;AA9BD,0DAAkD;AAIlD;;;;;GAKG;AACH,SAAgB,yBAAyB,CAAC,QAAoC;IAC5E,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,CAAC;IACzB,MAAM,GAAG,GAAoB,EAAE,CAAC;IAChC,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;QAClC,MAAM,WAAW,GAAG,CAAC,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;QACzE,MAAM,KAAK,GAAyB;YAClC,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,WAAW;SACZ,CAAC;QACF,GAAG,CAAC,IAAI,CAAC;YACP,EAAE,EAAE,IAAA,8BAAW,EAAC,KAAK,CAAC;YACtB,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,WAAW;SACZ,CAAC,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|