@blamejs/core 0.5.4 → 0.5.5

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,7 @@ upgrading across more than a few patches at a time.
8
8
 
9
9
  ## v0.5.x
10
10
 
11
+ - **0.5.4** (2026-04-30) — close SSRF DNS-rebinding window with pinned outbound DNS
11
12
  - **0.5.3** (2026-04-30) — security cleanup: trustProxy primitive + Vary merge + HSTS gate
12
13
  - **0.5.2** (2026-04-30) — b.breakGlass: passkey factor + service-account bypass + admin tools
13
14
  - **0.5.1** (2026-04-30) — b.breakGlass: per-cell encryption + context binding + migrate
@@ -46,10 +46,16 @@ var DEFAULT_PERMISSIONS = [
46
46
  "screen-wake-lock=()", "sync-xhr=()", "usb=()", "web-share=()", "xr-spatial-tracking=()",
47
47
  ];
48
48
 
49
+ // Strict CSP — no 'unsafe-inline' on script-src OR style-src. Operators
50
+ // with inline styles / scripts wire `b.middleware.cspNonce()` and use
51
+ // `{{ cspNonce }}` in their views (or req.cspNonce in handlers); the
52
+ // nonce hooks into the policy via the `csp` opt or a custom value.
53
+ // Operators in transitional environments who genuinely need inline
54
+ // styles set `csp` explicitly to the loose form.
49
55
  var DEFAULT_CSP =
50
56
  "default-src 'self'; " +
51
57
  "script-src 'self'; " +
52
- "style-src 'self' 'unsafe-inline'; " +
58
+ "style-src 'self'; " +
53
59
  "img-src 'self' data:; " +
54
60
  "font-src 'self'; " +
55
61
  "connect-src 'self'; " +
package/lib/ssrf-guard.js CHANGED
@@ -94,6 +94,23 @@ var IPV6_PRIVATE_PREFIX = _ipv6ToBytes("fc00::");
94
94
  var IPV6_LINK_LOCAL_PREFIX = _ipv6ToBytes("fe80::");
95
95
  var IPV6_DOC_PREFIX = _ipv6ToBytes("2001:db8::"); // documentation
96
96
  var IPV6_V4_MAPPED_PREFIX = _ipv6ToBytes("::ffff:0:0"); // IPv4-mapped (::ffff:0:0/96)
97
+ // Multicast ff00::/8 — RFC 4291 §2.7. Refused for outbound HTTP same as
98
+ // IPv4 multicast 224/4 — there's no legitimate fetch from a multicast
99
+ // destination on a production gateway.
100
+ var IPV6_MULTICAST_PREFIX = _ipv6ToBytes("ff00::");
101
+ // NAT64 well-known prefix 64:ff9b::/96 — RFC 6052. Translates to IPv4
102
+ // embedded in the lower 32 bits; the framework refuses since the
103
+ // underlying v4 address is what gets contacted and might be private.
104
+ // (Operators with NAT64 deployments flip allowInternal.)
105
+ var IPV6_NAT64_PREFIX = _ipv6ToBytes("64:ff9b::");
106
+ // 6to4 2002::/16 — RFC 3056. Carries an embedded IPv4 in bytes 2-5;
107
+ // hostile use is to tunnel through to a v4 destination the v4 guard
108
+ // would have refused. Refused.
109
+ var IPV6_6TO4_PREFIX = _ipv6ToBytes("2002::");
110
+ // Discard prefix 100::/64 — RFC 6666. Dropped by routers; fetching
111
+ // from it is operationally meaningless and a likely sign of mis-config
112
+ // or attempted exfil to a sinkhole.
113
+ var IPV6_DISCARD_PREFIX = _ipv6ToBytes("100::");
97
114
 
98
115
  // ---- Cloud metadata addresses (string-equality, exact match) ----
99
116
  var CLOUD_METADATA_IPS = [
@@ -235,6 +252,20 @@ function classify(ip) {
235
252
  if (_ipv6PrefixMatch(IPV6_LINK_LOCAL_PREFIX, 10, bytes)) return "link-local";
236
253
  if (_ipv6PrefixMatch(IPV6_PRIVATE_PREFIX, 7, bytes)) return "private";
237
254
  if (_ipv6PrefixMatch(IPV6_DOC_PREFIX, 32, bytes)) return "reserved";
255
+ if (_ipv6PrefixMatch(IPV6_MULTICAST_PREFIX, 8, bytes)) return "reserved";
256
+ if (_ipv6PrefixMatch(IPV6_DISCARD_PREFIX, 64, bytes)) return "reserved";
257
+ // 6to4 (2002::/16) embeds a v4 address in bytes 2–5; classify the
258
+ // embedded v4 so a 6to4-wrapped private/metadata address is refused
259
+ // for the same reason its v4 form would be.
260
+ if (_ipv6PrefixMatch(IPV6_6TO4_PREFIX, 16, bytes)) {
261
+ var v4From6to4 = bytes[2] + "." + bytes[3] + "." + bytes[4] + "." + bytes[5];
262
+ return classify(v4From6to4) || "reserved";
263
+ }
264
+ // NAT64 well-known prefix (64:ff9b::/96) embeds v4 in bytes 12–15.
265
+ if (_ipv6PrefixMatch(IPV6_NAT64_PREFIX, 96, bytes)) {
266
+ var v4FromNat64 = bytes[12] + "." + bytes[13] + "." + bytes[14] + "." + bytes[15];
267
+ return classify(v4FromNat64) || "reserved";
268
+ }
238
269
  // IPv4-mapped addresses (::ffff:a.b.c.d/96): re-classify the v4 portion.
239
270
  if (_ipv6PrefixMatch(IPV6_V4_MAPPED_PREFIX, 96, bytes)) {
240
271
  var mappedV4 = bytes[12] + "." + bytes[13] + "." + bytes[14] + "." + bytes[15];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/core",
3
- "version": "0.5.4",
3
+ "version": "0.5.5",
4
4
  "description": "The Node framework that owns its stack.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "blamejs contributors",