Skip to content

6.2.0

Latest

Choose a tag to compare

@20syldev 20syldev released this 14 Nov 18:37
6.2.0
9b47ae4

Security release for moxon API: the issues found by an audit of the whole API are fixed, endpoint by endpoint. No endpoint is added or removed.

Security

Legitimate requests get exactly the same responses as before. Only abusive inputs are now refused, with the usual 400 error, or bounded. Two changes are visible:

  • /cron on v5 and v6 — dates were missing or repeated in timezones east of UTC, and a schedule at local midnight could be skipped right after a daylight-saving change; the results are now correct. v4 keeps its previous results.
  • /chat — it now keeps only the last 200 messages of a room and of each private chat.

Exceptionally, v4 and v5 receive these fixes too, although they are otherwise frozen: the same limits and refusals apply to every version that has the endpoint, and v6 follows v5. Each item below says which versions it concerns, and the page of each endpoint gives the exact limits and error messages.

Endpoints

  • /captcha (v4, v5 and v6) — the text parameter is capped at 32 characters. On v5 and v6, the signed token of a challenge can no longer be forged or exchanged for a token of another kind: a /pow token no longer verifies as a captcha token, nor the reverse. A token is burned after 5 wrong answers and then answers used.
  • POST /captcha (v5 and v6) — it accepts an optional minLength, read from the JSON body: a right answer to a captcha generated shorter than that is refused with the reason weak. Without minLength, nothing changes.
  • /barcode (v4, v5 and v6) — the data of the variable-length formats, code128 and code39, is capped at 128 characters (Data cannot exceed 128 characters). The fixed-length formats ean13, ean8 and upca are not concerned.
  • /regex (v4, v5 and v6) — the evaluation of a pattern is interrupted after 25 ms and answers 400 with Pattern took too long to evaluate, so a catastrophic pattern can no longer block the server. A pattern or text key repeated in the query is refused like a missing one. A pattern that finishes in time returns the same matches as before.
  • /cron — on all three versions, a cron expression that can never match, such as 0 0 31 2 *, ends at once with an empty list instead of running until its limit, and a search is bounded in time (250 ms on v5 and v6, 1 s on v4): the dates found until then are returned.
  • /chat and /tic-tac-toe (v4, v5 and v6) — their inputs are bounded: a username to 100 characters (1000 for the fetch action of /chat, which is keyed by the reader's IP address), a message to 1000 (Message cannot exceed 1000 characters) and a session, game or private chat identifier to 256. Names such as __proto__ or constructor are now treated as ordinary names.
  • /chat messages — it keeps the last 200 messages of the public room and of each private chat, allows at most 1000 private chats at a time (Too many active private chats), and replaces a client timestamp that cannot be stored as sent, an object or a text over 128 characters, with the server date.
  • /qrcode and /hyperplanning (v4, v5 and v6) — the icon parameter of /qrcode and the calendars of /hyperplanning are fetched through a guarded fetch: internal addresses are refused after name resolution and on every redirect, and redirects are capped at 10. A calendar stops at 1 MB and 5000 events, an icon at 2 MB and 16 megapixels (Icon must be under 16 megapixels).
  • POST /asymmetric (v5 and v6) — RSA key pairs are now generated off the main thread, two at a time, so a large key no longer freezes the server for the other requests. The response is the same.

Server

  • Rate limiter — it counts against the instance-wide limit only the requests it admits, so a client being refused can no longer use up the budget of the others. An IPv6 client is counted by its /64 block, an IPv4-mapped IPv6 address by its IPv4 form, and each /48 network is capped at four times the hourly quota of one client (Too many requests from your network., 429). A forwarded address that is not an IP address counts as the connecting peer.
  • Order of the middleware — the security headers are now sent first, so every response carries them, and request bodies, still capped at 10 kB, are parsed after the rate limiter, so malformed bodies are counted too.
  • TRUSTED_PROXIES — when it is unset, the server keeps assuming exactly one reverse proxy and now logs a warning at startup. That default is right behind a single proxy such as nginx or Caddy; exposed directly, callers can forge the X-Forwarded-For header and pick their own address, and behind several hops every caller is counted as the nearest proxy. The README explains when to set the variable.

Package

  • asymmetricAsync — a new export, available from @moxon/api, @moxon/api/v5 and @moxon/api/v6. It takes the same arguments and returns the same result as asymmetric, as a promise, and generates RSA key pairs on the thread pool, at most two at a time. POST /asymmetric uses it.
  • Manifest — the experimental manifest export is not touched by this release: it still lists only hash, and describing the other endpoints as contracts is planned for a later release.
  • Dependencies — they are updated: body-parser goes to 2.4.0, with the qs (6.16.1) and iconv-lite (0.7.3) it uses. These versions are pinned in the repository's package-lock.json: they protect clones and deployments done with npm ci.