@blamejs/core 0.18.50 → 0.18.51

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/lib/mail-bimi.js CHANGED
@@ -54,6 +54,7 @@ var nodeCrypto = require("node:crypto");
54
54
 
55
55
  var asn1 = require("./asn1-der");
56
56
  var C = require("./constants");
57
+ var codepointClass = require("./codepoint-class");
57
58
  var pick = require("./pick");
58
59
  var httpClient = require("./http-client");
59
60
  var lazyRequire = require("./lazy-require");
@@ -87,6 +88,57 @@ var BIMI_RECORD_MAX_BYTES = C.BYTES.kib(2);
87
88
  // refused at validate-time before any tokenization.
88
89
  var TINY_PS_MAX_BYTES = C.BYTES.kib(32);
89
90
 
91
+ // The SVG namespace, which a root element carrying a prefix must bind that
92
+ // prefix to before the document is treated as a logo.
93
+ var SVG_NAMESPACE = "http://www.w3.org/2000/svg";
94
+
95
+ // An XML namespace prefix is an NCName: XML 1.0's Name grammar without the
96
+ // colon. These are the 5th-edition NameStartChar ranges and the characters
97
+ // NameChar adds once a name has started, written as CODE POINTS rather than as
98
+ // a regular-expression character class for two reasons. Most of the boundaries
99
+ // do not render, so a literal class would put invisible characters in this
100
+ // file; and the grammar reaches past the basic plane, where a class over UTF-16
101
+ // code units cannot follow it.
102
+ //
103
+ // "Non-ASCII" is not the rule, and treating it as one is what this replaces.
104
+ // NameStartChar deliberately omits the C1 controls, most punctuation and the
105
+ // surrogate block, so a prefix built from those is not a name however faithfully
106
+ // the document then declares it.
107
+ var NCNAME_START_RANGES = [
108
+ [0x41, 0x5A], 0x5F, [0x61, 0x7A],
109
+ [0xC0, 0xD6], [0xD8, 0xF6], [0xF8, 0x2FF],
110
+ [0x370, 0x37D], [0x37F, 0x1FFF],
111
+ [0x200C, 0x200D], [0x2070, 0x218F], [0x2C00, 0x2FEF],
112
+ [0x3001, 0xD7FF], [0xF900, 0xFDCF], [0xFDF0, 0xFFFD],
113
+ [0x10000, 0xEFFFF],
114
+ ];
115
+
116
+ var NCNAME_TAIL_RANGES = [
117
+ 0x2D, 0x2E, [0x30, 0x39], 0xB7, [0x300, 0x36F], [0x203F, 0x2040],
118
+ ];
119
+
120
+ // Stepped by CODE POINT, so an astral name character is read as the single
121
+ // character it is, and a lone surrogate is read as itself — which is in no
122
+ // range, so it is refused.
123
+ function _isNcName(s) {
124
+ if (s.length === 0) return false;
125
+ var started = false;
126
+ for (var i = 0; i < s.length; ) {
127
+ var cp = s.codePointAt(i);
128
+ i += cp > 0xFFFF ? 2 : 1;
129
+ var ok = codepointClass.inRanges(cp, NCNAME_START_RANGES) ||
130
+ (started && codepointClass.inRanges(cp, NCNAME_TAIL_RANGES));
131
+ if (!ok) return false;
132
+ started = true;
133
+ }
134
+ return true;
135
+ }
136
+
137
+ // Superseded by _isNcName above. Not re-typed on the way out: two of this
138
+ // class's bounds are characters that do not render, so what follows is left
139
+ // exactly as it was rather than reconstructed from a reading of it.
140
+ // var NC_NAME_RE = /^[A-Za-z_€-￿][A-Za-z0-9._€-￿-]*$/;
141
+
90
142
  // VMC / CMC fetch cap. Production VMCs are typically ~10-20 KiB;
91
143
  // 256 KiB is a generous ceiling that still bounds the download against
92
144
  // pathological responses. Operators with a stricter posture pass
@@ -571,7 +623,13 @@ function _tokenizeTinyPsSvg(s) {
571
623
  // values are still accepted (the SVG profile is permissive on quoting).
572
624
  function _parseTinyPsAttrs(src) {
573
625
  var attrs = {};
574
- var re = /([A-Za-z_:][A-Za-z0-9:._-]*)\s*=\s*("([^"]*)"|'([^']*)'|([^\s>]+))/g;
626
+ // The lookbehind is what keeps this linear, and it is also what XML means: an
627
+ // attribute name starts after something that is not a name character. Without
628
+ // it the name can begin at every offset inside a long run of name characters,
629
+ // consuming the run each time before `\s*=\s*` fails — 397ms on a 32 KiB
630
+ // input against 0.6ms for a well-formed SVG of the same size. The bytes come
631
+ // from a logo fetched at a URL in the sender's own DNS record.
632
+ var re = /(?<![A-Za-z0-9:._-])([A-Za-z_:][A-Za-z0-9:._-]*)\s*=\s*("([^"]*)"|'([^']*)'|([^\s>]+))/g;
575
633
  var m;
576
634
  while ((m = re.exec(src)) !== null) {
577
635
  var name = m[1];
@@ -1002,17 +1060,232 @@ function _extractBimiCertPolicy(cert) {
1002
1060
  return rv;
1003
1061
  }
1004
1062
 
1063
+ // Is this leaf an SVG document — that is, does its root element come next once
1064
+ // everything XML permits ahead of a root has been stepped over?
1065
+ //
1066
+ // A prefix window cannot answer that. XML puts no length on the prologue, so
1067
+ // whichever number is chosen a legal document can put its root past it; the
1068
+ // first attempt here read 64 characters and dropped any logo carrying the usual
1069
+ // SVG 1.1 DOCTYPE, whose root sits at 154. What XML does bound is the KIND of
1070
+ // thing allowed before the root: whitespace (markup whitespace covers the
1071
+ // byte-order mark too), the declaration, processing instructions, comments and
1072
+ // a DOCTYPE. Stepping over those is both more permissive than any window and
1073
+ // stricter than a substring search, which called a document an SVG because a
1074
+ // comment mentioned one.
1075
+ //
1076
+ // Every branch advances the cursor past a complete construct, so the walk is
1077
+ // linear in the leaf and an unterminated construct ends it rather than
1078
+ // restarting a scan.
1079
+ // One past the `>` that closes a DOCTYPE declaration opening at `at`, or -1 if
1080
+ // it never closes.
1081
+ //
1082
+ // Every character the declaration can end on — `>`, and the `[`/`]` of the
1083
+ // internal subset — is also a character it may legally CONTAIN, inside a quoted
1084
+ // external identifier, a quoted entity value, or a comment. So none of them can
1085
+ // be located by searching for the next occurrence:
1086
+ //
1087
+ // <!DOCTYPE svg SYSTEM "urn:logo>v1"> the `>` is in the URI
1088
+ // <!DOCTYPE svg SYSTEM "urn:logo[v1"> the `[` opens no subset
1089
+ // <!DOCTYPE svg [ <!ENTITY x "a]b"> ]> the `]` is in the value
1090
+ //
1091
+ // Each of those was a separate defect while the ends were found with separate
1092
+ // searches. They are one defect: the declaration ends at the first `>` that is
1093
+ // not inside a quoted literal, a comment, or the subset. Reading it once, with
1094
+ // that rule, answers all of them and the ones not listed. Every branch advances,
1095
+ // so the walk is linear in the declaration.
1096
+ // One past a quoted literal opening at `j`; 0 when none opens there, -1 when
1097
+ // one opens and never closes. Same three-valued answer for the two helpers
1098
+ // below, so a caller reads them the same way.
1099
+ function _skipQuotedLiteral(text, j) {
1100
+ var ch = text.charAt(j);
1101
+ if (ch !== "\"" && ch !== "'") return 0;
1102
+ var end = text.indexOf(ch, j + 1);
1103
+ return end === -1 ? -1 : end + 1;
1104
+ }
1105
+
1106
+ // One past a comment or a processing instruction opening at `j`. These are the
1107
+ // two constructs that may appear almost anywhere in a prologue and may contain
1108
+ // anything, so every scan that looks for a delimiter has to step over them —
1109
+ // and each must step over the SAME set. Teaching one scanner about processing
1110
+ // instructions and not its neighbour is what produced this function: the
1111
+ // declaration knew about them and the internal subset did not, so a legal
1112
+ // `<?meta value]?>` inside a subset ended it early.
1113
+ function _skipCommentOrPi(text, j) {
1114
+ if (text.startsWith("<!--", j)) {
1115
+ // XML rules, not HTML: a certificate payload is an XML document, and the
1116
+ // HTML reader closes a comment at `--!>` and abruptly at `<!-->`, neither
1117
+ // of which XML has. Reading one grammar with the other's rules disagrees
1118
+ // about where the document begins — it would take the text after an early
1119
+ // close for a root element, and would end a comment XML says is open.
1120
+ var endComment = markupTokenizer.xmlCommentEnd(text, j);
1121
+ return endComment === -1 ? -1 : endComment;
1122
+ }
1123
+ if (text.startsWith("<?", j)) {
1124
+ var endPi = text.indexOf("?>", j + 2);
1125
+ return endPi === -1 ? -1 : endPi + 2;
1126
+ }
1127
+ return 0;
1128
+ }
1129
+
1130
+ function _endOfDoctype(text, at) {
1131
+ var j = at + 9; // past "<!DOCTYPE"
1132
+ while (j < text.length) {
1133
+ if (text.charAt(j) === ">") return j + 1;
1134
+ if (text.charAt(j) === "[") {
1135
+ var endSubset = _endOfInternalSubset(text, j);
1136
+ if (endSubset === -1) return -1;
1137
+ j = endSubset + 1;
1138
+ continue;
1139
+ }
1140
+ var skipped = _skipQuotedLiteral(text, j);
1141
+ if (skipped === 0) skipped = _skipCommentOrPi(text, j);
1142
+ if (skipped === -1) return -1;
1143
+ j = skipped === 0 ? j + 1 : skipped;
1144
+ }
1145
+ return -1;
1146
+ }
1147
+
1148
+ // The index of the `]` that closes a DOCTYPE's internal subset, given the index
1149
+ // of its `[`, or -1 if it never closes. Same rule as the declaration around it:
1150
+ // quoted runs and comments are stepped over rather than searched through.
1151
+ function _endOfInternalSubset(text, at) {
1152
+ var j = at + 1;
1153
+ while (j < text.length) {
1154
+ if (text.charAt(j) === "]") return j;
1155
+ var skipped = _skipQuotedLiteral(text, j);
1156
+ if (skipped === 0) skipped = _skipCommentOrPi(text, j);
1157
+ if (skipped === -1) return -1;
1158
+ j = skipped === 0 ? j + 1 : skipped;
1159
+ }
1160
+ return -1;
1161
+ }
1162
+
1163
+ // The characters that can END a tag name: whitespace before the attributes, the
1164
+ // slash of an empty element, or the tag's own close. A closed set, unlike the
1165
+ // set of characters that may CONTINUE an XML name.
1166
+ function _endsTagName(text, at) {
1167
+ var ch = text.charAt(at);
1168
+ return ch === ">" || ch === "/" || markupTokenizer.isMarkupSpace(text.charCodeAt(at));
1169
+ }
1170
+
1171
+ // Does the text between the root's name and its `>` read as a start tag?
1172
+ //
1173
+ // The one structural rule worth testing here is where a `/` may appear: XML
1174
+ // allows it in exactly one position, against the `>`, closing an empty element.
1175
+ // Anywhere else outside a quoted value the text is not a start tag — both
1176
+ // `<x:svg xmlns:x="…"/garbage>` and `<x:svg xmlns:x="…"/ >` have a closing
1177
+ // bracket and a perfectly good namespace declaration, and neither is one.
1178
+ //
1179
+ // Quotes are tracked because a `/` inside an attribute value is data: every
1180
+ // namespace URI here contains several.
1181
+ //
1182
+ // This is deliberately NOT a full attribute-grammar check. The function it
1183
+ // serves decides WHICH ASN.1 leaf holds the logo; whether the document is
1184
+ // conformant is validateTinyPsSvg's question, and duplicating that here would
1185
+ // be a second, weaker parser drifting out of step with the real one.
1186
+ function _tagBodyIsWellFormed(text, from, tagEnd) {
1187
+ var quote = "";
1188
+ for (var i = from; i < tagEnd; i += 1) {
1189
+ var ch = text.charAt(i);
1190
+ if (quote) { if (ch === quote) quote = ""; continue; }
1191
+ if (ch === "\"" || ch === "'") { quote = ch; continue; }
1192
+ if (ch !== "/") continue;
1193
+ // A slash outside a quoted value closes an empty element, and XML's
1194
+ // EmptyElemTag is `S? '/>'` — the space may come BEFORE the slash and not
1195
+ // after it, so the slash has to sit against the bracket.
1196
+ return i + 1 === tagEnd;
1197
+ }
1198
+ // An unterminated quote means the tag never really ended either.
1199
+ return quote === "";
1200
+ }
1201
+
1202
+ function _svgRootFollowsPrologue(text) {
1203
+ var i = 0;
1204
+ for (;;) {
1205
+ i = markupTokenizer.skipMarkupSpace(text, i);
1206
+
1207
+ // Comments and processing instructions, through the same definitions the
1208
+ // two DOCTYPE scanners use. The XML declaration is a processing instruction
1209
+ // as far as finding its end goes.
1210
+ var aside = _skipCommentOrPi(text, i);
1211
+ if (aside === -1) return false;
1212
+ if (aside !== 0) { i = aside; continue; }
1213
+
1214
+ if (text.startsWith("<!DOCTYPE", i) || text.startsWith("<!doctype", i)) {
1215
+ var endDoctype = _endOfDoctype(text, i);
1216
+ if (endDoctype === -1) return false;
1217
+ i = endDoctype;
1218
+ continue;
1219
+ }
1220
+ break;
1221
+ }
1222
+
1223
+ if (text.charAt(i) !== "<") return false;
1224
+
1225
+ // Read the whole root name and compare its LOCAL part.
1226
+ //
1227
+ // Two things this gets right that a `startsWith("<svg")` does not. `<svgfoo`
1228
+ // and `<svg.foo` are different elements — and asking instead "does a name
1229
+ // character follow?" is only as good as the character list, since XML's name
1230
+ // grammar runs well past the ASCII set any such list holds, `.` alone being
1231
+ // enough to let `<svg.foo` through. And an SVG may bind its own namespace to
1232
+ // a prefix and write the root `<svg:svg>`, which is the same element.
1233
+ //
1234
+ // What is deliberately NOT done is resolving the prefix to a namespace URI. A
1235
+ // logo that omits `xmlns` altogether is common and was accepted before, so
1236
+ // requiring the binding here would reject real marks; this step is best-effort
1237
+ // detection deciding which leaf to hand back, not validation.
1238
+ var nameEnd = i + 1;
1239
+ while (nameEnd < text.length && !_endsTagName(text, nameEnd)) nameEnd += 1;
1240
+ if (nameEnd >= text.length) return false; // the name never ends: truncated
1241
+ // A qualified name is `prefix:local`, one colon, two parts.
1242
+ // The start tag has to CLOSE. A tag name ends at the whitespace before the
1243
+ // attributes, so a document whose bytes stop mid-tag still has a complete
1244
+ // name — and, if it got as far as a namespace declaration, a perfectly good
1245
+ // binding. That is a truncated document rather than a logo. scanToTagEnd
1246
+ // reports the end of the input when it finds no `>`.
1247
+ var tagEnd = markupTokenizer.scanToTagEnd(text, nameEnd, text.length);
1248
+ if (tagEnd >= text.length) return false;
1249
+ if (!_tagBodyIsWellFormed(text, nameEnd, tagEnd)) return false;
1250
+
1251
+ var parts = text.slice(i + 1, nameEnd).split(":");
1252
+ if (parts.length > 2 || parts[parts.length - 1] !== "svg") return false;
1253
+ // A prefix is an NCName, so a digit or a punctuation character cannot begin
1254
+ // one. Without this a malformed name that declares a matching attribute —
1255
+ // `<0ns:svg xmlns:0ns="...">` — would satisfy the binding check below, since
1256
+ // attribute parsing is as permissive about names as this scan is.
1257
+ if (parts.length === 2 && !_isNcName(parts[0])) return false;
1258
+ // An unprefixed root is accepted without an `xmlns`: logos omit it, and the
1259
+ // scanner this replaces accepted them.
1260
+ if (parts.length === 1) return true;
1261
+
1262
+ // A prefix, though, means nothing until the root binds it. `<x:svg>` where
1263
+ // `x` is another vocabulary is not an SVG, and one declared nowhere names
1264
+ // nothing — so requiring the binding is what separates a namespaced root from
1265
+ // arbitrary XML whose local name happens to read `svg`. It also settles the
1266
+ // malformed names for free: `<a::svg` has too many parts, and `<a<:svg` and
1267
+ // `<0ns:svg` declare no matching `xmlns:` attribute.
1268
+ var attrs = markupTokenizer.parseAttrs(text.slice(nameEnd, tagEnd));
1269
+ var wanted = "xmlns:" + parts[0];
1270
+ for (var a = 0; a < attrs.length; a += 1) {
1271
+ // The value is compared for what it DENOTES: an XML processor resolves
1272
+ // `&#x73;vg` and `svg` to the same namespace, so comparing the lexical form
1273
+ // would reject a root whose namespace is the SVG one.
1274
+ if (attrs[a].name === wanted) {
1275
+ return markupTokenizer.decodeCharRefs(attrs[a].value) === SVG_NAMESPACE;
1276
+ }
1277
+ }
1278
+ return false;
1279
+ }
1280
+
1005
1281
  function _scanForEmbeddedSvg(node, depthBudget) {
1006
1282
  if (!node) return null;
1007
1283
  if (depthBudget < 0) return null;
1008
1284
 
1009
1285
  if (!node.constructed) {
1010
1286
  if (!node.value || node.value.length < 4) return null;
1011
- var prefix = node.value.slice(0, Math.min(node.value.length, 64)).toString("utf8"); /* display truncation length, not bytes */
1012
- if (prefix.indexOf("<svg") !== -1 || /<\?xml[\s\S]*<svg/.test(prefix)) {
1013
- return node.value.toString("utf8");
1014
- }
1015
- return null;
1287
+ var text = node.value.toString("utf8");
1288
+ return _svgRootFollowsPrologue(text) ? text : null;
1016
1289
  }
1017
1290
 
1018
1291
  var children;
@@ -61,6 +61,92 @@ function splitTagNameAttrs(inner, tailChars) {
61
61
  var HTML_TAG_NAME_TAIL = codepointClass.ASCII_ALNUM + ":-";
62
62
  var XML_TAG_NAME_TAIL = codepointClass.ASCII_ALNUM + ":-_";
63
63
 
64
+ // The five entities XML predefines. Everything else in an attribute value is
65
+ // either a numeric character reference or a reference to an entity a DTD
66
+ // declared, which nothing here expands: an attribute value is compared, not
67
+ // executed, and expanding declared entities is the door XXE comes through.
68
+ var XML_PREDEFINED_REFS = {
69
+ amp: "&", lt: "<", gt: ">", quot: "\"", apos: "'",
70
+ };
71
+
72
+ var DEC_DIGITS_RE = /^[0-9]+$/;
73
+ var HEX_DIGITS_RE = /^[0-9A-Fa-f]+$/;
74
+
75
+ // U+10FFFF is six hex digits and 1114111 is seven decimal ones.
76
+ var MAX_CHAR_REF_DIGITS = 7; // digit count, not bytes
77
+
78
+ // decodeCharRefs(s) — an attribute value with its numeric character references
79
+ // and predefined entities resolved, so a value can be COMPARED against what it
80
+ // denotes rather than against one spelling of it. `&#x73;vg` and `svg` are the
81
+ // same namespace to an XML processor, and a scanner that compares the lexical
82
+ // form disagrees with it.
83
+ //
84
+ // An unrecognized or malformed reference is left exactly as written rather than
85
+ // dropped, so nothing a caller then matches on can be manufactured by deleting
86
+ // characters. Returns the input unchanged when it holds no `&` at all.
87
+ function decodeCharRefs(s) {
88
+ if (s.indexOf("&") === -1) return s;
89
+ var out = "";
90
+ var i = 0;
91
+ while (i < s.length) {
92
+ var amp = s.indexOf("&", i);
93
+ if (amp === -1) { out += s.slice(i); break; }
94
+ out += s.slice(i, amp);
95
+ var semi = s.indexOf(";", amp + 1);
96
+ if (semi === -1) { out += s.slice(amp); break; }
97
+ var body = s.slice(amp + 1, semi);
98
+ var decoded = null;
99
+ if (body.charAt(0) === "#") {
100
+ var hex = body.charAt(1) === "x" || body.charAt(1) === "X";
101
+ var digits = hex ? body.slice(2) : body.slice(1);
102
+ // XML puts no limit on leading zeros, so what gets bounded is the
103
+ // SIGNIFICANT digits, not the lexical run: a cap on the written form
104
+ // refuses `&#0000000104;`, which an XML processor resolves normally.
105
+ // Skipping the zeros is a plain index walk, so the unbounded part of the
106
+ // input never reaches a pattern. The largest code point is six hex digits
107
+ // or seven decimal ones, and a refused reference is left exactly as
108
+ // written, so bounding it cannot manufacture a match.
109
+ var firstSignificant = 0;
110
+ while (firstSignificant < digits.length - 1 &&
111
+ digits.charAt(firstSignificant) === "0") firstSignificant += 1;
112
+ var significant = digits.slice(firstSignificant);
113
+ var wellFormed = significant.length > 0 &&
114
+ significant.length <= MAX_CHAR_REF_DIGITS &&
115
+ (hex ? HEX_DIGITS_RE.test(significant) : DEC_DIGITS_RE.test(significant));
116
+ if (wellFormed) {
117
+ var cp = parseInt(significant, hex ? 16 : 10);
118
+ // A lone surrogate is not a character; neither is anything past the
119
+ // last plane, nor U+0000, which XML's Char production excludes. Each
120
+ // would either throw out of fromCodePoint or put a value in the string
121
+ // that no document can contain.
122
+ if (cp > 0 && cp <= 0x10FFFF && !(cp >= 0xD800 && cp <= 0xDFFF)) {
123
+ decoded = String.fromCodePoint(cp);
124
+ }
125
+ }
126
+ } else if (Object.prototype.hasOwnProperty.call(XML_PREDEFINED_REFS, body)) {
127
+ decoded = XML_PREDEFINED_REFS[body];
128
+ }
129
+ out += decoded === null ? s.slice(amp, semi + 1) : decoded;
130
+ i = semi + 1;
131
+ }
132
+ return out;
133
+ }
134
+
135
+ // xmlCommentEnd(s, lt) — the same question for an XML document, where the
136
+ // answer is different. XML 1.0 §2.5 gives a comment exactly one terminator,
137
+ // "-->": there is no "--!>" and no abrupt "<!-->" / "<!--->" close. So the two
138
+ // grammars disagree in BOTH directions, and using the HTML reader on XML is a
139
+ // parser differential either way — it ends a comment early and reads the text
140
+ // after it as markup, and it ends one that XML says is still open.
141
+ //
142
+ // This module already names both tag-name grammars for the same reason; a
143
+ // caller picks the one its document is written in rather than restating it.
144
+ // Returns -1 when the comment is unterminated, as its HTML sibling does.
145
+ function xmlCommentEnd(s, lt) {
146
+ var end = s.indexOf("-->", lt + 4);
147
+ return end === -1 ? -1 : end + 3;
148
+ }
149
+
64
150
  // htmlCommentEnd(s, lt) — given that an HTML comment opens at index `lt`
65
151
  // (s.startsWith("<!--", lt)), return the index ONE PAST the comment's
66
152
  // terminator per the WHATWG HTML tokenizer, not just the legacy "-->" form.
@@ -233,6 +319,8 @@ module.exports = {
233
319
  scanToTagEnd: scanToTagEnd,
234
320
  splitTagNameAttrs: splitTagNameAttrs,
235
321
  htmlCommentEnd: htmlCommentEnd,
322
+ xmlCommentEnd: xmlCommentEnd,
323
+ decodeCharRefs: decodeCharRefs,
236
324
  HTML_TAG_NAME_TAIL: HTML_TAG_NAME_TAIL,
237
325
  XML_TAG_NAME_TAIL: XML_TAG_NAME_TAIL,
238
326
  isMarkupSpace: isMarkupSpace,
@@ -21,7 +21,7 @@
21
21
  "server": "sha256:f3325f480cb8eb814fcb0baaa19336cbbf2b993f48624c6aa9600ffd69d0be5e",
22
22
  "browser": "sha256:0ffd91540bcb586a29b56e52ee1c29df69097b50776beb4036a07558f7a4e12e"
23
23
  },
24
- "refreshedAt": "2026-08-22T03:19:31.188Z"
24
+ "refreshedAt": "2026-08-23T07:32:38.917Z"
25
25
  },
26
26
  "@noble/hashes": {
27
27
  "version": "2.3.0",
@@ -48,7 +48,7 @@
48
48
  "hashes": {
49
49
  "browser": "sha256:dfe4b7ae3c9880e388c8da4b68f44742b229b53afacd1e674179527e33da62b0"
50
50
  },
51
- "refreshedAt": "2026-08-22T03:19:31.188Z"
51
+ "refreshedAt": "2026-08-23T07:32:38.917Z"
52
52
  },
53
53
  "@noble/curves": {
54
54
  "version": "2.3.0",
@@ -70,7 +70,7 @@
70
70
  "hashes": {
71
71
  "server": "sha256:b5fe88d1ea780d0581dee6145d666f89d46fc9531b5db35db2e5b16627840890"
72
72
  },
73
- "refreshedAt": "2026-08-22T03:19:31.188Z",
73
+ "refreshedAt": "2026-08-23T07:32:38.917Z",
74
74
  "components": {
75
75
  "@noble/hashes": {
76
76
  "url": "https://github.com/paulmillr/noble-hashes",
@@ -114,7 +114,7 @@
114
114
  "server": "sha256:fab7ebe5737793862c473444f4ee5912f79dd1edec86683acbb4eecbca0f5892",
115
115
  "browser": "sha256:cae1d5bbdc7184b202b6ca68df6e1db7b0d0f668c77809ded189ca7f271accc9"
116
116
  },
117
- "refreshedAt": "2026-08-22T03:19:31.188Z",
117
+ "refreshedAt": "2026-08-23T07:32:38.917Z",
118
118
  "components": {
119
119
  "@noble/hashes": {
120
120
  "url": "https://github.com/paulmillr/noble-hashes",
@@ -148,7 +148,7 @@
148
148
  },
149
149
  "runtime_artifact": "lib/vendor/common-passwords-top-10000.data.js",
150
150
  "integrity_layers": "sha256 + sha3-512 + SLH-DSA-SHAKE-256f signature + in-payload canary (where applicable)",
151
- "refreshedAt": "2026-08-22T03:19:31.188Z"
151
+ "refreshedAt": "2026-08-23T07:32:38.917Z"
152
152
  },
153
153
  "bimi-trust-anchors": {
154
154
  "version": "operator-managed",
@@ -173,7 +173,7 @@
173
173
  },
174
174
  "runtime_artifact": "lib/vendor/bimi-trust-anchors.data.js",
175
175
  "integrity_layers": "sha256 + sha3-512 + SLH-DSA-SHAKE-256f signature + in-payload canary (where applicable)",
176
- "refreshedAt": "2026-08-22T03:19:31.188Z"
176
+ "refreshedAt": "2026-08-23T07:32:38.917Z"
177
177
  },
178
178
  "publicsuffix-list": {
179
179
  "version": "master",
@@ -193,10 +193,10 @@
193
193
  },
194
194
  "runtime_artifact": "lib/vendor/public-suffix-list.data.js",
195
195
  "integrity_layers": "sha256 + sha3-512 + SLH-DSA-SHAKE-256f signature + in-payload canary (where applicable)",
196
- "refreshedAt": "2026-08-22T03:19:31.188Z"
196
+ "refreshedAt": "2026-08-23T07:32:38.917Z"
197
197
  },
198
198
  "@blamejs/pki": {
199
- "version": "0.5.25",
199
+ "version": "0.5.28",
200
200
  "license": "Apache-2.0",
201
201
  "author": "blamejs",
202
202
  "source": "https://github.com/blamejs/pki",
@@ -216,12 +216,12 @@
216
216
  "server": "lib/vendor/blamejs-pki.cjs"
217
217
  },
218
218
  "bundler": "esbuild --format=cjs --platform=node --external:crypto --external:node:crypto",
219
- "bundledAt": "2026-08-21T00:00:00Z",
220
- "cpe": "cpe:2.3:a:blamejs:pki:0.5.25:*:*:*:*:node.js:*:*",
219
+ "bundledAt": "2026-08-23T00:00:00Z",
220
+ "cpe": "cpe:2.3:a:blamejs:pki:0.5.28:*:*:*:*:node.js:*:*",
221
221
  "hashes": {
222
- "server": "sha256:4e64654dfddb16742f615f24a4e8892286495d94ae29597cdc3e988122f3ef4a"
222
+ "server": "sha256:a11e84272034dc4065dac44f55b722b3b4e1803ddeb27b09cbe6d8644225209c"
223
223
  },
224
- "refreshedAt": "2026-08-22T03:19:31.188Z"
224
+ "refreshedAt": "2026-08-23T07:32:38.917Z"
225
225
  }
226
226
  }
227
227
  }