@oxyhq/core 3.9.1 → 3.10.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.
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ /**
3
+ * Constant-time secret comparison for Oxy backends.
4
+ *
5
+ * WHY THIS EXISTS
6
+ * ---------------
7
+ * Backends kept comparing secrets with `provided !== EXPECTED`. A plain `===`/
8
+ * `!==` short-circuits on the first differing byte, leaking timing information
9
+ * an attacker can use to recover a secret byte-by-byte. This helper performs a
10
+ * constant-time comparison via `crypto.timingSafeEqual`, guarded by a length
11
+ * check, and never throws — replacing the `token !== SECRET` pattern (Alia
12
+ * docker-host / integrations webhook secrets, internal webhook bearers, etc.).
13
+ *
14
+ * Node-only (`node:crypto`); exported solely from `@oxyhq/core/server`.
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.verifySecret = verifySecret;
18
+ const node_crypto_1 = require("node:crypto");
19
+ const node_buffer_1 = require("node:buffer");
20
+ /**
21
+ * Compare two secrets in constant time.
22
+ *
23
+ * Returns `true` iff both are non-empty strings of equal byte length with
24
+ * identical contents. Returns `false` — without throwing — when either value is
25
+ * not a string, when lengths differ, or when contents differ.
26
+ *
27
+ * The length-equality guard is required because `crypto.timingSafeEqual` throws
28
+ * on unequal-length buffers; comparing lengths first leaks only the LENGTH of
29
+ * the expected secret (already low-value / often public), never its bytes.
30
+ *
31
+ * @param provided - The untrusted, caller-supplied value (e.g. a request token).
32
+ * @param expected - The trusted secret to compare against.
33
+ */
34
+ function verifySecret(provided, expected) {
35
+ if (typeof provided !== 'string' || typeof expected !== 'string') {
36
+ return false;
37
+ }
38
+ if (provided.length === 0 || expected.length === 0) {
39
+ return false;
40
+ }
41
+ const providedBuf = node_buffer_1.Buffer.from(provided, 'utf8');
42
+ const expectedBuf = node_buffer_1.Buffer.from(expected, 'utf8');
43
+ // timingSafeEqual requires equal byte length. A mismatch here is itself a
44
+ // (length-only) early return — acceptable, since the secret's length is not
45
+ // the sensitive part; its bytes are, and those are compared in constant time.
46
+ if (providedBuf.length !== expectedBuf.length) {
47
+ return false;
48
+ }
49
+ return (0, node_crypto_1.timingSafeEqual)(providedBuf, expectedBuf);
50
+ }