@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.
- package/README.md +2 -1
- package/dist/finding.d.ts +9 -8
- package/dist/finding.d.ts.map +1 -1
- package/dist/fingerprint.d.ts +12 -5
- package/dist/fingerprint.d.ts.map +1 -1
- package/dist/fingerprint.js +74 -8
- package/dist/fingerprint.js.map +1 -1
- package/dist/import/nessus.d.ts +9 -6
- package/dist/import/nessus.d.ts.map +1 -1
- package/dist/import/nessus.js +9 -6
- package/dist/import/nessus.js.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/issue.d.ts +1 -1
- package/dist/issue.d.ts.map +1 -1
- package/dist/reconcile.d.ts +71 -1
- package/dist/reconcile.d.ts.map +1 -1
- package/dist/reconcile.js +64 -4
- package/dist/reconcile.js.map +1 -1
- package/dist/refingerprint.d.ts +116 -0
- package/dist/refingerprint.d.ts.map +1 -0
- package/dist/refingerprint.js +190 -0
- package/dist/refingerprint.js.map +1 -0
- package/dist/report/anchors.d.ts +39 -0
- package/dist/report/anchors.d.ts.map +1 -0
- package/dist/report/anchors.js +73 -0
- package/dist/report/anchors.js.map +1 -0
- package/dist/report/html.d.ts.map +1 -1
- package/dist/report/html.js +126 -22
- package/dist/report/html.js.map +1 -1
- package/dist/report/markdown.d.ts.map +1 -1
- package/dist/report/markdown.js +112 -26
- package/dist/report/markdown.js.map +1 -1
- package/dist/report/model.d.ts +227 -1
- package/dist/report/model.d.ts.map +1 -1
- package/dist/report/model.js +87 -8
- package/dist/report/model.js.map +1 -1
- package/package.json +1 -1
- package/src/finding.ts +9 -8
- package/src/fingerprint.ts +76 -10
- package/src/import/nessus.ts +9 -6
- package/src/index.ts +14 -2
- package/src/issue.ts +1 -0
- package/src/reconcile.ts +121 -5
- package/src/refingerprint.ts +282 -0
- package/src/report/anchors.ts +96 -0
- package/src/report/html.ts +146 -26
- package/src/report/markdown.ts +125 -25
- 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 `
|
|
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
|
|
80
|
-
*
|
|
81
|
-
*
|
|
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
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
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. */
|
package/dist/finding.d.ts.map
CHANGED
|
@@ -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
|
|
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"}
|
package/dist/fingerprint.d.ts
CHANGED
|
@@ -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 = "
|
|
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
|
-
*
|
|
47
|
-
* `
|
|
48
|
-
*
|
|
49
|
-
*
|
|
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
|
|
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"}
|
package/dist/fingerprint.js
CHANGED
|
@@ -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 = '
|
|
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
|
-
*
|
|
79
|
-
* `
|
|
80
|
-
*
|
|
81
|
-
*
|
|
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
|
-
|
|
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
|
-
|
|
244
|
-
|
|
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
|
package/dist/fingerprint.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../src/fingerprint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,OAAO,CAAC;AAE3C,+EAA+E;AAC/E,MAAM,eAAe,GAAG,QAAQ,CAAC;AAEjC,sEAAsE;AACtE,MAAM,YAAY,GAAG,kEAAkE,CAAC;AAExF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAEvC;;;;;;;;;GASG;AACH,SAAS,UAAU,CAAC,KAAa;IAC/B,IAAI,CAAC;QACH,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,eAAe,CAAC,OAAe;IACtC,IAAI,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,gBAAgB,CAAC;IACzF,OAAO,OAAO,CAAC;AACjB,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../src/fingerprint.ts"],"names":[],"mappings":"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"}
|
package/dist/import/nessus.d.ts
CHANGED
|
@@ -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
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
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
|
|
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"}
|
package/dist/import/nessus.js
CHANGED
|
@@ -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
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
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":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC9E,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAGxD;;;;;GAKG;AACH,MAAM,eAAe,GAAuC,MAAM,CAAC,MAAM,CAAC;IACxE,GAAG,EAAE,UAAU;IACf,GAAG,EAAE,MAAM;IACX,GAAG,EAAE,QAAQ;IACb,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,UAAU;CAChB,CAAC,CAAC;AAEH
|
|
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';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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;
|
|
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;
|
|
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
|
*
|
package/dist/issue.d.ts.map
CHANGED
|
@@ -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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"}
|
package/dist/reconcile.d.ts
CHANGED
|
@@ -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
|
*
|
package/dist/reconcile.d.ts.map
CHANGED
|
@@ -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;
|
|
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
|
-
|
|
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
|
-
|
|
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,
|