@blamejs/core 0.7.75 → 0.7.77

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 CHANGED
@@ -8,6 +8,10 @@ upgrading across more than a few patches at a time.
8
8
 
9
9
  ## v0.7.x
10
10
 
11
+ - **0.7.77** (2026-05-06) — Argon2 switched from vendored prebuilds to Node's built-in `crypto.argon2*` (Node 24+). The framework's `lib/vendor/argon2/` directory (with the `argon2.cjs` bundle and the `prebuilds/` tree of platform-specific `.glibc.node` / `.musl.node` artifacts for darwin-arm64 / darwin-x64 / freebsd-arm64 / freebsd-x64 / linux-arm / linux-arm64 / linux-x64 / win32-x64) is **deleted**. New `lib/argon2-builtin.js` is a thin wrapper over `crypto.argon2Sync` that produces and parses the PHC string format (`$argon2id$v=19$m=...,t=...,p=...$<salt>$<hash>`). Wire-format compatibility preserved: existing rows in operator databases continue to verify. Behavior preserved: `b.auth.password.hash` / `.verify` / `.needsRehash` retain their async signatures and return shapes; `b.vault.wrap` and `b.backupCrypto.deriveKey` use the same `raw: true` path for raw-bytes output. Operators wanting to supply their own argon2 implementation (pinned upstream, hardware-accelerated, etc.) override at the call site via `opts.argon2` — the supplied object MUST expose the same `hash` / `verify` / `needsRehash` shape. Drops ~440 KB of platform-specific native prebuilds from the repository and shipped npm tarball; eliminates a supply-chain hop. The vendor manifest's `argon2` entry is removed; `scripts/vendor-update.sh argon2` now refuses with a pointer to `lib/argon2-builtin.js`.
12
+
13
+ - **0.7.76** (2026-05-06) — CVE-class web hardening sweep — Trojan Source (CVE-2021-42574) log defense + drive-by-MIME attachment opt for `staticServe`. **Trojan Source defense** in `b.log` output: every log line now post-processes Unicode bidi / format-control characters (U+061C / U+200E-200F / U+202A-202E / U+2066-2069) into their `\uXXXX` literal escape on the wire so a hostile log message can't re-order the visible line in a TTY / syslog / file reader. JSON.stringify alone does NOT escape these codepoints, so a captured-error message containing `U+202E` (RIGHT-TO-LEFT OVERRIDE) survives into the log surface and silently flips visible field/key associations. The escape applies to the entire serialized JSON line including any extras / bound-context fields. **`staticServe.create({ safeAttachmentForRiskyMimes: true })`** — opt-in flag that adds `Content-Disposition: attachment` to responses whose Content-Type is in the risky-inline-MIME set (`text/html`, `text/xml`, `application/xml`, `application/xhtml+xml`, `image/svg+xml`, `application/javascript`, `text/javascript`, `application/x-javascript`). Defends against drive-by execution of user-uploaded HTML / JS / SVG (CVE-2017-15012 SVG XSS / CVE-2009-1312 HTML drive-by class). Default `false` — operators serving framework asset bundles continue to render inline; operators serving user-content directories opt in. Filename is RFC 5987-encoded (ASCII filename + `filename*=UTF-8''...`) so non-ASCII filenames survive without allowing CR/LF header injection.
14
+
11
15
  - **0.7.75** (2026-05-06) — Audit-emit redaction pipeline. `b.audit.safeEmit` now scrubs the `actor` / `reason` / `metadata` fields through `b.redact.redact()` before they hit the audit handler. Operators who pass `metadata: { reason: e.message }` from a caught error could land DB connection strings, bearer tokens, JWT compact-serialization fixtures, AWS access keys, PEM private keys, SSH keys, credit cards, and SSNs in audit rows; the redact pipeline catches the common shapes (sensitive field names + value-shape detectors) and replaces them with markers (`[REDACTED]`, `[REDACTED-CONN-STRING]`, `[REDACTED-JWT]`, `[REDACTED-PEM]`, `[REDACTED-AWS-KEY]`, `[REDACTED-CC]`, `[REDACTED-SSN]`, `[REDACTED-SEALED]`, `[REDACTED-SSH-KEY]`). The `b.redact` primitive existed in lib/ since v0.4.x but was dead code — `audit.safeEmit` previously passed metadata through unchanged. New connection-string detector matches `protocol://user:pass@host` shapes that surface in error messages from external-DB / SMTP / HTTP drivers (RFC 3986 generic syntax). Drop-silent on redact failure — the pipeline never breaks the caller's audit attempt.
12
16
 
13
17
  - **0.7.74** (2026-05-06) — Email receive-side parity: DMARC aggregate (RUA) report parser + ARC trust evaluation + Authentication-Results header builder + TLS-RPT receive-side report parser. Closes the "framework can send mail compliantly but can't receive compliantly" gap. **`b.mail.dmarc.parseAggregateReport(xmlBytes, { contentType? })`** parses RFC 7489 §7.2 aggregate XML reports through the framework's existing `lib/parsers/safe-xml.js` (the existing security-focused XML parser handles XXE / DOCTYPE / entity-expansion defenses by default). Auto-detects gzip via magic bytes (`0x1f 0x8b`) or `Content-Type: application/gzip`. Returns `{ reportMetadata, policyPublished, records, totals }` with per-record source-IP / count / policy-evaluated dispositions / identifiers / DKIM + SPF auth results, plus aggregated `messages` / `aligned` / `notAligned` totals operators want for dashboards. Caps report size at 8 MiB and records-per-report at 10 000. **`b.mail.arc.evaluate(rfc822, { trustedSealers })`** wraps the existing `arc.verify` cryptographic chain check with the operator-side trust decision: given a passing chain, did any hop in the chain belong to a sealer the operator trusts? Returns `{ chainStatus, trusted, trustedHop, trustedDomain }` walking hops most-recent-first so the deepest trusted sealer wins. **`b.mail.authResults.emit({ authservId, results, fold? })`** builds the RFC 8601 Authentication-Results header value — operators consume per-method results from `b.mail.spf.verify` / `b.mail.dmarc.evaluate` / `b.mail.arc.verify`, hand them to `.emit`, and the framework formats the conformant header string with method-specific properties (`smtp.mailfrom`, `header.d`, `header.from`, `policy.iprev`, `policy.ip`, `policy.tls`). Refuses unknown methods / results at config-mistake time. **`b.network.smtp.tlsRpt.parseReport(body, { contentType? })`** is the receive-side counterpart to `tlsRpt.recordShape` / `tlsRpt.submit` — accepts a Buffer or string, auto-detects gzip, parses JSON, validates the RFC 8460 §4.4 required-fields shape (`organization-name`, `date-range`, `report-id`, `policies`), aggregates `total-successful-session-count` / `total-failure-session-count` across policies. Caps report size at 8 MiB and policies-per-report at 1024.
package/NOTICE CHANGED
@@ -24,16 +24,6 @@ Copyright: Copyright (c) 2023 Paul Miller (https://paulmillr.com)
24
24
  Used for: XChaCha20-Poly1305 authenticated encryption (lib/crypto.js,
25
25
  lib/vault-wrap.js, via lib/vendor/noble-ciphers.cjs)
26
26
  --------------------------------------------------------------------------------
27
- Component: argon2 (node-argon2)
28
- Version: 0.44.0
29
- Source: https://github.com/ranisalt/node-argon2
30
- License: MIT
31
- Copyright: Copyright (c) 2017 Ranieri Althoff
32
- Used for: Argon2id passphrase-derived key derivation in the vault wrap
33
- format (lib/vault-wrap.js, via lib/vendor/argon2/). Native
34
- prebuilds shipped for darwin-{arm64,x64}, freebsd-{arm64,x64},
35
- linux-{arm,arm64,x64}, win32-x64.
36
- --------------------------------------------------------------------------------
37
27
  Component: @simplewebauthn/server
38
28
  Version: 13.3.0
39
29
  Source: https://github.com/MasterKale/SimpleWebAuthn
package/README.md CHANGED
@@ -114,7 +114,6 @@ All runtime dependencies are committed to the repo — no transitive npm install
114
114
  |---|---|---|---|
115
115
  | [`@noble/ciphers`](https://github.com/paulmillr/noble-ciphers) | 2.2.0 | [Paul Miller](https://github.com/paulmillr) | XChaCha20-Poly1305 AEAD |
116
116
  | [`@simplewebauthn/server`](https://github.com/MasterKale/SimpleWebAuthn) | 13.3.0 | [Matthew Miller](https://github.com/MasterKale) | WebAuthn / passkey verification |
117
- | [`argon2`](https://github.com/ranisalt/node-argon2) | 0.44.0 | [Ranieri Althoff](https://github.com/ranisalt) | Password hashing (native prebuilds, 8 platforms) |
118
117
  | [`@peculiar/x509`](https://github.com/PeculiarVentures/x509) + [`pkijs`](https://github.com/PeculiarVentures/PKI.js) | 2.0.0 + 3.4.0 | [Peculiar Ventures](https://github.com/PeculiarVentures) | Pure-JS mTLS CA — ECDSA P-384 cert signing, PKCS#12 packaging (no openssl CLI) |
119
118
  | [`SecLists` 10k-most-common.txt](https://github.com/danielmiessler/SecLists/blob/master/Passwords/Common-Credentials/10k-most-common.txt) | master snapshot | [Daniel Miessler / SecLists contributors](https://github.com/danielmiessler/SecLists) (CC-BY-3.0) | Top-10000 common-password dictionary read by `b.auth.password.policy()` for the NIST 800-63B §5.1.1.2 "previously breached" check |
120
119
  | [`prismjs`](https://prismjs.com/) | 1.30.0 | [Lea Verou + contributors](https://github.com/PrismJS/prism) | Syntax highlighting in the example wiki's code blocks (browser-side) |
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ /**
3
+ * Thin wrapper over Node's built-in `crypto.argon2` that produces and
4
+ * parses the PHC string format
5
+ * (`$argon2id$v=19$m=65536,t=3,p=4$<salt>$<hash>`).
6
+ *
7
+ * Replaces the vendored `lib/vendor/argon2/` prebuilds (which the
8
+ * framework carried since v0.4.x). Node 24+ ships a stable
9
+ * `crypto.argon2*` API; vendoring the third-party native module is no
10
+ * longer necessary, eliminates the supply-chain weight of platform-
11
+ * specific prebuilds, and keeps the framework's "zero npm runtime
12
+ * deps" posture intact without dragging argon2 prebuild artifacts
13
+ * across every install.
14
+ *
15
+ * Operators wanting to supply their own argon2 implementation (e.g.
16
+ * pinned to a specific upstream commit, or routed through a hardware-
17
+ * backed accelerator) override at the call site by passing `argon2:`
18
+ * in opts to `b.auth.password.hash` / `.verify` / `.needsRehash`. The
19
+ * supplied object MUST expose the same `hash` / `verify` /
20
+ * `needsRehash` shape this wrapper exposes.
21
+ */
22
+
23
+ var nodeCrypto = require("crypto");
24
+ var blamejsCrypto = require("./crypto");
25
+ var C = require("./constants");
26
+
27
+ var ARGON2ID = "argon2id";
28
+
29
+ // Argon2 v1.3 — the only version current implementations emit.
30
+ var ARGON2_VERSION = 0x13; // allow:raw-byte-literal — argon2 algorithm version
31
+
32
+ var DEFAULT_HASH_LENGTH = C.BYTES.bytes(32);
33
+ var DEFAULT_SALT_LENGTH = C.BYTES.bytes(16);
34
+
35
+ // Standard PHC base64 — no padding, alphabet [A-Za-z0-9+/].
36
+ function _b64NoPad(buf) {
37
+ return buf.toString("base64").replace(/=+$/g, "");
38
+ }
39
+
40
+ function _fromB64NoPad(s) {
41
+ // Node tolerates missing padding in `Buffer.from(s, "base64")` so we
42
+ // pass straight through; the no-pad form is what PHC strings emit
43
+ // on the wire.
44
+ return Buffer.from(s, "base64");
45
+ }
46
+
47
+ function _phcEncode(salt, hash, params) {
48
+ return "$argon2id$v=" + ARGON2_VERSION +
49
+ "$m=" + params.memoryCost +
50
+ ",t=" + params.timeCost +
51
+ ",p=" + params.parallelism +
52
+ "$" + _b64NoPad(salt) +
53
+ "$" + _b64NoPad(hash);
54
+ }
55
+
56
+ // Parse a PHC string into structured form. Accepts only argon2id
57
+ // shapes — argon2i / argon2d are intentionally not supported by the
58
+ // framework wrapper.
59
+ function _phcDecode(stored) {
60
+ if (typeof stored !== "string" || stored.length === 0) return null;
61
+ var parts = stored.split("$");
62
+ if (parts.length !== 6) return null;
63
+ if (parts[0] !== "" || parts[1] !== ARGON2ID) return null;
64
+ var ver = /^v=(\d+)$/.exec(parts[2]);
65
+ if (!ver) return null;
66
+ var version = parseInt(ver[1], 10);
67
+ if (!isFinite(version) || version <= 0) return null;
68
+ var paramTokens = parts[3].split(",");
69
+ var p = { memoryCost: NaN, timeCost: NaN, parallelism: NaN };
70
+ for (var i = 0; i < paramTokens.length; i += 1) {
71
+ var t = paramTokens[i];
72
+ var eq = t.indexOf("=");
73
+ if (eq === -1) return null;
74
+ var k = t.slice(0, eq);
75
+ var v = parseInt(t.slice(eq + 1), 10);
76
+ if (!isFinite(v)) return null;
77
+ if (k === "m") p.memoryCost = v;
78
+ else if (k === "t") p.timeCost = v;
79
+ else if (k === "p") p.parallelism = v;
80
+ }
81
+ if (!isFinite(p.memoryCost) || !isFinite(p.timeCost) || !isFinite(p.parallelism)) return null;
82
+ var salt;
83
+ var hash;
84
+ try { salt = _fromB64NoPad(parts[4]); }
85
+ catch (_e) { return null; }
86
+ try { hash = _fromB64NoPad(parts[5]); }
87
+ catch (_e) { return null; }
88
+ return { version: version, params: p, salt: salt, hash: hash };
89
+ }
90
+
91
+ function _runArgon2(message, salt, params, hashLength) {
92
+ // Use the async variant so the call queues onto the libuv threadpool
93
+ // instead of blocking the main event loop. argon2 with framework
94
+ // defaults (64 MiB / 3 passes / 1 lane) takes ~100ms per call;
95
+ // blocking the loop that long stalls every concurrent timer the
96
+ // test suite is also running and trips spurious flakes in
97
+ // safe-async-loops fixtures.
98
+ return new Promise(function (resolve, reject) {
99
+ nodeCrypto.argon2(ARGON2ID, {
100
+ message: message,
101
+ nonce: salt,
102
+ memory: params.memoryCost,
103
+ passes: params.timeCost,
104
+ parallelism: params.parallelism,
105
+ tagLength: hashLength,
106
+ }, function (err, result) {
107
+ if (err) reject(err);
108
+ else resolve(result);
109
+ });
110
+ });
111
+ }
112
+
113
+ // ---- public surface ----
114
+
115
+ async function hash(plain, opts) {
116
+ opts = opts || {};
117
+ var params = {
118
+ memoryCost: opts.memoryCost || C.BYTES.kib(64), // 64 MiB
119
+ timeCost: opts.timeCost || 3,
120
+ parallelism: opts.parallelism || 1,
121
+ };
122
+ var hashLength = opts.hashLength || DEFAULT_HASH_LENGTH;
123
+ var salt = opts.salt || nodeCrypto.randomBytes(DEFAULT_SALT_LENGTH);
124
+ var message = Buffer.isBuffer(plain) ? plain : Buffer.from(String(plain), "utf8");
125
+ var raw = await _runArgon2(message, salt, params, hashLength);
126
+ // raw: true — return the unwrapped Buffer (used by vault key
127
+ // derivation + backup KDF where the bytes feed directly into
128
+ // XChaCha20). Default produces a PHC-string-encoded password hash.
129
+ if (opts.raw === true) return raw;
130
+ return _phcEncode(salt, raw, params);
131
+ }
132
+
133
+ async function verify(stored, plain) {
134
+ var dec = _phcDecode(stored);
135
+ if (!dec) return false;
136
+ var message = Buffer.isBuffer(plain) ? plain : Buffer.from(String(plain), "utf8");
137
+ var actual;
138
+ try { actual = await _runArgon2(message, dec.salt, dec.params, dec.hash.length); }
139
+ catch (_e) { return false; }
140
+ return blamejsCrypto.timingSafeEqual(actual, dec.hash);
141
+ }
142
+
143
+ function needsRehash(stored, opts) {
144
+ opts = opts || {};
145
+ var dec = _phcDecode(stored);
146
+ if (!dec) return true;
147
+ if (dec.version !== ARGON2_VERSION) return true;
148
+ var memoryCost = opts.memoryCost || C.BYTES.kib(64); // same defaults as hash()
149
+ var timeCost = opts.timeCost || 3;
150
+ var parallelism = opts.parallelism || 1;
151
+ if (dec.params.memoryCost < memoryCost) return true;
152
+ if (dec.params.timeCost < timeCost) return true;
153
+ if (dec.params.parallelism < parallelism) return true;
154
+ return false;
155
+ }
156
+
157
+ module.exports = {
158
+ argon2id: ARGON2ID,
159
+ hash: hash,
160
+ verify: verify,
161
+ needsRehash: needsRehash,
162
+ // Test-only — let the test harness exercise the PHC encode/decode
163
+ // round trip without re-running actual hashing.
164
+ _phcEncode: _phcEncode,
165
+ _phcDecode: _phcDecode,
166
+ };
@@ -46,7 +46,7 @@
46
46
  * verify is NOT an error — it returns false. Errors are reserved for
47
47
  * "the call shape was wrong" (empty plain, oversize plain).
48
48
  */
49
- var argon2 = require("../vendor/argon2");
49
+ var argon2 = require("../argon2-builtin");
50
50
  var C = require("../constants");
51
51
  var httpClient = require("../http-client");
52
52
  var hibpSha1 = require("../framework-sha1-hibp");
@@ -45,7 +45,7 @@ var nodeCrypto = require("node:crypto");
45
45
  var C = require("../constants");
46
46
  var safeBuffer = require("../safe-buffer");
47
47
  var { xchacha20poly1305 } = require("../vendor/noble-ciphers.cjs");
48
- var argon2 = require("../vendor/argon2");
48
+ var argon2 = require("../argon2-builtin");
49
49
  var { FrameworkError } = require("../framework-error");
50
50
 
51
51
  class BackupCryptoError extends FrameworkError {
package/lib/log.js CHANGED
@@ -279,6 +279,14 @@ function create(opts) {
279
279
  _logError: "extras not serializable",
280
280
  }) + "\n";
281
281
  }
282
+ // Trojan-Source defense (CVE-2021-42574). JSON.stringify does NOT
283
+ // escape Unicode bidi / format controls, so a hostile log message
284
+ // containing U+202E (RIGHT-TO-LEFT OVERRIDE) survives into TTY /
285
+ // syslog / file sinks where it can re-order the visible line —
286
+ // forging which fields appear under which keys when the operator
287
+ // reads the log. Escape the entire bidi/format-control set to
288
+ // `\uXXXX` literals on the wire.
289
+ line = _escapeBidiControls(line);
282
290
 
283
291
  var lvlNum = LEVELS[levelName];
284
292
  for (var s = 0; s < sinks.length; s++) {
@@ -479,6 +487,25 @@ function makeViaOrFallback(operatorLog, fallbackLog) {
479
487
 
480
488
  // Boot-time minimum level (debug suppressed unless explicitly enabled).
481
489
  // Uses raw process.env per the documented load-cycle exception: log.js
490
+ // Trojan-Source defense (CVE-2021-42574). Replace Unicode bidi /
491
+ // format-control characters with their `\uXXXX` literal escape so a
492
+ // hostile log message can't re-order the visible line in a TTY /
493
+ // syslog reader. Set covers:
494
+ // U+061C — Arabic Letter Mark
495
+ // U+200E/U+200F — LRM/RLM
496
+ // U+202A-U+202E — LRE/RLE/PDF/LRO/RLO
497
+ // U+2066-U+2069 — LRI/RLI/FSI/PDI
498
+ var _BIDI_CONTROL_RE = /[؜‎‏‪‫‬‭‮⁦⁧⁨⁩]/g;
499
+
500
+ function _escapeBidiControls(s) {
501
+ if (typeof s !== "string" || s.length === 0) return s;
502
+ return s.replace(_BIDI_CONTROL_RE, function (ch) {
503
+ var code = ch.charCodeAt(0).toString(16); // allow:raw-byte-literal — Unicode hex radix
504
+ while (code.length < 4) code = "0" + code;
505
+ return "\\u" + code;
506
+ });
507
+ }
508
+
482
509
  // runs before safeEnv on the boot path; safeEnv requires log, so log
483
510
  // can't go through safeEnv to read its own level.
484
511
  function _bootMinLevel() {
package/lib/static.js CHANGED
@@ -208,6 +208,46 @@ function _contentTypeFor(filePath, table) {
208
208
  return (table && table[ext]) || DEFAULT_CONTENT_TYPES[ext] || "application/octet-stream";
209
209
  }
210
210
 
211
+ // Risky MIMEs that the browser executes inline. When safeAttachment is
212
+ // on, the framework forces Content-Disposition: attachment so
213
+ // drive-by uploads can't be executed in the user's browser. Operators
214
+ // serving trusted assets (CSS / JS bundle / SVG icon) opt out by NOT
215
+ // setting safeAttachmentForRiskyMimes — leaving the existing inline
216
+ // default. The defense is per-CVE-2017-15012 (SVG XSS) /
217
+ // CVE-2009-1312 (HTML drive-by) class.
218
+ var RISKY_INLINE_MIMES = {
219
+ "text/html": true,
220
+ "text/xml": true,
221
+ "application/xml": true,
222
+ "application/xhtml+xml": true,
223
+ "image/svg+xml": true,
224
+ "application/javascript": true,
225
+ "text/javascript": true,
226
+ "application/x-javascript": true,
227
+ };
228
+
229
+ function _isRiskyInlineMime(contentType) {
230
+ if (typeof contentType !== "string" || contentType.length === 0) return false;
231
+ // Strip parameters like "; charset=utf-8".
232
+ var semi = contentType.indexOf(";");
233
+ var bare = (semi === -1 ? contentType : contentType.slice(0, semi)).trim().toLowerCase();
234
+ return RISKY_INLINE_MIMES[bare] === true;
235
+ }
236
+
237
+ // Build a safe Content-Disposition value for an attachment. The
238
+ // filename is RFC 5987-encoded so non-ASCII characters survive without
239
+ // allowing CR/LF header injection.
240
+ function _attachmentDisposition(filePath) {
241
+ var name = path.basename(filePath);
242
+ // Refuse CR/LF/NUL outright — they're already filtered upstream by
243
+ // the path-traversal guard, but defense-in-depth here.
244
+ if (/[\r\n\0]/.test(name)) name = "download";
245
+ // ASCII-safe filename (replace non-ASCII with _) plus filename* = UTF-8 form.
246
+ var asciiName = name.replace(/[^\x20-\x7e]/g, "_").replace(/["\\]/g, "_");
247
+ var encName = encodeURIComponent(name);
248
+ return 'attachment; filename="' + asciiName + '"; filename*=UTF-8\'\'' + encName;
249
+ }
250
+
211
251
  // _parseRangeHeader — RFC 7233 single-range parser. Returns null when:
212
252
  // - header absent
213
253
  // - syntactically malformed (not `bytes=`, multi-range, suffix syntax
@@ -331,6 +371,8 @@ function _validateCreateOpts(opts) {
331
371
  validateOpts.optionalBoolean(opts.acceptRanges, "staticServe.create: acceptRanges", StaticServeError);
332
372
  validateOpts.optionalBoolean(opts.auditSuccess, "staticServe.create: auditSuccess", StaticServeError);
333
373
  validateOpts.optionalBoolean(opts.auditFailures, "staticServe.create: auditFailures", StaticServeError);
374
+ validateOpts.optionalBoolean(opts.safeAttachmentForRiskyMimes,
375
+ "staticServe.create: safeAttachmentForRiskyMimes", StaticServeError);
334
376
  numericBounds.requireNonNegativeFiniteIntIfPresent(opts.maxBytesPerActorPerWindowMs,
335
377
  "staticServe.create: maxBytesPerActorPerWindowMs", StaticServeError, "BAD_OPT");
336
378
  numericBounds.requireNonNegativeFiniteIntIfPresent(opts.maxBytesAllActorsPerWindowMs,
@@ -507,6 +549,7 @@ function create(opts) {
507
549
  var auditSuccess = cfg.auditSuccess;
508
550
  var auditFailures = cfg.auditFailures;
509
551
  var acceptRanges = cfg.acceptRanges;
552
+ var safeAttachment = !!cfg.safeAttachmentForRiskyMimes;
510
553
  var perActorCap = cfg.maxBytesPerActorPerWindowMs;
511
554
  var globalCap = cfg.maxBytesAllActorsPerWindowMs;
512
555
  var bandwidthWindowMs = cfg.bandwidthWindowMs;
@@ -851,6 +894,13 @@ function create(opts) {
851
894
  "Last-Modified": meta.lastModified,
852
895
  "X-Integrity": meta.integrity,
853
896
  };
897
+ // Drive-by-execution defense — when safeAttachmentForRiskyMimes is
898
+ // on, force Content-Disposition: attachment for HTML / JS / SVG /
899
+ // XML so the browser downloads instead of rendering. Operator's
900
+ // onServe hook can override.
901
+ if (safeAttachment && _isRiskyInlineMime(headers["Content-Type"])) {
902
+ headers["Content-Disposition"] = _attachmentDisposition(absPath);
903
+ }
854
904
  if (acceptRanges) headers["Accept-Ranges"] = "bytes";
855
905
  if (range) headers["Content-Range"] = "bytes " + range.start + "-" + range.end + "/" + meta.size;
856
906
 
package/lib/vault/wrap.js CHANGED
@@ -25,7 +25,7 @@
25
25
  * This module is PURE — no filesystem I/O. Callers handle reading/writing.
26
26
  * wrap() and unwrap() are async because Argon2 is async via its native binding.
27
27
  */
28
- var argon2 = require("../vendor/argon2");
28
+ var argon2 = require("../argon2-builtin");
29
29
  var C = require("../constants");
30
30
  var { xchacha20poly1305 } = require("../vendor/noble-ciphers.cjs");
31
31
  var { generateBytes } = require("../crypto");
@@ -18,36 +18,6 @@
18
18
  "server": "sha256:5d539dfc9ef47121d4c09bd7256d76448a1f5ac47ee09ac44c78ff6a062af9ab"
19
19
  }
20
20
  },
21
- "argon2": {
22
- "version": "0.44.0",
23
- "license": "MIT",
24
- "author": "Ranieri Althoff",
25
- "source": "https://github.com/ranisalt/node-argon2",
26
- "exports": [
27
- "hash",
28
- "verify"
29
- ],
30
- "files": {
31
- "server": "lib/vendor/argon2/argon2.cjs",
32
- "prebuilds": "lib/vendor/argon2/prebuilds/"
33
- },
34
- "platforms": [
35
- "darwin-arm64",
36
- "darwin-x64",
37
- "freebsd-arm64",
38
- "freebsd-x64",
39
- "linux-arm",
40
- "linux-arm64",
41
- "linux-x64",
42
- "win32-x64"
43
- ],
44
- "bundler": "esbuild --format=cjs --platform=node (inlines @phc/format + node-gyp-build)",
45
- "bundledAt": "2026-04-25",
46
- "hashes": {
47
- "server": "sha256:93b8d2fb7f24dc1b3304dc9420844d5e1afc199c41ab1f9a90c8de48cc7c2359",
48
- "prebuilds": "sha256-tree:65921b7cf331e0a9430a1b52440da8f26cdf9d215a4cd490edbc4804dd713df3"
49
- }
50
- },
51
21
  "@simplewebauthn/server": {
52
22
  "version": "13.3.0",
53
23
  "license": "MIT",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/core",
3
- "version": "0.7.75",
3
+ "version": "0.7.77",
4
4
  "description": "The Node framework that owns its stack.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "blamejs contributors",
@@ -2,10 +2,10 @@
2
2
  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
3
3
  "bomFormat": "CycloneDX",
4
4
  "specVersion": "1.5",
5
- "serialNumber": "urn:uuid:029bc278-cc4e-40cb-9b56-3102289527e4",
5
+ "serialNumber": "urn:uuid:3d6aa43b-6da6-44c8-a687-434e93ef3b07",
6
6
  "version": 1,
7
7
  "metadata": {
8
- "timestamp": "2026-05-06T04:13:02.729Z",
8
+ "timestamp": "2026-05-06T04:48:07.561Z",
9
9
  "lifecycles": [
10
10
  {
11
11
  "phase": "build"
@@ -19,14 +19,14 @@
19
19
  }
20
20
  ],
21
21
  "component": {
22
- "bom-ref": "@blamejs/core@0.7.75",
22
+ "bom-ref": "@blamejs/core@0.7.77",
23
23
  "type": "library",
24
24
  "name": "blamejs",
25
- "version": "0.7.75",
25
+ "version": "0.7.77",
26
26
  "scope": "required",
27
27
  "author": "blamejs contributors",
28
28
  "description": "The Node framework that owns its stack.",
29
- "purl": "pkg:npm/%40blamejs/core@0.7.75",
29
+ "purl": "pkg:npm/%40blamejs/core@0.7.77",
30
30
  "properties": [],
31
31
  "externalReferences": [
32
32
  {
@@ -54,7 +54,7 @@
54
54
  "components": [],
55
55
  "dependencies": [
56
56
  {
57
- "ref": "@blamejs/core@0.7.75",
57
+ "ref": "@blamejs/core@0.7.77",
58
58
  "dependsOn": []
59
59
  }
60
60
  ]
@@ -1,466 +0,0 @@
1
- // argon2 v0.44.0 — MIT License (c) Ranieri Althoff — https://github.com/ranisalt/node-argon2
2
- var __getOwnPropNames = Object.getOwnPropertyNames;
3
- var __commonJS = (cb, mod) => function __require() {
4
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
5
- };
6
-
7
- // node_modules/@phc/format/index.js
8
- var require_format = __commonJS({
9
- "node_modules/@phc/format/index.js"(exports2, module2) {
10
- var idRegex = /^[a-z0-9-]{1,32}$/;
11
- var nameRegex = /^[a-z0-9-]{1,32}$/;
12
- var valueRegex = /^[a-zA-Z0-9/+.-]+$/;
13
- var b64Regex = /^([a-zA-Z0-9/+.-]+|)$/;
14
- var decimalRegex = /^((-)?[1-9]\d*|0)$/;
15
- var versionRegex = /^v=(\d+)$/;
16
- function objToKeyVal(obj) {
17
- return objectKeys(obj).map((k) => [k, obj[k]].join("=")).join(",");
18
- }
19
- function keyValtoObj(str) {
20
- const obj = {};
21
- str.split(",").forEach((ps) => {
22
- const pss = ps.split("=");
23
- if (pss.length < 2) {
24
- throw new TypeError(`params must be in the format name=value`);
25
- }
26
- obj[pss.shift()] = pss.join("=");
27
- });
28
- return obj;
29
- }
30
- function objectKeys(object) {
31
- return Object.keys(object);
32
- }
33
- function objectValues(object) {
34
- if (typeof Object.values === "function") return Object.values(object);
35
- return objectKeys(object).map((k) => object[k]);
36
- }
37
- function serialize(opts) {
38
- const fields = [""];
39
- if (typeof opts !== "object" || opts === null) {
40
- throw new TypeError("opts must be an object");
41
- }
42
- if (typeof opts.id !== "string") {
43
- throw new TypeError("id must be a string");
44
- }
45
- if (!idRegex.test(opts.id)) {
46
- throw new TypeError(`id must satisfy ${idRegex}`);
47
- }
48
- fields.push(opts.id);
49
- if (typeof opts.version !== "undefined") {
50
- if (typeof opts.version !== "number" || opts.version < 0 || !Number.isInteger(opts.version)) {
51
- throw new TypeError("version must be a positive integer number");
52
- }
53
- fields.push(`v=${opts.version}`);
54
- }
55
- if (typeof opts.params !== "undefined") {
56
- if (typeof opts.params !== "object" || opts.params === null) {
57
- throw new TypeError("params must be an object");
58
- }
59
- const pk = objectKeys(opts.params);
60
- if (!pk.every((p) => nameRegex.test(p))) {
61
- throw new TypeError(`params names must satisfy ${nameRegex}`);
62
- }
63
- pk.forEach((k) => {
64
- if (typeof opts.params[k] === "number") {
65
- opts.params[k] = opts.params[k].toString();
66
- } else if (Buffer.isBuffer(opts.params[k])) {
67
- opts.params[k] = opts.params[k].toString("base64").split("=")[0];
68
- }
69
- });
70
- const pv = objectValues(opts.params);
71
- if (!pv.every((v) => typeof v === "string")) {
72
- throw new TypeError("params values must be strings");
73
- }
74
- if (!pv.every((v) => valueRegex.test(v))) {
75
- throw new TypeError(`params values must satisfy ${valueRegex}`);
76
- }
77
- const strpar = objToKeyVal(opts.params);
78
- fields.push(strpar);
79
- }
80
- if (typeof opts.salt !== "undefined") {
81
- if (!Buffer.isBuffer(opts.salt)) {
82
- throw new TypeError("salt must be a Buffer");
83
- }
84
- fields.push(opts.salt.toString("base64").split("=")[0]);
85
- if (typeof opts.hash !== "undefined") {
86
- if (!Buffer.isBuffer(opts.hash)) {
87
- throw new TypeError("hash must be a Buffer");
88
- }
89
- fields.push(opts.hash.toString("base64").split("=")[0]);
90
- }
91
- }
92
- const phcstr = fields.join("$");
93
- return phcstr;
94
- }
95
- function deserialize(phcstr) {
96
- if (typeof phcstr !== "string" || phcstr === "") {
97
- throw new TypeError("pchstr must be a non-empty string");
98
- }
99
- if (phcstr[0] !== "$") {
100
- throw new TypeError("pchstr must contain a $ as first char");
101
- }
102
- const fields = phcstr.split("$");
103
- fields.shift();
104
- let maxf = 5;
105
- if (!versionRegex.test(fields[1])) maxf--;
106
- if (fields.length > maxf) {
107
- throw new TypeError(
108
- `pchstr contains too many fileds: ${fields.length}/${maxf}`
109
- );
110
- }
111
- const id = fields.shift();
112
- if (!idRegex.test(id)) {
113
- throw new TypeError(`id must satisfy ${idRegex}`);
114
- }
115
- let version;
116
- if (versionRegex.test(fields[0])) {
117
- version = parseInt(fields.shift().match(versionRegex)[1], 10);
118
- }
119
- let hash;
120
- let salt;
121
- if (b64Regex.test(fields[fields.length - 1])) {
122
- if (fields.length > 1 && b64Regex.test(fields[fields.length - 2])) {
123
- hash = Buffer.from(fields.pop(), "base64");
124
- salt = Buffer.from(fields.pop(), "base64");
125
- } else {
126
- salt = Buffer.from(fields.pop(), "base64");
127
- }
128
- }
129
- let params;
130
- if (fields.length > 0) {
131
- const parstr = fields.pop();
132
- params = keyValtoObj(parstr);
133
- if (!objectKeys(params).every((p) => nameRegex.test(p))) {
134
- throw new TypeError(`params names must satisfy ${nameRegex}`);
135
- }
136
- const pv = objectValues(params);
137
- if (!pv.every((v) => valueRegex.test(v))) {
138
- throw new TypeError(`params values must satisfy ${valueRegex}`);
139
- }
140
- const pk = objectKeys(params);
141
- pk.forEach((k) => {
142
- params[k] = decimalRegex.test(params[k]) ? parseInt(params[k], 10) : params[k];
143
- });
144
- }
145
- if (fields.length > 0) {
146
- throw new TypeError(`pchstr contains unrecognized fileds: ${fields}`);
147
- }
148
- const phcobj = { id };
149
- if (version) phcobj.version = version;
150
- if (params) phcobj.params = params;
151
- if (salt) phcobj.salt = salt;
152
- if (hash) phcobj.hash = hash;
153
- return phcobj;
154
- }
155
- module2.exports = {
156
- serialize,
157
- deserialize
158
- };
159
- }
160
- });
161
-
162
- // node_modules/node-gyp-build/node-gyp-build.js
163
- var require_node_gyp_build = __commonJS({
164
- "node_modules/node-gyp-build/node-gyp-build.js"(exports2, module2) {
165
- var fs = require("fs");
166
- var path = require("path");
167
- var os = require("os");
168
- var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : require;
169
- var vars = process.config && process.config.variables || {};
170
- var prebuildsOnly = !!process.env.PREBUILDS_ONLY;
171
- var abi = process.versions.modules;
172
- var runtime = isElectron() ? "electron" : isNwjs() ? "node-webkit" : "node";
173
- var arch = process.env.npm_config_arch || os.arch();
174
- var platform = process.env.npm_config_platform || os.platform();
175
- var libc = process.env.LIBC || (isAlpine(platform) ? "musl" : "glibc");
176
- var armv = process.env.ARM_VERSION || (arch === "arm64" ? "8" : vars.arm_version) || "";
177
- var uv = (process.versions.uv || "").split(".")[0];
178
- module2.exports = load;
179
- function load(dir) {
180
- return runtimeRequire(load.resolve(dir));
181
- }
182
- load.resolve = load.path = function(dir) {
183
- dir = path.resolve(dir || ".");
184
- try {
185
- var name = runtimeRequire(path.join(dir, "package.json")).name.toUpperCase().replace(/-/g, "_");
186
- if (process.env[name + "_PREBUILD"]) dir = process.env[name + "_PREBUILD"];
187
- } catch (err) {
188
- }
189
- if (!prebuildsOnly) {
190
- var release = getFirst(path.join(dir, "build/Release"), matchBuild);
191
- if (release) return release;
192
- var debug = getFirst(path.join(dir, "build/Debug"), matchBuild);
193
- if (debug) return debug;
194
- }
195
- var prebuild = resolve(dir);
196
- if (prebuild) return prebuild;
197
- var nearby = resolve(path.dirname(process.execPath));
198
- if (nearby) return nearby;
199
- var target = [
200
- "platform=" + platform,
201
- "arch=" + arch,
202
- "runtime=" + runtime,
203
- "abi=" + abi,
204
- "uv=" + uv,
205
- armv ? "armv=" + armv : "",
206
- "libc=" + libc,
207
- "node=" + process.versions.node,
208
- process.versions.electron ? "electron=" + process.versions.electron : "",
209
- typeof __webpack_require__ === "function" ? "webpack=true" : ""
210
- // eslint-disable-line
211
- ].filter(Boolean).join(" ");
212
- throw new Error("No native build was found for " + target + "\n loaded from: " + dir + "\n");
213
- function resolve(dir2) {
214
- var tuples = readdirSync(path.join(dir2, "prebuilds")).map(parseTuple);
215
- var tuple = tuples.filter(matchTuple(platform, arch)).sort(compareTuples)[0];
216
- if (!tuple) return;
217
- var prebuilds = path.join(dir2, "prebuilds", tuple.name);
218
- var parsed = readdirSync(prebuilds).map(parseTags);
219
- var candidates = parsed.filter(matchTags(runtime, abi));
220
- var winner = candidates.sort(compareTags(runtime))[0];
221
- if (winner) return path.join(prebuilds, winner.file);
222
- }
223
- };
224
- function readdirSync(dir) {
225
- try {
226
- return fs.readdirSync(dir);
227
- } catch (err) {
228
- return [];
229
- }
230
- }
231
- function getFirst(dir, filter) {
232
- var files = readdirSync(dir).filter(filter);
233
- return files[0] && path.join(dir, files[0]);
234
- }
235
- function matchBuild(name) {
236
- return /\.node$/.test(name);
237
- }
238
- function parseTuple(name) {
239
- var arr = name.split("-");
240
- if (arr.length !== 2) return;
241
- var platform2 = arr[0];
242
- var architectures = arr[1].split("+");
243
- if (!platform2) return;
244
- if (!architectures.length) return;
245
- if (!architectures.every(Boolean)) return;
246
- return { name, platform: platform2, architectures };
247
- }
248
- function matchTuple(platform2, arch2) {
249
- return function(tuple) {
250
- if (tuple == null) return false;
251
- if (tuple.platform !== platform2) return false;
252
- return tuple.architectures.includes(arch2);
253
- };
254
- }
255
- function compareTuples(a, b) {
256
- return a.architectures.length - b.architectures.length;
257
- }
258
- function parseTags(file) {
259
- var arr = file.split(".");
260
- var extension = arr.pop();
261
- var tags = { file, specificity: 0 };
262
- if (extension !== "node") return;
263
- for (var i = 0; i < arr.length; i++) {
264
- var tag = arr[i];
265
- if (tag === "node" || tag === "electron" || tag === "node-webkit") {
266
- tags.runtime = tag;
267
- } else if (tag === "napi") {
268
- tags.napi = true;
269
- } else if (tag.slice(0, 3) === "abi") {
270
- tags.abi = tag.slice(3);
271
- } else if (tag.slice(0, 2) === "uv") {
272
- tags.uv = tag.slice(2);
273
- } else if (tag.slice(0, 4) === "armv") {
274
- tags.armv = tag.slice(4);
275
- } else if (tag === "glibc" || tag === "musl") {
276
- tags.libc = tag;
277
- } else {
278
- continue;
279
- }
280
- tags.specificity++;
281
- }
282
- return tags;
283
- }
284
- function matchTags(runtime2, abi2) {
285
- return function(tags) {
286
- if (tags == null) return false;
287
- if (tags.runtime && tags.runtime !== runtime2 && !runtimeAgnostic(tags)) return false;
288
- if (tags.abi && tags.abi !== abi2 && !tags.napi) return false;
289
- if (tags.uv && tags.uv !== uv) return false;
290
- if (tags.armv && tags.armv !== armv) return false;
291
- if (tags.libc && tags.libc !== libc) return false;
292
- return true;
293
- };
294
- }
295
- function runtimeAgnostic(tags) {
296
- return tags.runtime === "node" && tags.napi;
297
- }
298
- function compareTags(runtime2) {
299
- return function(a, b) {
300
- if (a.runtime !== b.runtime) {
301
- return a.runtime === runtime2 ? -1 : 1;
302
- } else if (a.abi !== b.abi) {
303
- return a.abi ? -1 : 1;
304
- } else if (a.specificity !== b.specificity) {
305
- return a.specificity > b.specificity ? -1 : 1;
306
- } else {
307
- return 0;
308
- }
309
- };
310
- }
311
- function isNwjs() {
312
- return !!(process.versions && process.versions.nw);
313
- }
314
- function isElectron() {
315
- if (process.versions && process.versions.electron) return true;
316
- if (process.env.ELECTRON_RUN_AS_NODE) return true;
317
- return typeof window !== "undefined" && window.process && window.process.type === "renderer";
318
- }
319
- function isAlpine(platform2) {
320
- return platform2 === "linux" && fs.existsSync("/etc/alpine-release");
321
- }
322
- load.parseTags = parseTags;
323
- load.matchTags = matchTags;
324
- load.compareTags = compareTags;
325
- load.parseTuple = parseTuple;
326
- load.matchTuple = matchTuple;
327
- load.compareTuples = compareTuples;
328
- }
329
- });
330
-
331
- // node_modules/node-gyp-build/index.js
332
- var require_node_gyp_build2 = __commonJS({
333
- "node_modules/node-gyp-build/index.js"(exports2, module2) {
334
- var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : require;
335
- if (typeof runtimeRequire.addon === "function") {
336
- module2.exports = runtimeRequire.addon.bind(runtimeRequire);
337
- } else {
338
- module2.exports = require_node_gyp_build();
339
- }
340
- }
341
- });
342
-
343
- // node_modules/argon2/argon2.cjs
344
- var require_argon2 = __commonJS({
345
- "node_modules/argon2/argon2.cjs"(exports2, module2) {
346
- var { randomBytes, timingSafeEqual } = require("node:crypto");
347
- var { promisify } = require("node:util");
348
- var { deserialize, serialize } = require_format();
349
- var gypBuild = require_node_gyp_build2();
350
- var { hash: bindingsHash } = gypBuild(__dirname);
351
- var generateSalt = promisify(randomBytes);
352
- var argon2d = 0;
353
- var argon2i = 1;
354
- var argon2id = 2;
355
- module2.exports.argon2d = argon2d;
356
- module2.exports.argon2i = argon2i;
357
- module2.exports.argon2id = argon2id;
358
- var types = Object.freeze({ argon2d, argon2i, argon2id });
359
- var names = Object.freeze({
360
- [types.argon2d]: "argon2d",
361
- [types.argon2i]: "argon2i",
362
- [types.argon2id]: "argon2id"
363
- });
364
- var defaults = {
365
- hashLength: 32,
366
- timeCost: 3,
367
- memoryCost: 1 << 16,
368
- parallelism: 4,
369
- type: argon2id,
370
- version: 19
371
- };
372
- async function hash(password, options) {
373
- let { raw, salt, ...rest } = { ...defaults, ...options };
374
- if (rest.hashLength > 2 ** 32 - 1) {
375
- throw new RangeError("Hash length is too large");
376
- }
377
- if (rest.memoryCost > 2 ** 32 - 1) {
378
- throw new RangeError("Memory cost is too large");
379
- }
380
- if (rest.timeCost > 2 ** 32 - 1) {
381
- throw new RangeError("Time cost is too large");
382
- }
383
- if (rest.parallelism > 2 ** 24 - 1) {
384
- throw new RangeError("Parallelism is too large");
385
- }
386
- salt = salt ?? await generateSalt(16);
387
- const {
388
- hashLength,
389
- secret = Buffer.alloc(0),
390
- type,
391
- version,
392
- memoryCost: m,
393
- timeCost: t,
394
- parallelism: p,
395
- associatedData: data = Buffer.alloc(0)
396
- } = rest;
397
- const hash2 = await bindingsHash({
398
- password: Buffer.from(password),
399
- salt,
400
- secret,
401
- data,
402
- hashLength,
403
- m,
404
- t,
405
- p,
406
- version,
407
- type
408
- });
409
- if (raw) {
410
- return hash2;
411
- }
412
- return serialize({
413
- id: names[type],
414
- version,
415
- params: { m, t, p, ...data.byteLength > 0 ? { data } : {} },
416
- salt,
417
- hash: hash2
418
- });
419
- }
420
- module2.exports.hash = hash;
421
- function needsRehash(digest, options = {}) {
422
- const { memoryCost, timeCost, parallelism, version } = {
423
- ...defaults,
424
- ...options
425
- };
426
- const {
427
- version: v,
428
- params: { m, t, p }
429
- } = deserialize(digest);
430
- return +v !== +version || +m !== +memoryCost || +t !== +timeCost || +p !== +parallelism;
431
- }
432
- module2.exports.needsRehash = needsRehash;
433
- async function verify(digest, password, options = {}) {
434
- const { id, ...rest } = deserialize(digest);
435
- if (!(id in types)) {
436
- return false;
437
- }
438
- const {
439
- version = 16,
440
- params: { m, t, p, data = "" },
441
- salt,
442
- hash: hash2
443
- } = rest;
444
- const { secret = Buffer.alloc(0) } = options;
445
- return timingSafeEqual(
446
- await bindingsHash({
447
- password: Buffer.from(password),
448
- salt,
449
- secret,
450
- data: Buffer.from(data, "base64"),
451
- hashLength: hash2.byteLength,
452
- m: +m,
453
- t: +t,
454
- p: +p,
455
- version: +version,
456
- type: types[id]
457
- }),
458
- hash2
459
- );
460
- }
461
- module2.exports.verify = verify;
462
- }
463
- });
464
-
465
- // _bundle-argon2.cjs
466
- module.exports = require_argon2();
@@ -1,62 +0,0 @@
1
- export type Options = {
2
- hashLength?: number | undefined;
3
- timeCost?: number | undefined;
4
- memoryCost?: number | undefined;
5
- parallelism?: number | undefined;
6
- type?: 0 | 1 | 2 | undefined;
7
- version?: number | undefined;
8
- salt?: Buffer | undefined;
9
- associatedData?: Buffer | undefined;
10
- secret?: Buffer | undefined;
11
- };
12
- export const argon2d: 0;
13
- export const argon2i: 1;
14
- export const argon2id: 2;
15
- /**
16
- * Hashes a password with Argon2, producing a raw hash
17
- *
18
- * @overload
19
- * @param {Buffer | string} password The plaintext password to be hashed
20
- * @param {Options & { raw: true }} options The parameters for Argon2
21
- * @returns {Promise<Buffer>} The raw hash generated from `password`
22
- */
23
- export function hash(password: Buffer | string, options: Options & {
24
- raw: true;
25
- }): Promise<Buffer>;
26
- /**
27
- * Hashes a password with Argon2, producing an encoded hash
28
- *
29
- * @overload
30
- * @param {Buffer | string} password The plaintext password to be hashed
31
- * @param {Options & { raw?: boolean }} [options] The parameters for Argon2
32
- * @returns {Promise<string>} The encoded hash generated from `password`
33
- */
34
- export function hash(password: Buffer | string, options?: (Options & {
35
- raw?: boolean;
36
- }) | undefined): Promise<string>;
37
- /**
38
- * @param {string} digest The digest to be checked
39
- * @param {Object} [options] The current parameters for Argon2
40
- * @param {number} [options.timeCost=3]
41
- * @param {number} [options.memoryCost=65536]
42
- * @param {number} [options.parallelism=4]
43
- * @param {number} [options.version=0x13]
44
- * @returns {boolean} `true` if the digest parameters do not match the parameters in `options`, otherwise `false`
45
- */
46
- export function needsRehash(digest: string, options?: {
47
- timeCost?: number | undefined;
48
- memoryCost?: number | undefined;
49
- parallelism?: number | undefined;
50
- version?: number | undefined;
51
- } | undefined): boolean;
52
- /**
53
- * @param {string} digest The digest to be checked
54
- * @param {Buffer | string} password The plaintext password to be verified
55
- * @param {Object} [options] The current parameters for Argon2
56
- * @param {Buffer} [options.secret]
57
- * @returns {Promise<boolean>} `true` if the digest parameters matches the hash generated from `password`, otherwise `false`
58
- */
59
- export function verify(digest: string, password: Buffer | string, options?: {
60
- secret?: Buffer | undefined;
61
- } | undefined): Promise<boolean>;
62
- //# sourceMappingURL=argon2.d.cts.map
@@ -1 +0,0 @@
1
- {"name":"argon2","version":"0.44.0","main":"argon2.cjs"}