@fedify/fedify 1.4.14 → 1.4.16

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/CHANGES.md CHANGED
@@ -3,6 +3,30 @@
3
3
  Fedify changelog
4
4
  ================
5
5
 
6
+ Version 1.4.16
7
+ --------------
8
+
9
+ Released on September 17, 2025.
10
+
11
+ - Added a temporary workaround for invalid AT Protocol URIs from BridgyFed.
12
+ URIs like `at://did:plc:...` that violate RFC 3986 URI syntax are now
13
+ automatically URL-encoded to `at://did%3Aplc%3A...` to prevent parsing
14
+ failures when processing bridged Bluesky content. [[#436]]
15
+
16
+
17
+ Version 1.4.15
18
+ --------------
19
+
20
+ Released on August 25, 2025.
21
+
22
+ - Fixed a bug where `verifyRequest()` function threw a `TypeError` when
23
+ verifying HTTP Signatures with `created` or `expires` fields in
24
+ the `Signature` header as defined in draft-cavage-http-signatures-12,
25
+ causing `500 Internal Server Error` responses in inbox handlers.
26
+ Now it correctly handles these fields as unquoted integers according
27
+ to the specification.
28
+
29
+
6
30
  Version 1.4.14
7
31
  --------------
8
32
 
@@ -276,6 +300,30 @@ Released on February 5, 2025.
276
300
  [#195]: https://github.com/fedify-dev/fedify/issues/195
277
301
 
278
302
 
303
+ Version 1.3.23
304
+ --------------
305
+
306
+ Released on September 17, 2025.
307
+
308
+ - Added a temporary workaround for invalid AT Protocol URIs from BridgyFed.
309
+ URIs like `at://did:plc:...` that violate RFC 3986 URI syntax are now
310
+ automatically URL-encoded to `at://did%3Aplc%3A...` to prevent parsing
311
+ failures when processing bridged Bluesky content. [[#436]]
312
+
313
+
314
+ Version 1.3.22
315
+ --------------
316
+
317
+ Released on August 25, 2025.
318
+
319
+ - Fixed a bug where `verifyRequest()` function threw a `TypeError` when
320
+ verifying HTTP Signatures with `created` or `expires` fields in
321
+ the `Signature` header as defined in draft-cavage-http-signatures-12,
322
+ causing `500 Internal Server Error` responses in inbox handlers.
323
+ Now it correctly handles these fields as unquoted integers according
324
+ to the specification.
325
+
326
+
279
327
  Version 1.3.21
280
328
  --------------
281
329
 
@@ -667,6 +715,30 @@ Released on November 30, 2024.
667
715
  [#193]: https://github.com/fedify-dev/fedify/issues/193
668
716
 
669
717
 
718
+ Version 1.2.26
719
+ --------------
720
+
721
+ Released on September 17, 2025.
722
+
723
+ - Added a temporary workaround for invalid AT Protocol URIs from BridgyFed.
724
+ URIs like `at://did:plc:...` that violate RFC 3986 URI syntax are now
725
+ automatically URL-encoded to `at://did%3Aplc%3A...` to prevent parsing
726
+ failures when processing bridged Bluesky content. [[#436]]
727
+
728
+
729
+ Version 1.2.25
730
+ --------------
731
+
732
+ Released on August 25, 2025.
733
+
734
+ - Fixed a bug where `verifyRequest()` function threw a `TypeError` when
735
+ verifying HTTP Signatures with `created` or `expires` fields in
736
+ the `Signature` header as defined in draft-cavage-http-signatures-12,
737
+ causing `500 Internal Server Error` responses in inbox handlers.
738
+ Now it correctly handles these fields as unquoted integers according
739
+ to the specification.
740
+
741
+
670
742
  Version 1.2.24
671
743
  --------------
672
744
 
@@ -1091,6 +1163,30 @@ Released on October 31, 2024.
1091
1163
  [#118]: https://github.com/fedify-dev/fedify/issues/118
1092
1164
 
1093
1165
 
1166
+ Version 1.1.26
1167
+ --------------
1168
+
1169
+ Released on September 17, 2025.
1170
+
1171
+ - Added a temporary workaround for invalid AT Protocol URIs from BridgyFed.
1172
+ URIs like `at://did:plc:...` that violate RFC 3986 URI syntax are now
1173
+ automatically URL-encoded to `at://did%3Aplc%3A...` to prevent parsing
1174
+ failures when processing bridged Bluesky content. [[#436]]
1175
+
1176
+
1177
+ Version 1.1.25
1178
+ --------------
1179
+
1180
+ Released on August 25, 2025.
1181
+
1182
+ - Fixed a bug where `verifyRequest()` function threw a `TypeError` when
1183
+ verifying HTTP Signatures with `created` or `expires` fields in
1184
+ the `Signature` header as defined in draft-cavage-http-signatures-12,
1185
+ causing `500 Internal Server Error` responses in inbox handlers.
1186
+ Now it correctly handles these fields as unquoted integers according
1187
+ to the specification.
1188
+
1189
+
1094
1190
  Version 1.1.24
1095
1191
  --------------
1096
1192
 
@@ -1556,6 +1652,32 @@ Released on October 20, 2024.
1556
1652
  [#150]: https://github.com/fedify-dev/fedify/issues/150
1557
1653
 
1558
1654
 
1655
+ Version 1.0.29
1656
+ --------------
1657
+
1658
+ Released on September 17, 2025.
1659
+
1660
+ - Added a temporary workaround for invalid AT Protocol URIs from BridgyFed.
1661
+ URIs like `at://did:plc:...` that violate RFC 3986 URI syntax are now
1662
+ automatically URL-encoded to `at://did%3Aplc%3A...` to prevent parsing
1663
+ failures when processing bridged Bluesky content. [[#436]]
1664
+
1665
+ [#436]: https://github.com/fedify-dev/fedify/issues/436
1666
+
1667
+
1668
+ Version 1.0.28
1669
+ --------------
1670
+
1671
+ Released on August 25, 2025.
1672
+
1673
+ - Fixed a bug where `verifyRequest()` function threw a `TypeError` when
1674
+ verifying HTTP Signatures with `created` or `expires` fields in
1675
+ the `Signature` header as defined in draft-cavage-http-signatures-12,
1676
+ causing `500 Internal Server Error` responses in inbox handlers.
1677
+ Now it correctly handles these fields as unquoted integers according
1678
+ to the specification.
1679
+
1680
+
1559
1681
  Version 1.0.27
1560
1682
  --------------
1561
1683
 
package/esm/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "@fedify/fedify",
3
- "version": "1.4.14",
3
+ "version": "1.4.16",
4
4
  "license": "MIT",
5
5
  "exports": {
6
6
  ".": "./mod.ts",
package/esm/sig/http.js CHANGED
@@ -221,7 +221,7 @@ async function verifyRequestInternal(request, span, { documentLoader, contextLoa
221
221
  return null;
222
222
  }
223
223
  }
224
- const sigValues = Object.fromEntries(sigHeader.split(",").map((pair) => pair.match(/^\s*([A-Za-z]+)="([^"]*)"\s*$/)).filter((m) => m != null).map((m) => m.slice(1, 3)));
224
+ const sigValues = Object.fromEntries(sigHeader.split(",").map((pair) => pair.match(/^\s*([A-Za-z]+)=(?:"([^"]*)"|(\d+))\s*$/)).filter((m) => m != null).map((m) => [m[1], m[2] ?? m[3]]));
225
225
  if (!("keyId" in sigValues)) {
226
226
  logger.debug("Failed to verify; no keyId field found in the Signature header.", { signature: sigHeader });
227
227
  return null;
@@ -234,6 +234,41 @@ async function verifyRequestInternal(request, span, { documentLoader, contextLoa
234
234
  logger.debug("Failed to verify; no signature field found in the Signature header.", { signature: sigHeader });
235
235
  return null;
236
236
  }
237
+ if ("expires" in sigValues) {
238
+ const expiresSeconds = parseInt(sigValues.expires);
239
+ if (!Number.isInteger(expiresSeconds)) {
240
+ logger.debug("Failed to verify; invalid expires field in the Signature header: {expires}.", { expires: sigValues.expires, signature: sigHeader });
241
+ return null;
242
+ }
243
+ const expires = dntShim.Temporal.Instant.fromEpochMilliseconds(expiresSeconds * 1000);
244
+ if (dntShim.Temporal.Instant.compare(now, expires) > 0) {
245
+ logger.debug("Failed to verify; signature expired at {expires} (now: {now}).", {
246
+ expires: expires.toString(),
247
+ now: now.toString(),
248
+ signature: sigHeader,
249
+ });
250
+ return null;
251
+ }
252
+ }
253
+ if ("created" in sigValues) {
254
+ const createdSeconds = parseInt(sigValues.created);
255
+ if (!Number.isInteger(createdSeconds)) {
256
+ logger.debug("Failed to verify; invalid created field in the Signature header: {created}.", { created: sigValues.created, signature: sigHeader });
257
+ return null;
258
+ }
259
+ if (timeWindow !== false) {
260
+ const created = dntShim.Temporal.Instant.fromEpochMilliseconds(createdSeconds * 1000);
261
+ const tw = timeWindow ?? { minutes: 1 };
262
+ if (dntShim.Temporal.Instant.compare(created, now.add(tw)) > 0) {
263
+ logger.debug("Failed to verify; created is too far in the future.", { created: created.toString(), now: now.toString() });
264
+ return null;
265
+ }
266
+ else if (dntShim.Temporal.Instant.compare(created, now.subtract(tw)) < 0) {
267
+ logger.debug("Failed to verify; created is too far in the past.", { created: created.toString(), now: now.toString() });
268
+ return null;
269
+ }
270
+ }
271
+ }
237
272
  const { keyId, headers, signature } = sigValues;
238
273
  span?.setAttribute("http_signatures.key_id", keyId);
239
274
  if ("algorithm" in sigValues) {
@@ -259,11 +294,15 @@ async function verifyRequestInternal(request, span, { documentLoader, contextLoa
259
294
  return null;
260
295
  }
261
296
  const message = headerNames.map((name) => `${name}: ` +
262
- (name == "(request-target)"
297
+ (name === "(request-target)"
263
298
  ? `${request.method.toLowerCase()} ${new URL(request.url).pathname}`
264
- : name == "host"
265
- ? request.headers.get("host") ?? new URL(request.url).host
266
- : request.headers.get(name))).join("\n");
299
+ : name === "(created)"
300
+ ? (sigValues.created ?? "")
301
+ : name === "(expires)"
302
+ ? (sigValues.expires ?? "")
303
+ : name === "host"
304
+ ? request.headers.get("host") ?? new URL(request.url).host
305
+ : request.headers.get(name))).join("\n");
267
306
  const sig = decodeBase64(signature);
268
307
  span?.setAttribute("http_signatures.signature", encodeHex(sig));
269
308
  // TODO: support other than RSASSA-PKCS1-v1_5:
@@ -0,0 +1,24 @@
1
+ {
2
+ "@context": [
3
+ "https://www.w3.org/ns/activitystreams",
4
+ "https://w3id.org/security/v1"
5
+ ],
6
+ "id": "https://oeee.cafe/ap/users/3609fd4e-d51d-4db8-9f04-4189815864dd",
7
+ "type": "Person",
8
+ "preferredUsername": "hongminhee",
9
+ "name": "洪兔",
10
+ "inbox": "https://oeee.cafe/ap/users/3609fd4e-d51d-4db8-9f04-4189815864dd/inbox",
11
+ "outbox": "https://oeee.cafe/ap/users/3609fd4e-d51d-4db8-9f04-4189815864dd/outbox",
12
+ "publicKey": {
13
+ "id": "https://oeee.cafe/ap/users/3609fd4e-d51d-4db8-9f04-4189815864dd#main-key",
14
+ "owner": "https://oeee.cafe/ap/users/3609fd4e-d51d-4db8-9f04-4189815864dd",
15
+ "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAowJfOzpA/nAYyL0bVDTm\niCAOlhFCIBnqwk1jvGrbkDhMzxlsgyoDqUSlmcJdKaPwu24YdFajDtJIgto27Ju7\nIC3hB7OFchnZ4JZrdYFo7CJABOzK58o12sdmmkCdY5hXWf1604E+mzyIdBAJ1FFJ\nL8vP07VEUsZ7yo9x0iVNg7HpCOK+y6BqI2GHS2dq9qkqQEIhC2TKHXn/RQVXwYB6\nG+YQmVUtcsbCVKdcWyTKhItLRGnepu3BqBSbieLxV27B1O9NFSoPu8xiBUnYwMoe\nsUQCE5tGcqxc75HzcVCbq7PqVqHZ1NW9RYssaSUqi4FYcjXxQrR08DrAl8rR4eXT\n4QIDAQAB\n-----END PUBLIC KEY-----\n"
16
+ },
17
+ "endpoints": {
18
+ "type": "as:Endpoints",
19
+ "sharedInbox": "https://oeee.cafe/inbox"
20
+ },
21
+ "followers": "https://oeee.cafe/ap/users/3609fd4e-d51d-4db8-9f04-4189815864dd/followers",
22
+ "manuallyApprovesFollowers": false,
23
+ "url": "https://oeee.cafe/@hongminhee"
24
+ }