@secureport/core 1.0.0 → 2.2.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.
Files changed (51) hide show
  1. package/README.md +2 -1
  2. package/dist/finding.d.ts +9 -8
  3. package/dist/finding.d.ts.map +1 -1
  4. package/dist/fingerprint.d.ts +12 -5
  5. package/dist/fingerprint.d.ts.map +1 -1
  6. package/dist/fingerprint.js +74 -8
  7. package/dist/fingerprint.js.map +1 -1
  8. package/dist/import/nessus.d.ts +9 -6
  9. package/dist/import/nessus.d.ts.map +1 -1
  10. package/dist/import/nessus.js +9 -6
  11. package/dist/import/nessus.js.map +1 -1
  12. package/dist/index.d.ts +6 -3
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +3 -1
  15. package/dist/index.js.map +1 -1
  16. package/dist/issue.d.ts +1 -1
  17. package/dist/issue.d.ts.map +1 -1
  18. package/dist/reconcile.d.ts +71 -1
  19. package/dist/reconcile.d.ts.map +1 -1
  20. package/dist/reconcile.js +64 -4
  21. package/dist/reconcile.js.map +1 -1
  22. package/dist/refingerprint.d.ts +116 -0
  23. package/dist/refingerprint.d.ts.map +1 -0
  24. package/dist/refingerprint.js +190 -0
  25. package/dist/refingerprint.js.map +1 -0
  26. package/dist/report/anchors.d.ts +39 -0
  27. package/dist/report/anchors.d.ts.map +1 -0
  28. package/dist/report/anchors.js +73 -0
  29. package/dist/report/anchors.js.map +1 -0
  30. package/dist/report/html.d.ts.map +1 -1
  31. package/dist/report/html.js +126 -22
  32. package/dist/report/html.js.map +1 -1
  33. package/dist/report/markdown.d.ts.map +1 -1
  34. package/dist/report/markdown.js +112 -26
  35. package/dist/report/markdown.js.map +1 -1
  36. package/dist/report/model.d.ts +227 -1
  37. package/dist/report/model.d.ts.map +1 -1
  38. package/dist/report/model.js +87 -8
  39. package/dist/report/model.js.map +1 -1
  40. package/package.json +1 -1
  41. package/src/finding.ts +9 -8
  42. package/src/fingerprint.ts +76 -10
  43. package/src/import/nessus.ts +9 -6
  44. package/src/index.ts +14 -2
  45. package/src/issue.ts +1 -0
  46. package/src/reconcile.ts +121 -5
  47. package/src/refingerprint.ts +282 -0
  48. package/src/report/anchors.ts +96 -0
  49. package/src/report/html.ts +146 -26
  50. package/src/report/markdown.ts +125 -25
  51. package/src/report/model.ts +344 -7
package/README.md CHANGED
@@ -51,6 +51,7 @@ renderMarkdown(snapshot, { kind: 'retest', now });
51
51
  | **Importers** | `importNuclei`, `importZap`, `importBurp`, `importNessus`, `importGeneric` |
52
52
  | **Fingerprint** | `fingerprint`, `vulnKey`, `normaliseLocation`, `FINGERPRINT_VERSION` |
53
53
  | **Reconciliation** | `reconcile` — the only thing that changes issue state |
54
+ | **Migration** | `planRefingerprint` — what a version bump would do, before it does it |
54
55
  | **Coverage** | `coversLocation` — what makes auto-resolution safe |
55
56
  | **Snapshots** | `buildSnapshot`, `parseSnapshot` |
56
57
  | **Reports** | `renderMarkdown`, `renderHtml`, `renderJson`, `buildReportModel` |
@@ -139,7 +140,7 @@ because they outlive any one version of this package.
139
140
  ### `fingerprint_version`
140
141
 
141
142
  An issue's identity is the pair `(fingerprintVersion, fingerprint)`, not the
142
- fingerprint alone. `FINGERPRINT_VERSION` is `fp_v1` and it travels with every
143
+ fingerprint alone. `FINGERPRINT_VERSION` is `fp_v2` and it travels with every
143
144
  fingerprint everywhere it is stored, so a fingerprint written today can always
144
145
  be interpreted — including by code that has moved on.
145
146
 
package/dist/finding.d.ts CHANGED
@@ -76,15 +76,16 @@ export interface Finding {
76
76
  *
77
77
  * **Recorded, not addressed.** The port is already inside
78
78
  * {@link Finding.location} for host-oriented engines (Nessus assembles
79
- * `host:port`) and is already a fingerprint component, so this field changes
80
- * neither. It exists because a port was otherwise unrecoverable from a
81
- * finding except by parsing its location, which is not something a consumer
82
- * should have to do.
79
+ * `host:port`), and that location is what the fingerprint reads. It exists
80
+ * because a port was otherwise unrecoverable from a finding except by
81
+ * parsing its location, which is not something a consumer should have to do.
83
82
  *
84
- * Deliberately **not** added to the fingerprint inputs: doing so would move
85
- * every existing Nessus fingerprint and force a re-fingerprint migration,
86
- * which is a far worse outcome than a field being merely inconvenient to
87
- * read.
83
+ * **No longer a fingerprint component at all, as of `fp_v2`.** It used to
84
+ * fill the last slot when no parameter was named, which counted a Nessus
85
+ * port twice and stopped a network scan ever matching a web scan of the same
86
+ * endpoint. The location carries the port now, canonicalised — so a default
87
+ * port drops and any other is kept, which is the distinction that actually
88
+ * matters.
88
89
  */
89
90
  readonly port?: number;
90
91
  /** Pointers to stored evidence: request/response captures, screenshots. */
@@ -1 +1 @@
1
- {"version":3,"file":"finding.d.ts","sourceRoot":"","sources":["../src/finding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE9D;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,OAAO;IACtB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB,oEAAoE;IACpE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,gCAAgC;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB;;;;;;;OAOG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAE7B;;;;;;;OAOG;IACH,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IAEpC,kDAAkD;IAClD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,+CAA+C;IAC/C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAE9B;;;;;OAKG;IACH,QAAQ,CAAC,gBAAgB,EAAE,QAAQ,CAAC;IAEpC,0DAA0D;IAC1D,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IAExC,kEAAkE;IAClE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAE5B,kDAAkD;IAClD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAE7B,qCAAqC;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAEtB,4CAA4C;IAC5C,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAE3B,2DAA2D;IAC3D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,qEAAqE;IACrE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAE5B;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAEvB,2EAA2E;IAC3E,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAEzC,2BAA2B;IAC3B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAEjC,iEAAiE;IACjE,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAExC,wEAAwE;IACxE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAE9B,2DAA2D;IAC3D,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAE/B,kEAAkE;IAClE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAE7B,qCAAqC;IACrC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;CAC1B"}
1
+ {"version":3,"file":"finding.d.ts","sourceRoot":"","sources":["../src/finding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE9D;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,OAAO;IACtB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB,oEAAoE;IACpE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,gCAAgC;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB;;;;;;;OAOG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAE7B;;;;;;;OAOG;IACH,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IAEpC,kDAAkD;IAClD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,+CAA+C;IAC/C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAE9B;;;;;OAKG;IACH,QAAQ,CAAC,gBAAgB,EAAE,QAAQ,CAAC;IAEpC,0DAA0D;IAC1D,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IAExC,kEAAkE;IAClE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAE5B,kDAAkD;IAClD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAE7B,qCAAqC;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAEtB,4CAA4C;IAC5C,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAE3B,2DAA2D;IAC3D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,qEAAqE;IACrE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAE5B;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAEvB,2EAA2E;IAC3E,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAEzC,2BAA2B;IAC3B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAEjC,iEAAiE;IACjE,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAExC,wEAAwE;IACxE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAE9B,2DAA2D;IAC3D,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAE/B,kEAAkE;IAClE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAE7B,qCAAqC;IACrC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;CAC1B"}
@@ -11,7 +11,7 @@
11
11
  * If you are tempted to "just tweak" the normaliser, that is this constant's
12
12
  * job to prevent.
13
13
  */
14
- export declare const FINGERPRINT_VERSION = "fp_v1";
14
+ export declare const FINGERPRINT_VERSION = "fp_v2";
15
15
  /**
16
16
  * The placeholder that a variable path segment collapses to.
17
17
  *
@@ -43,10 +43,17 @@ export declare const PATH_PLACEHOLDER = "{id}";
43
43
  * one issue into two.
44
44
  * - **Drops the fragment**, which the server never sees.
45
45
  *
46
- * Anything that is not a parseable absolute URL — a bare host, a file path, a
47
- * `host:port` pair from a network scan — is normalised as a path alone. That is
48
- * deliberate: refusing to fingerprint a non-HTTP finding would exclude whole
49
- * classes of scanner from the model.
46
+ * - **Reads `host:443` and `host:80` as the URL the port implies**, so a
47
+ * network scanner's `app.example.com:443` and a web scanner's
48
+ * `https://app.example.com/` are one endpoint (B102, `fp_v2`). Only those two
49
+ * ports: any other is left alone rather than guessed at, because
50
+ * `host:8443` could be TLS or plaintext and inventing a scheme to force a
51
+ * match would assert something nobody measured.
52
+ *
53
+ * Anything else that is not a parseable absolute URL — a bare host, a file
54
+ * path — is normalised as a path alone. That is deliberate: refusing to
55
+ * fingerprint a non-HTTP finding would exclude whole classes of scanner from
56
+ * the model.
50
57
  *
51
58
  * @param location - Where the weakness was found.
52
59
  * @returns The normalised location.
@@ -1 +1 @@
1
- {"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../src/fingerprint.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,mBAAmB,UAAU,CAAC;AAQ3C;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,SAAS,CAAC;AA6BvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CA2B1D;AAiBD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,sDAAsD;IACtD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAE9B,2DAA2D;IAC3D,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAE/B,qCAAqC;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAEtB,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAcxD,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAmBnD;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;OAOG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,iEAAiE;IACjE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,4DAA4D;IAC5D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAE5B,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CAO3D"}
1
+ {"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../src/fingerprint.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,mBAAmB,UAAU,CAAC;AAQ3C;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,SAAS,CAAC;AA6BvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CA6B1D;AA2CD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,sDAAsD;IACtD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAE9B,2DAA2D;IAC3D,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAE/B,qCAAqC;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAEtB,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAuBxD,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAmBnD;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;OAOG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,iEAAiE;IACjE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,4DAA4D;IAC5D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAE5B,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CAuB3D"}
@@ -12,7 +12,7 @@ import { createHash } from 'node:crypto';
12
12
  * If you are tempted to "just tweak" the normaliser, that is this constant's
13
13
  * job to prevent.
14
14
  */
15
- export const FINGERPRINT_VERSION = 'fp_v1';
15
+ export const FINGERPRINT_VERSION = 'fp_v2';
16
16
  /** A path segment that is entirely digits, e.g. the `123` in `/orders/123`. */
17
17
  const NUMERIC_SEGMENT = /^\d+$/u;
18
18
  /** A path segment that is a UUID in the canonical 8-4-4-4-12 form. */
@@ -75,10 +75,17 @@ function collapseSegment(segment) {
75
75
  * one issue into two.
76
76
  * - **Drops the fragment**, which the server never sees.
77
77
  *
78
- * Anything that is not a parseable absolute URL — a bare host, a file path, a
79
- * `host:port` pair from a network scan — is normalised as a path alone. That is
80
- * deliberate: refusing to fingerprint a non-HTTP finding would exclude whole
81
- * classes of scanner from the model.
78
+ * - **Reads `host:443` and `host:80` as the URL the port implies**, so a
79
+ * network scanner's `app.example.com:443` and a web scanner's
80
+ * `https://app.example.com/` are one endpoint (B102, `fp_v2`). Only those two
81
+ * ports: any other is left alone rather than guessed at, because
82
+ * `host:8443` could be TLS or plaintext and inventing a scheme to force a
83
+ * match would assert something nobody measured.
84
+ *
85
+ * Anything else that is not a parseable absolute URL — a bare host, a file
86
+ * path — is normalised as a path alone. That is deliberate: refusing to
87
+ * fingerprint a non-HTTP finding would exclude whole classes of scanner from
88
+ * the model.
82
89
  *
83
90
  * @param location - Where the weakness was found.
84
91
  * @returns The normalised location.
@@ -101,7 +108,10 @@ export function normaliseLocation(location) {
101
108
  // Not an absolute URL: normalise it as a bare path and stop. `new URL` would
102
109
  // otherwise turn `example.com/x` into the `example.com:` protocol.
103
110
  if (!url || url.protocol === '' || !url.host) {
104
- return normalisePathOnly(trimmed);
111
+ const implied = impliedSchemeUrl(trimmed);
112
+ if (implied === undefined)
113
+ return normalisePathOnly(trimmed);
114
+ url = implied;
105
115
  }
106
116
  // Not `decodeOnce` here: normalisePathOnly decodes, and decoding on the way
107
117
  // in as well would decode twice — which would fold `%252F` into `%2F` into
@@ -113,6 +123,33 @@ export function normaliseLocation(location) {
113
123
  const query = names.length > 0 ? `?${names.join('&')}` : '';
114
124
  return `${url.protocol}//${url.host}${path}${query}`;
115
125
  }
126
+ /**
127
+ * A bare `host:port` read as the URL its port implies, or `undefined`.
128
+ *
129
+ * **Only `:443` and `:80`, and that restraint is the point.** A network scanner
130
+ * reports `app.example.com:443` for the weakness a web scanner reports at
131
+ * `https://app.example.com/`, and those are one endpoint: 443 means TLS and an
132
+ * empty path means the root. Both are convention rather than guarantee, but
133
+ * they are conventions every scanner in this model already relies on, and
134
+ * leaving the two unmatched means a network scan and a web scan of one host
135
+ * can never agree about anything — which is the duplication P6 exists to
136
+ * remove (B102).
137
+ *
138
+ * Any other port is left alone rather than guessed at. `app.example.com:8443`
139
+ * could be TLS or plaintext, and inventing a scheme to make a match happen
140
+ * would be asserting something nobody measured.
141
+ */
142
+ function impliedSchemeUrl(location) {
143
+ const match = /^([a-z0-9.\-_]+|\[[0-9a-f:]+\]):(443|80)$/iu.exec(location);
144
+ if (!match)
145
+ return undefined;
146
+ try {
147
+ return new URL(`${match[2] === '443' ? 'https' : 'http'}://${location}`);
148
+ }
149
+ catch {
150
+ return undefined;
151
+ }
152
+ }
116
153
  /**
117
154
  * Normalises a path with no scheme or host.
118
155
  */
@@ -167,6 +204,14 @@ export const VULN_KEY_MAP = Object.freeze({
167
204
  // the other stops the two agreeing, so these travel together.
168
205
  'nuclei:xss-reflected': 'xss-reflected',
169
206
  'nuclei:missing-hsts': 'hsts-missing',
207
+ // Burp and Nessus, added in `fp_v2`. Neither had a single entry, so both fell
208
+ // through to the CWE for every finding — which is worse than no table at all:
209
+ // ZAP and Nuclei keyed `hsts-missing` while Burp and Nessus keyed `CWE-319`
210
+ // for the same weakness, so half a table was actively splitting issues that a
211
+ // plain CWE fallback would have kept together.
212
+ 'burp:5244160': 'xss-reflected',
213
+ 'burp:6234880': 'hsts-missing',
214
+ 'nessus:42822': 'hsts-missing',
170
215
  });
171
216
  /**
172
217
  * The engine-independent key for a weakness class.
@@ -240,8 +285,29 @@ export function vulnKey(input) {
240
285
  * ```
241
286
  */
242
287
  export function fingerprint(input) {
243
- const tail = input.parameter ?? (input.port !== undefined ? String(input.port) : '');
244
- const material = [input.targetId, input.vulnKey, normaliseLocation(input.location), tail].join('|');
288
+ // The port is no longer part of the tail. `normaliseLocation` now canonicalises
289
+ // a `host:port` location, so a non-default port is already in the location and
290
+ // a default one is deliberately absent from it — counting the port again here
291
+ // made a Nessus finding on 443 unable to match a web scanner's finding on the
292
+ // same endpoint. `import/nessus.ts` recorded this double-count as something
293
+ // that had to stay because removing it would force a re-fingerprint migration;
294
+ // `fp_v2` is that migration.
295
+ const tail = input.parameter ?? '';
296
+ // A named parameter makes the query string redundant: both describe the same
297
+ // input, and keeping the query too means a scanner that reports the parameter
298
+ // separately (Burp: `/search`, parameter `q`) can never match one that leaves
299
+ // it in the URL (ZAP: `/search?q=test`, parameter `q`). When no parameter is
300
+ // named the query names stay, because then they are the only thing
301
+ // distinguishing one page from another — and Nuclei never names a parameter,
302
+ // so dropping them unconditionally would merge `/view?id` with `/view?page`.
303
+ const location = normaliseLocation(input.location);
304
+ const addressed = input.parameter === undefined ? location : stripQuery(location);
305
+ const material = [input.targetId, input.vulnKey, addressed, tail].join('|');
245
306
  return createHash('sha256').update(material, 'utf8').digest('hex');
246
307
  }
308
+ /** Everything before the `?` of an already-normalised location. */
309
+ function stripQuery(location) {
310
+ const at = location.indexOf('?');
311
+ return at === -1 ? location : location.slice(0, at);
312
+ }
247
313
  //# sourceMappingURL=fingerprint.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../src/fingerprint.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../src/fingerprint.ts"],"names":[],"mappings":"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"}
@@ -9,12 +9,15 @@ import type { ImportOptions } from './nuclei.js';
9
9
  * fingerprints distinctly per service.
10
10
  *
11
11
  * The port is also recorded on {@link Finding.port} (**B42**), which is a
12
- * record and nothing more. The location assembly and the fingerprint inputs are
13
- * deliberately unchanged: the fingerprint's last component is
14
- * `parameter ?? port ?? ''`, so a Nessus port is still counted twice — once
15
- * inside the location and once as that component. That double-count is
16
- * harmless and **must stay**, because removing it would move every existing
17
- * Nessus fingerprint and force a re-fingerprint migration.
12
+ * record and nothing more. **The double-count is gone in `fp_v2`** (6.9c): the
13
+ * fingerprint's last component was `parameter ?? port ?? ''`, so a Nessus port
14
+ * was counted twice — once inside the location and once as that component —
15
+ * and this comment said it had to stay because removing it would force a
16
+ * re-fingerprint migration. 6.9b built that migration, so it went. The tail is
17
+ * now `parameter ?? ''`, and the port is carried by the location alone, which
18
+ * `normaliseLocation` canonicalises: `app.example.com:443` and
19
+ * `https://app.example.com/` are one endpoint (B102), and a non-default port
20
+ * stays in the location where it belongs.
18
21
  *
19
22
  * Severity comes from the CVSS v3 base score where Nessus supplies one, and from
20
23
  * its own numeric rating otherwise.
@@ -1 +1 @@
1
- {"version":3,"file":"nessus.d.ts","sourceRoot":"","sources":["../../src/import/nessus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAK7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAgBjD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,EAAE,CAuF3E"}
1
+ {"version":3,"file":"nessus.d.ts","sourceRoot":"","sources":["../../src/import/nessus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAK7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAgBjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,EAAE,CAuF3E"}
@@ -23,12 +23,15 @@ const NESSUS_SEVERITY = Object.freeze({
23
23
  * fingerprints distinctly per service.
24
24
  *
25
25
  * The port is also recorded on {@link Finding.port} (**B42**), which is a
26
- * record and nothing more. The location assembly and the fingerprint inputs are
27
- * deliberately unchanged: the fingerprint's last component is
28
- * `parameter ?? port ?? ''`, so a Nessus port is still counted twice — once
29
- * inside the location and once as that component. That double-count is
30
- * harmless and **must stay**, because removing it would move every existing
31
- * Nessus fingerprint and force a re-fingerprint migration.
26
+ * record and nothing more. **The double-count is gone in `fp_v2`** (6.9c): the
27
+ * fingerprint's last component was `parameter ?? port ?? ''`, so a Nessus port
28
+ * was counted twice — once inside the location and once as that component —
29
+ * and this comment said it had to stay because removing it would force a
30
+ * re-fingerprint migration. 6.9b built that migration, so it went. The tail is
31
+ * now `parameter ?? ''`, and the port is carried by the location alone, which
32
+ * `normaliseLocation` canonicalises: `app.example.com:443` and
33
+ * `https://app.example.com/` are one endpoint (B102), and a non-default port
34
+ * stays in the location where it belongs.
32
35
  *
33
36
  * Severity comes from the CVSS v3 base score where Nessus supplies one, and from
34
37
  * its own numeric rating otherwise.
@@ -1 +1 @@
1
- {"version":3,"file":"nessus.js","sourceRoot":"","sources":["../../src/import/nessus.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"nessus.js","sourceRoot":"","sources":["../../src/import/nessus.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -15,6 +15,9 @@
15
15
  */
16
16
  export type { Finding } from './finding.js';
17
17
  export type { FingerprintInput, VulnKeyInput } from './fingerprint.js';
18
+ export type { FingerprintAlgorithm, IssuePlan, IssueWithEvidence, RefingerprintOutcome, RefingerprintPlan, } from './refingerprint.js';
19
+ export { currentAlgorithm, planRefingerprint } from './refingerprint.js';
20
+ export { exposureOf } from './reconcile.js';
18
21
  export { FINGERPRINT_VERSION, PATH_PLACEHOLDER, VULN_KEY_MAP, fingerprint, normaliseLocation, vulnKey, } from './fingerprint.js';
19
22
  export type { IgnoreReason, IgnoreScope, Issue, IssueEvent, IssueEventType, IssueOrigin, IssueStatus, } from './issue.js';
20
23
  export { coversLocation } from './coverage.js';
@@ -27,13 +30,13 @@ export type { GenericDocument, GenericFinding } from './import/generic.js';
27
30
  export { importGeneric } from './import/generic.js';
28
31
  export type { BuildSnapshotInput } from './snapshot-builder.js';
29
32
  export { buildSnapshot, parseSnapshot } from './snapshot-builder.js';
30
- export type { ReportKind, ReportModel, ReportOptions, ReportSection, RetestEntry, RetestOutcome, RetestVerdict, TestingBasis, } from './report/model.js';
31
- export { buildReportModel } from './report/model.js';
33
+ export type { Branding, EvidenceVerbosity, OmittedIssues, ReportKind, ReportModel, ReportOptions, ReportSection, RetestEntry, RetestOutcome, RetestVerdict, TestingBasis, } from './report/model.js';
34
+ export { buildReportModel, VERDICT_LABELS } from './report/model.js';
32
35
  export { renderMarkdown } from './report/markdown.js';
33
36
  export { renderHtml } from './report/html.js';
34
37
  export type { JsonReport } from './report/json.js';
35
38
  export { renderJson } from './report/json.js';
36
- export type { ReconcileInput, ReconcileResult } from './reconcile.js';
39
+ export type { ReconcileInput, ReconcileResult, SuppressionDecision } from './reconcile.js';
37
40
  export { reconcile } from './reconcile.js';
38
41
  export type { Coverage, Run, RunKind, RunStatus, RunSummary, RunTrigger, SeverityCounts, } from './run.js';
39
42
  export type { IssueChange, Snapshot, SnapshotIssue, SuppressedIssue, Target } from './snapshot.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,OAAO,GACR,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,YAAY,EACZ,WAAW,EACX,KAAK,EACL,UAAU,EACV,cAAc,EACd,WAAW,EACX,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACrE,YAAY,EACV,UAAU,EACV,WAAW,EACX,aAAa,EACb,aAAa,EACb,WAAW,EACX,aAAa,EACb,aAAa,EACb,YAAY,GACb,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,YAAY,EACV,QAAQ,EACR,GAAG,EACH,OAAO,EACP,SAAS,EACT,UAAU,EACV,UAAU,EACV,cAAc,GACf,MAAM,UAAU,CAAC;AAClB,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACnG,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACpF,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,0BAA0B,EAC1B,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,QAAQ,EACR,SAAS,GACV,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACvE,YAAY,EACV,oBAAoB,EACpB,SAAS,EACT,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,OAAO,GACR,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,YAAY,EACZ,WAAW,EACX,KAAK,EACL,UAAU,EACV,cAAc,EACd,WAAW,EACX,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACrE,YAAY,EACV,QAAQ,EACR,iBAAiB,EACjB,aAAa,EACb,UAAU,EACV,WAAW,EACX,aAAa,EACb,aAAa,EACb,WAAW,EACX,aAAa,EACb,aAAa,EACb,YAAY,GACb,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC3F,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,YAAY,EACV,QAAQ,EACR,GAAG,EACH,OAAO,EACP,SAAS,EACT,UAAU,EACV,UAAU,EACV,cAAc,GACf,MAAM,UAAU,CAAC;AAClB,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACnG,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACpF,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,0BAA0B,EAC1B,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,QAAQ,EACR,SAAS,GACV,MAAM,eAAe,CAAC"}
package/dist/index.js CHANGED
@@ -13,6 +13,8 @@
13
13
  *
14
14
  * @packageDocumentation
15
15
  */
16
+ export { currentAlgorithm, planRefingerprint } from './refingerprint.js';
17
+ export { exposureOf } from './reconcile.js';
16
18
  export { FINGERPRINT_VERSION, PATH_PLACEHOLDER, VULN_KEY_MAP, fingerprint, normaliseLocation, vulnKey, } from './fingerprint.js';
17
19
  export { coversLocation } from './coverage.js';
18
20
  export { importNuclei } from './import/nuclei.js';
@@ -21,7 +23,7 @@ export { importBurp } from './import/burp.js';
21
23
  export { importNessus } from './import/nessus.js';
22
24
  export { importGeneric } from './import/generic.js';
23
25
  export { buildSnapshot, parseSnapshot } from './snapshot-builder.js';
24
- export { buildReportModel } from './report/model.js';
26
+ export { buildReportModel, VERDICT_LABELS } from './report/model.js';
25
27
  export { renderMarkdown } from './report/markdown.js';
26
28
  export { renderHtml } from './report/html.js';
27
29
  export { renderJson } from './report/json.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,OAAO,GACR,MAAM,kBAAkB,CAAC;AAU1B,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAWrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAY3C,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,0BAA0B,EAC1B,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,QAAQ,EACR,SAAS,GACV,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAWH,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,OAAO,GACR,MAAM,kBAAkB,CAAC;AAU1B,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAcrE,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAY3C,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,0BAA0B,EAC1B,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,QAAQ,EACR,SAAS,GACV,MAAM,eAAe,CAAC"}
package/dist/issue.d.ts CHANGED
@@ -168,7 +168,7 @@ export interface Issue {
168
168
  * request time: "issues resolved this quarter" and "regressions caught" are
169
169
  * both counts over this log.
170
170
  */
171
- export type IssueEventType = 'created' | 'seen' | 'severity_detected_changed' | 'severity_overridden' | 'resolved' | 'reopened' | 'ignored' | 'unignored' | 'commented' | 'assigned' | 'merged' | 'exported';
171
+ export type IssueEventType = 'created' | 'seen' | 'severity_detected_changed' | 'severity_overridden' | 'resolved' | 'reopened' | 'ignored' | 'unignored' | 'commented' | 'assigned' | 'merged' | 'retitled' | 'exported';
172
172
  /**
173
173
  * An append-only record of a single change to an issue.
174
174
  *
@@ -1 +1 @@
1
- {"version":3,"file":"issue.d.ts","sourceRoot":"","sources":["../src/issue.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"issue.d.ts","sourceRoot":"","sources":["../src/issue.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import type { Finding } from './finding.js';
2
- import type { Issue, IssueEvent } from './issue.js';
2
+ import type { IgnoreReason, IgnoreScope, Issue, IssueEvent } from './issue.js';
3
3
  import type { Run, RunSummary } from './run.js';
4
4
  import { type SlaPolicy } from './severity.js';
5
5
  /**
@@ -55,6 +55,51 @@ export interface ReconcileInput {
55
55
  readonly autoResolveThreshold?: number;
56
56
  /** How long the run took, for the summary. */
57
57
  readonly durationMs?: number;
58
+ /**
59
+ * Consulted for each issue this run would newly open, to suppress it at
60
+ * birth — a standing rule rather than a decision about one issue.
61
+ *
62
+ * **It has to live here, and B89 records why the obvious alternative fails.**
63
+ * `reconcile()` computes the run summary, so an issue it opens is counted
64
+ * `new`. A caller that suppressed that issue after the fact would produce a
65
+ * report whose opening line said `new` while its own appendix said
66
+ * `suppressed`, about the same issue, in the same document. Filtering the
67
+ * findings before reconciling is no better: the issue then vanishes from the
68
+ * summary entirely rather than being suppressed, and invariant 7 says a
69
+ * suppressed issue is never absent from the appendix.
70
+ *
71
+ * Return `undefined` to open the issue normally. The suppressed issue is
72
+ * counted `ignored` in the same pass that counts everything else, which the
73
+ * summary already does correctly because it tests `status` before it tests
74
+ * whether the run created the issue.
75
+ *
76
+ * **Consulted only for new issues**, never for one that already exists: an
77
+ * issue a person has looked at is theirs, and a rule written afterwards does
78
+ * not get to reach back and hide it.
79
+ */
80
+ readonly suppress?: (issue: Issue) => SuppressionDecision | undefined;
81
+ }
82
+ /**
83
+ * Why a standing rule suppressed an issue at the moment it was opened.
84
+ *
85
+ * @see {@link ReconcileInput.suppress}
86
+ */
87
+ export interface SuppressionDecision {
88
+ /** Which of the domain's ignore reasons applies. */
89
+ readonly reason: IgnoreReason;
90
+ /** The justification an auditor reads in the suppressed appendix. */
91
+ readonly comment?: string;
92
+ /** How widely the suppression applies. */
93
+ readonly scope?: IgnoreScope;
94
+ /**
95
+ * Who accepted the risk. Defaults to {@link ReconcileInput.actor}.
96
+ *
97
+ * Worth passing. The appendix is an accepted-risk register, and a register
98
+ * whose every row says `reconciler` answers "who accepted this?" with "the
99
+ * clock did" — which `00-DOMAIN.md` §3 is explicit is not an identity. The
100
+ * rule that matched has an author; this is where to name them.
101
+ */
102
+ readonly by?: string;
58
103
  }
59
104
  /**
60
105
  * What reconciliation decided.
@@ -72,6 +117,31 @@ export interface ReconcileResult {
72
117
  /** What the run did, in the terms a report opens with. */
73
118
  readonly summary: RunSummary;
74
119
  }
120
+ /**
121
+ * How much a single issue contributes to an exposure score.
122
+ *
123
+ * **Severity times age in days, capped at ninety.** The cap is the load-bearing
124
+ * part: without it a two-year-old advisory eventually outweighs a critical
125
+ * found this morning, and the number stops being about risk and starts being
126
+ * about how long you have had the account. Ninety days is where an unfixed
127
+ * issue stops getting worse and simply *is* bad.
128
+ *
129
+ * **Only `open` and `regressed` count.** A resolved issue is not exposure, and
130
+ * an ignored one is excluded from exposure exactly as it is excluded from
131
+ * every count but its own (invariant 7) — suppressing an issue is a statement
132
+ * that it is not currently risk, and a score that disagreed with that would
133
+ * make the suppression pointless.
134
+ *
135
+ * Exported because `reconcile()` is not the only thing that needs it: the
136
+ * nightly rollup scores a whole organisation across every target, and two
137
+ * implementations of this would be two definitions of exposure.
138
+ *
139
+ * @param issue - The issue to score.
140
+ * @param now - When the score is being taken. An argument, so the same issue
141
+ * and the same clock always give the same number.
142
+ * @returns The contribution, which is zero for anything not currently open.
143
+ */
144
+ export declare function exposureOf(issue: Pick<Issue, 'status' | 'effectiveSeverity' | 'firstSeen'>, now: Date): number;
75
145
  /**
76
146
  * Turns a run's findings into issue state.
77
147
  *
@@ -1 +1 @@
1
- {"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../src/reconcile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,KAAK,EAAE,GAAG,EAAW,UAAU,EAAkB,MAAM,UAAU,CAAC;AACzE,OAAO,EAML,KAAK,SAAS,EACf,MAAM,eAAe,CAAC;AAGvB;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;;OAMG;IACH,QAAQ,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;IAElC,sCAAsC;IACtC,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;IAEtC,4EAA4E;IAC5E,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAElB,iDAAiD;IACjD,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC;IAEnB;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,MAAM,CAAC;IAE7B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAExB,uDAAuD;IACvD,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAE/B;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAEvC,8CAA8C;IAC9C,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,QAAQ,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;IAElC,iDAAiD;IACjD,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC;IAEvC,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;CAC9B;AAkGD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,eAAe,CA4OhE"}
1
+ {"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../src/reconcile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC/E,OAAO,KAAK,EAAE,GAAG,EAAW,UAAU,EAAkB,MAAM,UAAU,CAAC;AACzE,OAAO,EAML,KAAK,SAAS,EACf,MAAM,eAAe,CAAC;AAGvB;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;;OAMG;IACH,QAAQ,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;IAElC,sCAAsC;IACtC,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;IAEtC,4EAA4E;IAC5E,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAElB,iDAAiD;IACjD,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC;IAEnB;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,MAAM,CAAC;IAE7B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAExB,uDAAuD;IACvD,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAE/B;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAEvC,8CAA8C;IAC9C,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAE7B;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,mBAAmB,GAAG,SAAS,CAAC;CACvE;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,oDAAoD;IACpD,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAE9B,qEAAqE;IACrE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAE1B,0CAA0C;IAC1C,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC;IAE7B;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,QAAQ,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;IAElC,iDAAiD;IACjD,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC;IAEvC,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;CAC9B;AAsDD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,GAAG,mBAAmB,GAAG,WAAW,CAAC,EAChE,GAAG,EAAE,IAAI,GACR,MAAM,CAKR;AA8CD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,eAAe,CA4QhE"}
package/dist/reconcile.js CHANGED
@@ -46,6 +46,35 @@ function defaultThreshold(kind) {
46
46
  // for reasons that say nothing about the issue.
47
47
  return kind === 'upload' ? 1 : 2;
48
48
  }
49
+ /**
50
+ * How much a single issue contributes to an exposure score.
51
+ *
52
+ * **Severity times age in days, capped at ninety.** The cap is the load-bearing
53
+ * part: without it a two-year-old advisory eventually outweighs a critical
54
+ * found this morning, and the number stops being about risk and starts being
55
+ * about how long you have had the account. Ninety days is where an unfixed
56
+ * issue stops getting worse and simply *is* bad.
57
+ *
58
+ * **Only `open` and `regressed` count.** A resolved issue is not exposure, and
59
+ * an ignored one is excluded from exposure exactly as it is excluded from
60
+ * every count but its own (invariant 7) — suppressing an issue is a statement
61
+ * that it is not currently risk, and a score that disagreed with that would
62
+ * make the suppression pointless.
63
+ *
64
+ * Exported because `reconcile()` is not the only thing that needs it: the
65
+ * nightly rollup scores a whole organisation across every target, and two
66
+ * implementations of this would be two definitions of exposure.
67
+ *
68
+ * @param issue - The issue to score.
69
+ * @param now - When the score is being taken. An argument, so the same issue
70
+ * and the same clock always give the same number.
71
+ * @returns The contribution, which is zero for anything not currently open.
72
+ */
73
+ export function exposureOf(issue, now) {
74
+ if (issue.status !== 'open' && issue.status !== 'regressed')
75
+ return 0;
76
+ return (SEVERITY_WEIGHTS[issue.effectiveSeverity] * Math.min(daysBetween(issue.firstSeen, now), 90));
77
+ }
49
78
  /** An all-zero count, so a report never has to decide what a missing key means. */
50
79
  function emptyCounts() {
51
80
  return Object.fromEntries(SEVERITY_ORDER.map((s) => [s, 0]));
@@ -177,8 +206,41 @@ export function reconcile(input) {
177
206
  origin: run.kind,
178
207
  slaDueAt: slaDueAt(worst.detectedSeverity, now, slaPolicy),
179
208
  };
180
- updated.set(key, issue);
209
+ const decision = input.suppress?.(issue);
210
+ if (decision === undefined) {
211
+ updated.set(key, issue);
212
+ emit(id, 'created', { findingIds, severity: worst.detectedSeverity });
213
+ continue;
214
+ }
215
+ // Both events, in order. The issue was opened and then suppressed; a
216
+ // history that recorded only the suppression would have an issue whose
217
+ // first event is `ignored`, and invariant 2 wants every state change
218
+ // accounted for rather than the net result.
219
+ //
220
+ // `severityAtIgnore` is set deliberately, which is what makes a rule
221
+ // liftable: the existing branch above un-ignores an issue whose detected
222
+ // severity rises past what was accepted, and a standing rule should not
223
+ // be more permanent than a person's own decision. Accepting the risk of
224
+ // a medium is not accepting the risk of a critical, however the
225
+ // acceptance was expressed. **A merge survivor is the deliberate
226
+ // exception and omits it** (P6, B98) — that is a statement about
227
+ // identity rather than risk, and it has to survive a severity rise.
228
+ const suppressed = {
229
+ ...issue,
230
+ status: 'ignored',
231
+ ignoreReason: decision.reason,
232
+ ...(decision.comment === undefined ? {} : { ignoreComment: decision.comment }),
233
+ ...(decision.scope === undefined ? {} : { ignoreScope: decision.scope }),
234
+ ignoredBy: decision.by ?? actor,
235
+ severityAtIgnore: worst.detectedSeverity,
236
+ };
237
+ updated.set(key, suppressed);
181
238
  emit(id, 'created', { findingIds, severity: worst.detectedSeverity });
239
+ emit(id, 'ignored', {
240
+ reason: decision.reason,
241
+ ...(decision.comment === undefined ? {} : { comment: decision.comment }),
242
+ bornSuppressed: true,
243
+ });
182
244
  continue;
183
245
  }
184
246
  // One `seen` per issue per run, not one per finding. `issue_events` is what
@@ -326,9 +388,7 @@ export function reconcile(input) {
326
388
  counts.regressed[severity]++;
327
389
  else if (updated.has(key))
328
390
  counts.stillOpen[severity]++;
329
- if (issue.status === 'open' || issue.status === 'regressed') {
330
- exposureScore += SEVERITY_WEIGHTS[severity] * Math.min(daysBetween(issue.firstSeen, now), 90);
331
- }
391
+ exposureScore += exposureOf(issue, now);
332
392
  }
333
393
  const summary = {
334
394
  runId: run.id,