Skip to content

v0.1.2

Choose a tag to compare

@github-actions github-actions released this 25 Aug 23:46
· 69 commits to main since this release
v0.1.2
de46571

Security

  • The host of an import URL is now classified numerically instead of by
    comparing strings, and a hostname is resolved before it is accepted.
    http://localhost./recipe — the same name with its root label — walked past
    the old host === 'localhost' and endsWith('.local') checks, as did
    http://nas.local./. A DNS name pointing at 127.0.0.1 walked past all of it,
    because a Zod refinement is synchronous and cannot resolve anything. The check
    therefore moved out of the schema and into the tool handlers, where it can.
  • What is sent to Mealie is the parsed URL rather than the string that came in,
    so the address that was checked is the one Mealie fetches.
    http://ok.example.com\@127.0.0.1/recipe has the host ok.example.com for a
    URL parser and 127.0.0.1 for a fetcher that splits at the @.
  • The hostnames of the cloud metadata service — metadata.google.internal,
    instance-data and their siblings — are refused by name. They resolve to
    169.254.169.254 on the instance and to nothing anywhere else, so resolving
    them is exactly what cannot catch them. So are the endpoints that sit outside
    169.254/16: 100.100.100.200 (Alibaba Cloud) and 192.0.0.192 (Oracle).
  • An IPv6 scope id is stripped before the address is read. net.isIP accepts
    ::ffff:127.0.0.1%eth0, which made the dotted-quad fold miss its anchor and
    the address come out as routable. A URL cannot carry one, but a resolver
    answer can.

Changed

  • Private addresses are no longer refused here. Loopback, link-local and the
    metadata endpoints are still refused, but 10/8, 172.16/12, 192.168/16,
    fc00::/7, the rest of carrier-grade NAT and the
    .lan/.local/.internal/.home suffixes are not. That is a consistency
    change, not a new capability: Mealie has refused private addresses in its own
    HTTP transport since v1.4.0, so an import that names one still fails — further
    downstream and with a less helpful message. What this server now guards is the
    set of addresses Mealie does not guard for itself, which is why the two
    metadata endpoints outside 169.254/16 were added. If you were relying on this
    check to keep Mealie off your LAN, that job belongs to Mealie's own egress
    rules; SECURITY.md says what is and is not covered.
  • Bracketed IPv6 literals are no longer refused as a class. They were, because
    classifying them piecemeal was thought to be a losing game — the IPv4-mapped
    forms in particular. The classifier now unwraps those forms instead, so a public
    IPv6 address works while [::ffff:169.254.169.254] is still caught.
  • A name that a resolver sinkholes — answering 0.0.0.0 or ::, which is what
    every ad blocker and DNS filter does — is no longer refused as a loopback
    address. That is the resolver declining to answer rather than the name
    addressing the machine, and describing it as loopback made every blocklisted
    domain unusable with a message that was simply wrong.
  • The description of import_recipe_from_html_or_json no longer claims the tool
    works "without Mealie fetching anything". Mealie does not fetch the page, but it
    does read the image address out of the supplied document and retrieve that — an
    address this server never sees.