Repository navigation
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:
/crononv5andv6— 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.v4keeps its previous results./chat— it now keeps only the last200messages 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,v5andv6) — thetextparameter is capped at32characters. Onv5andv6, the signed token of a challenge can no longer be forged or exchanged for a token of another kind: a/powtoken no longer verifies as a captcha token, nor the reverse. A token is burned after5wrong answers and then answersused.POST /captcha(v5andv6) — it accepts an optionalminLength, read from the JSON body: a right answer to a captcha generated shorter than that is refused with the reasonweak. WithoutminLength, nothing changes./barcode(v4,v5andv6) — thedataof the variable-length formats,code128andcode39, is capped at128characters (Data cannot exceed 128 characters). The fixed-length formatsean13,ean8andupcaare not concerned./regex(v4,v5andv6) — the evaluation of a pattern is interrupted after25ms and answers400withPattern took too long to evaluate, so a catastrophic pattern can no longer block the server. Apatternortextkey 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 as0 0 31 2 *, ends at once with an empty list instead of running until its limit, and a search is bounded in time (250ms onv5andv6,1s onv4): the dates found until then are returned./chatand/tic-tac-toe(v4,v5andv6) — their inputs are bounded: a username to100characters (1000for thefetchaction of/chat, which is keyed by the reader's IP address), a message to1000(Message cannot exceed 1000 characters) and a session, game or private chat identifier to256. Names such as__proto__orconstructorare now treated as ordinary names./chatmessages — it keeps the last200messages of the public room and of each private chat, allows at most1000private chats at a time (Too many active private chats), and replaces a clienttimestampthat cannot be stored as sent, an object or a text over128characters, with the server date./qrcodeand/hyperplanning(v4,v5andv6) — theiconparameter of/qrcodeand the calendars of/hyperplanningare fetched through a guarded fetch: internal addresses are refused after name resolution and on every redirect, and redirects are capped at10. A calendar stops at1MB and5000events, an icon at2MB and16megapixels (Icon must be under 16 megapixels).POST /asymmetric(v5andv6) — 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
/64block, an IPv4-mapped IPv6 address by its IPv4 form, and each/48network 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
10kB, 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 theX-Forwarded-Forheader 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/v5and@moxon/api/v6. It takes the same arguments and returns the same result asasymmetric, as a promise, and generates RSA key pairs on the thread pool, at most two at a time.POST /asymmetricuses it.- Manifest — the experimental
manifestexport is not touched by this release: it still lists onlyhash, and describing the other endpoints as contracts is planned for a later release. - Dependencies — they are updated:
body-parsergoes to2.4.0, with theqs(6.16.1) andiconv-lite(0.7.3) it uses. These versions are pinned in the repository'spackage-lock.json: they protect clones and deployments done withnpm ci.