@blamejs/core 0.14.21 → 0.14.24

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.
@@ -34,18 +34,10 @@
34
34
  */
35
35
 
36
36
  var problemDetails = require("../problem-details");
37
+ var validateOpts = require("../validate-opts");
37
38
 
38
39
  function _isFn(x) { return typeof x === "function"; }
39
40
 
40
- function _mergeInto(target, extra) {
41
- if (!extra || typeof extra !== "object") return target;
42
- var keys = Object.keys(extra);
43
- for (var i = 0; i < keys.length; i += 1) {
44
- target[keys[i]] = extra[keys[i]];
45
- }
46
- return target;
47
- }
48
-
49
41
  /**
50
42
  * Resolve a deny-path refusal through the uniform hook / problem+json
51
43
  * / default chain. Returns whatever the `onDeny` hook returns when it
@@ -144,7 +136,7 @@ function denyResponse(req, res, ctx) {
144
136
  return undefined;
145
137
  }
146
138
 
147
- var head = _mergeInto({ "Content-Type": ctx.contentType }, extra);
139
+ var head = validateOpts.assignOwnEnumerable({ "Content-Type": ctx.contentType }, extra);
148
140
  var denyOut = (ctx.body === undefined || ctx.body === null) ? ""
149
141
  : (typeof ctx.body === "string" ? ctx.body : JSON.stringify(ctx.body));
150
142
  if (ctx.body !== undefined && ctx.body !== null && req && typeof req.apiEncryptEncode === "function") {
@@ -317,10 +317,7 @@ function create(opts) {
317
317
  var entry = { ok: r.ok, ms: r.ms };
318
318
  if (r.detail) {
319
319
  // Merge detail keys other than `ok` into the entry.
320
- var keys = Object.keys(r.detail);
321
- for (var n = 0; n < keys.length; n++) {
322
- if (keys[n] !== "ok") entry[keys[n]] = r.detail[keys[n]];
323
- }
320
+ validateOpts.assignOwnEnumerable(entry, r.detail, ["ok"]);
324
321
  }
325
322
  if (r.error) entry.error = r.error;
326
323
  if (!r.critical) entry.critical = false;
@@ -52,13 +52,10 @@ function _baggageToObject(entries) {
52
52
 
53
53
  function _wrapLogger(baseLogger, req, opts) {
54
54
  if (!baseLogger || typeof baseLogger !== "object") return baseLogger;
55
- var wrapped = Object.create(null);
56
55
  // Preserve any non-level properties the operator put on the
57
- // logger (e.g. boot context, child-logger metadata).
58
- var keys = Object.keys(baseLogger);
59
- for (var i = 0; i < keys.length; i++) {
60
- if (LOG_LEVELS.indexOf(keys[i]) === -1) wrapped[keys[i]] = baseLogger[keys[i]];
61
- }
56
+ // logger (e.g. boot context, child-logger metadata); the level
57
+ // methods themselves are re-wrapped below.
58
+ var wrapped = validateOpts.assignOwnEnumerable(Object.create(null), baseLogger, LOG_LEVELS);
62
59
 
63
60
  function _enrichMeta(meta) {
64
61
  var enriched = Object.assign({}, meta || {});
@@ -393,6 +393,39 @@ function makeNamespacedEmitters(prefix, deps) {
393
393
  return { audit: audit, metric: metric };
394
394
  }
395
395
 
396
+ // assignOwnEnumerable — copy a source object's own enumerable keys onto a
397
+ // target, skipping the prototype-pollution sentinels (__proto__ /
398
+ // constructor / prototype) and any caller-named reserved keys. Several
399
+ // primitives that merge operator-supplied free-form fields onto a
400
+ // spec-built object (JOSE claim sets, JWS protected headers, attestation
401
+ // extra-claims) previously open-coded the identical
402
+ // `for (k of Object.keys(src)) { if (sentinel) continue; if (reserved)
403
+ // continue; dst[k] = src[k]; }` loop. Centralizing the proto-safe walk
404
+ // keeps the merge contract in one place. Reserved keys win — they are NOT
405
+ // overwritten — so the caller's spec-built fields can never be shadowed by
406
+ // a same-named operator key. Returns the target.
407
+ function assignOwnEnumerable(target, source, reservedKeys) {
408
+ if (!source || typeof source !== "object") return target;
409
+ var reserved = Object.create(null);
410
+ if (reservedKeys) for (var r = 0; r < reservedKeys.length; r += 1) reserved[reservedKeys[r]] = true;
411
+ var keys = Object.keys(source);
412
+ var entries = [];
413
+ for (var i = 0; i < keys.length; i += 1) {
414
+ var k = keys[i];
415
+ if (k === "__proto__" || k === "constructor" || k === "prototype") continue;
416
+ if (reserved[k]) continue;
417
+ entries.push([k, source[k]]);
418
+ }
419
+ // Staged through entries + Object.assign so the copy contains no
420
+ // computed-name property write at all: Object.fromEntries creates own
421
+ // data properties (it cannot walk the prototype chain), and the
422
+ // sentinel skip above means the staging object carries no
423
+ // __proto__/constructor/prototype key for Object.assign's [[Set]] to
424
+ // trip over. Same observable result as a key-by-key copy, with the
425
+ // arbitrary-property-write shape removed instead of merely guarded.
426
+ return Object.assign(target, Object.fromEntries(entries));
427
+ }
428
+
396
429
  // observabilityShape — operator-supplied `opts.observability` must
397
430
  // expose an `event` function. Parallel to auditShape; the n=1 catalog
398
431
  // tracks both inline-shape regexes.
@@ -426,3 +459,4 @@ module.exports.requireMethods = requireMethods;
426
459
  module.exports.applyDefaults = applyDefaults;
427
460
  module.exports.makeAuditEmitter = makeAuditEmitter;
428
461
  module.exports.makeNamespacedEmitters = makeNamespacedEmitters;
462
+ module.exports.assignOwnEnumerable = assignOwnEnumerable;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/core",
3
- "version": "0.14.21",
3
+ "version": "0.14.24",
4
4
  "description": "The Node framework that owns its stack.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "blamejs contributors",
package/sbom.cdx.json CHANGED
@@ -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:37cb0e0e-7cba-440b-89c3-febfeb9f7eef",
5
+ "serialNumber": "urn:uuid:0697fb13-faa3-47c7-8ac0-7a29c980f002",
6
6
  "version": 1,
7
7
  "metadata": {
8
- "timestamp": "2026-06-05T04:48:42.555Z",
8
+ "timestamp": "2026-06-06T15:36:19.660Z",
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.14.21",
22
+ "bom-ref": "@blamejs/core@0.14.24",
23
23
  "type": "application",
24
24
  "name": "blamejs",
25
- "version": "0.14.21",
25
+ "version": "0.14.24",
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.14.21",
29
+ "purl": "pkg:npm/%40blamejs/core@0.14.24",
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.14.21",
57
+ "ref": "@blamejs/core@0.14.24",
58
58
  "dependsOn": []
59
59
  }
60
60
  ]