Summary
Fedify's document loader rejects valid public ActivityPub URLs hosted on CNAME-backed custom domains when running on Cloudflare Workers with nodejs_compat.
For example, this public ActivityPub Article cannot be loaded:
https://writings.hongminhee.org/ap/articles/2026/07/fedified-blog
Fedify throws:
UrlError: Invalid or private address: hongminhee-writings.netlify.app.
writings.hongminhee.org is a public hostname whose DNS record points to hongminhee-writings.netlify.app through a CNAME.
Minimal reproduction
import { getDocumentLoader } from "@fedify/vocab-runtime";
const loader = getDocumentLoader();
await loader(
"https://writings.hongminhee.org/ap/articles/2026/07/fedified-blog",
);
Equivalent Wrangler configuration:
Actual behavior
The call fails before the document is fetched:
UrlError: Invalid or private address: hongminhee-writings.netlify.app.
Runtime scope and likely root cause
Fedify's validatePublicUrl() calls:
addresses = await lookup(hostname, { all: true });
and then assumes that every LookupAddress.address is an IPv4 or IPv6 literal:
https://github.com/fedify-dev/fedify/blob/main/packages/vocab-runtime/src/url.ts
Under Cloudflare Workers' node:dns compatibility implementation, the lookup can return the CNAME target hostname—hongminhee-writings.netlify.app.—in the address field instead of a final IP address.
That hostname is passed to validatePublicIpAddress(), which rejects it because it is neither an IPv4 nor an IPv6 literal.
The same lookup under regular Node.js resolves to final IP addresses and does not exhibit this behavior.
Expected behavior
Fedify should successfully load the public ActivityPub document after securely resolving the CNAME target to its final A/AAAA records.
All resolved addresses should still be checked against Fedify's private and reserved address restrictions.
AI disclosure
This issue draft was created using codex:5.6-sol and fixed by @SJang1
Summary
Fedify's document loader rejects valid public ActivityPub URLs hosted on CNAME-backed custom domains when running on Cloudflare Workers with
nodejs_compat.For example, this public ActivityPub Article cannot be loaded:
https://writings.hongminhee.org/ap/articles/2026/07/fedified-blog
Fedify throws:
writings.hongminhee.orgis a public hostname whose DNS record points tohongminhee-writings.netlify.appthrough a CNAME.Minimal reproduction
Equivalent Wrangler configuration:
{ "compatibility_date": "2026-06-16", "compatibility_flags": ["nodejs_compat"] }Actual behavior
The call fails before the document is fetched:
Runtime scope and likely root cause
Fedify's
validatePublicUrl()calls:and then assumes that every
LookupAddress.addressis an IPv4 or IPv6 literal:https://github.com/fedify-dev/fedify/blob/main/packages/vocab-runtime/src/url.ts
Under Cloudflare Workers'
node:dnscompatibility implementation, the lookup can return the CNAME target hostname—hongminhee-writings.netlify.app.—in theaddressfield instead of a final IP address.That hostname is passed to
validatePublicIpAddress(), which rejects it because it is neither an IPv4 nor an IPv6 literal.The same lookup under regular Node.js resolves to final IP addresses and does not exhibit this behavior.
Expected behavior
Fedify should successfully load the public ActivityPub document after securely resolving the CNAME target to its final A/AAAA records.
All resolved addresses should still be checked against Fedify's private and reserved address restrictions.
AI disclosure
This issue draft was created using codex:5.6-sol and fixed by @SJang1