edfcore 0.3.30 → 0.3.31
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 +26 -0
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/diagnostics/format.d.ts.map +1 -1
- package/dist/diagnostics/format.js +31 -4
- package/dist/diagnostics/format.js.map +1 -1
- package/package.json +1 -1
- package/src/constants.ts +1 -1
- package/src/diagnostics/format.ts +30 -3
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,32 @@ alone does not tell you whether you were affected.
|
|
|
6
6
|
edfcore is pre-1.0. Patch releases have carried behaviour changes where the old behaviour was a
|
|
7
7
|
defect; those are called out below.
|
|
8
8
|
|
|
9
|
+
## 0.3.31
|
|
10
|
+
|
|
11
|
+
**Two ways patient identification reached the output with `--patient` absent.** Both produced text
|
|
12
|
+
that LOOKED redacted — `raw:` and `actual:` said `[redacted]` — which is worse than an obvious leak,
|
|
13
|
+
because a reader has no reason to check.
|
|
14
|
+
|
|
15
|
+
- **A NUL-padded identification field was printed verbatim.** `redactDiagnostic` substituted
|
|
16
|
+
spellings derived from `raw`, including `raw.trim()`. Every identification diagnostic builds its
|
|
17
|
+
message from `trimEdfField(raw)`, and `trimEdfField` strips 0x20 **and 0x00** while
|
|
18
|
+
`String.prototype.trim` strips whitespace but not U+0000. On a field padded with NULs — which a
|
|
19
|
+
large share of real writers emit, and which `header/fields.ts` treats as normal — none of the
|
|
20
|
+
spellings matched. `edfcore header` printed the whole name and MRN; `edfcore validate` printed it
|
|
21
|
+
twice.
|
|
22
|
+
- **`DATE_IMPLAUSIBLE` printed the patient's date of birth.** It spells the date `2050-05-02` while
|
|
23
|
+
the file writes `02-MAY-2050`, so no spelling derived from `raw` could ever match it — and it
|
|
24
|
+
fires on a perfectly conformant identification field, with no NUL padding and no grammar
|
|
25
|
+
violation needed. `formatHeader`'s own comment names "a name and a birth date" as what the flag
|
|
26
|
+
exists to withhold.
|
|
27
|
+
- Both close at the substitution: the field's `trimEdfField` spelling and the diagnostic's own
|
|
28
|
+
`actual`, captured before `actual` is replaced, are now removed from the message too. `actual`
|
|
29
|
+
already carries whatever the message chose to print, whatever spelling that is.
|
|
30
|
+
- 0.2.26 established that withholding `header.patient` while the diagnostic below it spells the
|
|
31
|
+
same string out is not withholding it at all. These are the two spellings that fix could not
|
|
32
|
+
reach. The rule, the code, the byte offset and the recording's own start date are not patient
|
|
33
|
+
data and stay readable.
|
|
34
|
+
|
|
9
35
|
## 0.3.30
|
|
10
36
|
|
|
11
37
|
- **Fixed** `readEnvelopeAtResolution` crushing the tail of a run into one bucket whenever the
|
package/dist/constants.d.ts
CHANGED
|
@@ -109,5 +109,5 @@ export declare const SIGNAL_FIELD_BLOCK_OFFSETS: {
|
|
|
109
109
|
readonly reserved: 224;
|
|
110
110
|
};
|
|
111
111
|
/** Published package version. Kept in sync with package.json by a test. */
|
|
112
|
-
export declare const VERSION = "0.3.
|
|
112
|
+
export declare const VERSION = "0.3.31";
|
|
113
113
|
//# sourceMappingURL=constants.d.ts.map
|
package/dist/constants.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/diagnostics/format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/diagnostics/format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,aAAa,CAAC;AAE9D,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3C;AAgBD;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,SAAS,aAAa,EAAE,EACrC,OAAO,CAAC,EAAE,wBAAwB,GACjC,MAAM,CAkBR"}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* Output is deterministic and asserted as such: no locale-sensitive number or date formatting,
|
|
9
9
|
* no iteration over an unordered collection, and no ANSI escapes unless `color` is requested.
|
|
10
10
|
*/
|
|
11
|
+
import { trimEdfField } from '../bytes/latin1.js';
|
|
11
12
|
import { printable } from '../text/printable.js';
|
|
12
13
|
const INDENT = ' ';
|
|
13
14
|
/** A report is a summary, not a hex dump; longer runs are elided with a count. */
|
|
@@ -60,11 +61,37 @@ const REDACTED = '[redacted]';
|
|
|
60
61
|
function redactDiagnostic(diagnostic) {
|
|
61
62
|
const raw = diagnostic.raw;
|
|
62
63
|
let message = diagnostic.message;
|
|
64
|
+
const spellings = [];
|
|
63
65
|
if (raw !== undefined) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
/*
|
|
67
|
+
* `raw.trim()` is not the same as the field's trimmed value, and that gap was the leak.
|
|
68
|
+
* `trimEdfField` strips 0x20 AND 0x00; `String.prototype.trim` strips whitespace but not
|
|
69
|
+
* U+0000. Every identification diagnostic builds its message from `trimEdfField(raw)`, so on
|
|
70
|
+
* a field padded with NULs — which a large share of real writers emit, and which
|
|
71
|
+
* `header/fields.ts` treats as normal — none of the four spellings matched and the name went
|
|
72
|
+
* through verbatim while `raw:` and `actual:` said `[redacted]`. Output that LOOKS redacted is
|
|
73
|
+
* worse than an obvious leak (fixed in 0.3.31).
|
|
74
|
+
*/
|
|
75
|
+
spellings.push(JSON.stringify(raw), JSON.stringify(raw.trim()), raw, raw.trim());
|
|
76
|
+
const trimmed = trimEdfField(raw);
|
|
77
|
+
spellings.push(trimmed, JSON.stringify(trimmed));
|
|
78
|
+
}
|
|
79
|
+
/*
|
|
80
|
+
* And the diagnostic's own `actual`, computed BEFORE it is replaced below.
|
|
81
|
+
*
|
|
82
|
+
* A message does not have to spell the value the way the field does. `DATE_IMPLAUSIBLE` writes
|
|
83
|
+
* the patient's date of birth as `2050-05-02` while the file says `02-MAY-2050`, so no spelling
|
|
84
|
+
* derived from `raw` could ever match it — and that diagnostic fires on a perfectly conformant
|
|
85
|
+
* identification field, with no NUL padding and no grammar violation needed. `actual` already
|
|
86
|
+
* carries whatever the message chose to print, which is exactly what has to be substituted.
|
|
87
|
+
*/
|
|
88
|
+
if (diagnostic.actual !== undefined) {
|
|
89
|
+
const actual = String(diagnostic.actual);
|
|
90
|
+
spellings.push(actual, JSON.stringify(actual));
|
|
91
|
+
}
|
|
92
|
+
for (const spelling of spellings) {
|
|
93
|
+
if (spelling.length > 0)
|
|
94
|
+
message = message.split(spelling).join(REDACTED);
|
|
68
95
|
}
|
|
69
96
|
return {
|
|
70
97
|
...diagnostic,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/diagnostics/format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAuBjD,MAAM,MAAM,GAAG,IAAI,CAAC;AAEpB,kFAAkF;AAClF,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAE/B,MAAM,UAAU,GAAG,WAAW,CAAC;AAC/B,MAAM,QAAQ,GAAG,WAAW,CAAC;AAE7B,MAAM,eAAe,GAA0C;IAC7D,KAAK,EAAE,YAAY;IACnB,OAAO,EAAE,YAAY;IACrB,IAAI,EAAE,YAAY;CACnB,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,WAAqC,EACrC,OAAkC;IAElC,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,KAAK,IAAI,CAAC;IACtC,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,EAAE,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAClE,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,EAAE,YAAY,IAAI,EAAE,CAAC,CAAC;IAEpD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/B,MAAM,UAAU,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;QAClC,oFAAoF;QACpF,IAAI,UAAU,KAAK,SAAS;YAAE,SAAS;QACvC,gBAAgB,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IACrD,CAAC;IAED,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,GAAG,KAAK,CAAC;IAC1C,IAAI,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,MAAM,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;IAE7E,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,YAAY,CAAC,QAA4B,EAAE,KAAa;IAC/D,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAC;IACvE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,QAAQ,GAAG,YAAY,CAAC;AAE9B;;;;;;;;;;GAUG;AACH,SAAS,gBAAgB,CAAC,UAAyB;IACjD,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC;IAC3B,IAAI,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC;IACjC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/diagnostics/format.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/constants.ts
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* no iteration over an unordered collection, and no ANSI escapes unless `color` is requested.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
import { trimEdfField } from '../bytes/latin1.js';
|
|
12
13
|
import { printable } from '../text/printable.js';
|
|
13
14
|
import type { EdfDiagnostic, EdfSeverity } from '../types.js';
|
|
14
15
|
|
|
@@ -94,10 +95,36 @@ const REDACTED = '[redacted]';
|
|
|
94
95
|
function redactDiagnostic(diagnostic: EdfDiagnostic): EdfDiagnostic {
|
|
95
96
|
const raw = diagnostic.raw;
|
|
96
97
|
let message = diagnostic.message;
|
|
98
|
+
const spellings: string[] = [];
|
|
97
99
|
if (raw !== undefined) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
100
|
+
/*
|
|
101
|
+
* `raw.trim()` is not the same as the field's trimmed value, and that gap was the leak.
|
|
102
|
+
* `trimEdfField` strips 0x20 AND 0x00; `String.prototype.trim` strips whitespace but not
|
|
103
|
+
* U+0000. Every identification diagnostic builds its message from `trimEdfField(raw)`, so on
|
|
104
|
+
* a field padded with NULs — which a large share of real writers emit, and which
|
|
105
|
+
* `header/fields.ts` treats as normal — none of the four spellings matched and the name went
|
|
106
|
+
* through verbatim while `raw:` and `actual:` said `[redacted]`. Output that LOOKS redacted is
|
|
107
|
+
* worse than an obvious leak (fixed in 0.3.31).
|
|
108
|
+
*/
|
|
109
|
+
spellings.push(JSON.stringify(raw), JSON.stringify(raw.trim()), raw, raw.trim());
|
|
110
|
+
const trimmed = trimEdfField(raw);
|
|
111
|
+
spellings.push(trimmed, JSON.stringify(trimmed));
|
|
112
|
+
}
|
|
113
|
+
/*
|
|
114
|
+
* And the diagnostic's own `actual`, computed BEFORE it is replaced below.
|
|
115
|
+
*
|
|
116
|
+
* A message does not have to spell the value the way the field does. `DATE_IMPLAUSIBLE` writes
|
|
117
|
+
* the patient's date of birth as `2050-05-02` while the file says `02-MAY-2050`, so no spelling
|
|
118
|
+
* derived from `raw` could ever match it — and that diagnostic fires on a perfectly conformant
|
|
119
|
+
* identification field, with no NUL padding and no grammar violation needed. `actual` already
|
|
120
|
+
* carries whatever the message chose to print, which is exactly what has to be substituted.
|
|
121
|
+
*/
|
|
122
|
+
if (diagnostic.actual !== undefined) {
|
|
123
|
+
const actual = String(diagnostic.actual);
|
|
124
|
+
spellings.push(actual, JSON.stringify(actual));
|
|
125
|
+
}
|
|
126
|
+
for (const spelling of spellings) {
|
|
127
|
+
if (spelling.length > 0) message = message.split(spelling).join(REDACTED);
|
|
101
128
|
}
|
|
102
129
|
return {
|
|
103
130
|
...diagnostic,
|