@fedify/fedify 1.5.6 → 1.5.7

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,19 @@
3
3
  Fedify changelog
4
4
  ================
5
5
 
6
+ Version 1.5.7
7
+ -------------
8
+
9
+ Released on August 25, 2025.
10
+
11
+ - Fixed a bug where `verifyRequest()` function threw a `TypeError` when
12
+ verifying HTTP Signatures with `created` or `expires` fields in
13
+ the `Signature` header as defined in draft-cavage-http-signatures-12,
14
+ causing `500 Internal Server Error` responses in inbox handlers.
15
+ Now it correctly handles these fields as unquoted integers according
16
+ to the specification.
17
+
18
+
6
19
  Version 1.5.6
7
20
  -------------
8
21
 
@@ -201,6 +214,19 @@ Released on March 28, 2025.
201
214
  [multibase]: https://github.com/multiformats/js-multibase
202
215
 
203
216
 
217
+ Version 1.4.15
218
+ --------------
219
+
220
+ Released on August 25, 2025.
221
+
222
+ - Fixed a bug where `verifyRequest()` function threw a `TypeError` when
223
+ verifying HTTP Signatures with `created` or `expires` fields in
224
+ the `Signature` header as defined in draft-cavage-http-signatures-12,
225
+ causing `500 Internal Server Error` responses in inbox handlers.
226
+ Now it correctly handles these fields as unquoted integers according
227
+ to the specification.
228
+
229
+
204
230
  Version 1.4.14
205
231
  --------------
206
232
 
@@ -474,6 +500,19 @@ Released on February 5, 2025.
474
500
  [#195]: https://github.com/fedify-dev/fedify/issues/195
475
501
 
476
502
 
503
+ Version 1.3.22
504
+ --------------
505
+
506
+ Released on August 25, 2025.
507
+
508
+ - Fixed a bug where `verifyRequest()` function threw a `TypeError` when
509
+ verifying HTTP Signatures with `created` or `expires` fields in
510
+ the `Signature` header as defined in draft-cavage-http-signatures-12,
511
+ causing `500 Internal Server Error` responses in inbox handlers.
512
+ Now it correctly handles these fields as unquoted integers according
513
+ to the specification.
514
+
515
+
477
516
  Version 1.3.21
478
517
  --------------
479
518
 
@@ -865,6 +904,19 @@ Released on November 30, 2024.
865
904
  [#193]: https://github.com/fedify-dev/fedify/issues/193
866
905
 
867
906
 
907
+ Version 1.2.25
908
+ --------------
909
+
910
+ Released on August 25, 2025.
911
+
912
+ - Fixed a bug where `verifyRequest()` function threw a `TypeError` when
913
+ verifying HTTP Signatures with `created` or `expires` fields in
914
+ the `Signature` header as defined in draft-cavage-http-signatures-12,
915
+ causing `500 Internal Server Error` responses in inbox handlers.
916
+ Now it correctly handles these fields as unquoted integers according
917
+ to the specification.
918
+
919
+
868
920
  Version 1.2.24
869
921
  --------------
870
922
 
@@ -1289,6 +1341,19 @@ Released on October 31, 2024.
1289
1341
  [#118]: https://github.com/fedify-dev/fedify/issues/118
1290
1342
 
1291
1343
 
1344
+ Version 1.1.25
1345
+ --------------
1346
+
1347
+ Released on August 25, 2025.
1348
+
1349
+ - Fixed a bug where `verifyRequest()` function threw a `TypeError` when
1350
+ verifying HTTP Signatures with `created` or `expires` fields in
1351
+ the `Signature` header as defined in draft-cavage-http-signatures-12,
1352
+ causing `500 Internal Server Error` responses in inbox handlers.
1353
+ Now it correctly handles these fields as unquoted integers according
1354
+ to the specification.
1355
+
1356
+
1292
1357
  Version 1.1.24
1293
1358
  --------------
1294
1359
 
@@ -1754,6 +1819,19 @@ Released on October 20, 2024.
1754
1819
  [#150]: https://github.com/fedify-dev/fedify/issues/150
1755
1820
 
1756
1821
 
1822
+ Version 1.0.28
1823
+ --------------
1824
+
1825
+ Released on August 25, 2025.
1826
+
1827
+ - Fixed a bug where `verifyRequest()` function threw a `TypeError` when
1828
+ verifying HTTP Signatures with `created` or `expires` fields in
1829
+ the `Signature` header as defined in draft-cavage-http-signatures-12,
1830
+ causing `500 Internal Server Error` responses in inbox handlers.
1831
+ Now it correctly handles these fields as unquoted integers according
1832
+ to the specification.
1833
+
1834
+
1757
1835
  Version 1.0.27
1758
1836
  --------------
1759
1837
 
package/esm/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "@fedify/fedify",
3
- "version": "1.5.6",
3
+ "version": "1.5.7",
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
+ }