Skip to content

Log DNS lookup failures separately from disallowed URLs - #1065

Open
dahlia wants to merge 1 commit into
fedify-dev:2.0-maintenancefrom
dahlia:bugfix/dns-failure-logs
Open

dahlia wants to merge 1 commit into
fedify-dev:2.0-maintenancefrom
dahlia:bugfix/dns-failure-logs

Conversation

@dahlia

@dahlia dahlia commented Sep 25, 2026

Copy link
Copy Markdown
Member

Fixes #1062. A hostname that doesn't resolve currently shows up in the logs as a blocked private address. The four callers of validatePublicUrl() that catch UrlError now branch on UrlError.reason from #1060 and log "dns" failures as DNS lookup failed for {url}, with the original error attached:

  • getAuthenticatedDocumentLoader() in packages/fedify/src/utils/docloader.ts
  • getDocumentLoader() in packages/vocab-runtime/src/docloader.ts
  • lookupWebFinger() in packages/webfinger/src/lookup.ts
  • getNodeInfo() in packages/fedify/src/nodeinfo/client.ts

Disallowed URLs keep their existing messages, and control flow doesn't change.

Log levels

Each caller logs DNS failures at the level it already uses for an ordinary fetch() failure. The two document loaders don't log those at all and lookupWebFinger() logs them at debug, so these three log DNS failures at debug. getNodeInfo() logs network failures at error, so its DNS failures stay at error. Error level in the loaders would keep the noise the issue complains about, since they run constantly on a busy server.

Tests

Each caller's new test stubs dns.lookup() the way #1060 did and captures LogTape records for three cases: a lookup that throws, one that returns no addresses, and one that resolves to a private address. All four fail without this fix.

In packages/vocab-runtime/ and packages/webfinger/, the Deno net permission check runs inside the test callback because those packages also build their tests as CommonJS, which rejects top-level await.

Merging forward

This needs UrlError.reason, so it has to reach 2.1-maintenance together with #1060.

  • From 2.3-maintenance on, the internal WebFinger lookup returns { resource: null, result: "network_error", remoteHost } instead of null. A TODO at the new branch says to keep that value for both reasons.
  • The tests rely on packages/vocab-runtime/src/url.ts using the default node:dns/promises import. 2.1-maintenance through main still use import { lookup }, so keep the default import when resolving the Fix DNS failures bypassing during inbox validation #1060 conflict.

CLI lookup hints are left to #1063 and #1064.

Since 2.0.23, validatePublicUrl() throws UrlError when a hostname fails
to resolve, and the callers that catch UrlError logged every such error
as a policy rejection.  A dead instance or a flaky resolver therefore
showed up as "Disallowed private URL" or a similar message, pointing
operators at an SSRF attempt or a misconfigured allowPrivateAddress
when the name simply did not resolve.  On a busy server these
error-level logs pile up from routine document loading and WebFinger
lookups.

The callers now check UrlError.reason, added in
fedify-dev#1060, and log DNS failures as
"DNS lookup failed for {url}" with the original error attached.  Each
one uses the level it already uses for other network failures: debug
for the two document loaders and lookupWebFinger(), error for
getNodeInfo().  Disallowed URLs keep their existing messages, and
control flow is unchanged.

A comment in lookupWebFinger() notes that 2.3-maintenance and later
return an outcome object there instead of null, for the forward merge.

Fixes fedify-dev#1062

Assisted-by: Claude Code:claude-opus-5-5
Assisted-by: Codex:gpt-6-astra
Assisted-by: Claude Code:claude-fable-5-1
@dahlia
dahlia requested review from 2chanhaeng and sij411 September 25, 2026 13:40
@dahlia dahlia self-assigned this Sep 25, 2026
@dahlia dahlia added component/vocab Activity Vocabulary related component/webfinger WebFinger related component/nodeinfo NodeInfo related labels Sep 25, 2026
@coderabbitai

coderabbitai Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 2947c29c-cb51-49e3-96d7-41dee153385a

📥 Commits

Reviewing files that changed from the base of the PR and between b789935 and 54ddf28.

📒 Files selected for processing (12)
  • CHANGES.md
  • changes.d/fedify/dns-failure-logs.md
  • changes.d/vocab-runtime/dns-failure-logs.md
  • changes.d/webfinger/dns-failure-logs.md
  • packages/fedify/src/nodeinfo/client.test.ts
  • packages/fedify/src/nodeinfo/client.ts
  • packages/fedify/src/utils/docloader.test.ts
  • packages/fedify/src/utils/docloader.ts
  • packages/vocab-runtime/src/docloader.test.ts
  • packages/vocab-runtime/src/docloader.ts
  • packages/webfinger/src/lookup.test.ts
  • packages/webfinger/src/lookup.ts

Included review availability: Your plan provides up to 4 included reviews per hour; 3 remain after this review.


📝 Walkthrough

Walkthrough

DNS resolution failures now receive distinct log messages from disallowed URLs across Fedify, vocab-runtime, and WebFinger. Existing return and throw behavior remains unchanged. Tests cover lookup failures, empty DNS results, and private-address results.

Changes

DNS failure logging

Layer / File(s) Summary
Fedify URL validation logging
packages/fedify/src/utils/docloader.ts, packages/fedify/src/nodeinfo/client.ts, packages/fedify/src/utils/docloader.test.ts, packages/fedify/src/nodeinfo/client.test.ts, changes.d/fedify/*, CHANGES.md
Document loading logs DNS failures at debug level. getNodeInfo logs them at error level. Other URL validation errors retain their existing log levels, and the existing return behavior remains unchanged. Tests cover failed lookups, empty results, and loopback results.
Vocab-runtime document loader logging
packages/vocab-runtime/src/docloader.ts, packages/vocab-runtime/src/docloader.test.ts, changes.d/vocab-runtime/*, CHANGES.md
DNS failures are logged at debug level. Other UrlError cases remain error-level logs, and the loader continues to rethrow the error. Tests cover DNS failures and private addresses.
WebFinger lookup logging
packages/webfinger/src/lookup.ts, packages/webfinger/src/lookup.test.ts, changes.d/webfinger/*, CHANGES.md
DNS failures are logged at debug level. Other UrlError cases remain error-level logs, and lookup continues to return null. Tests cover DNS failures and private addresses.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix · Severity of issue fixed: Low

Merge Risk: ⚪ Minimal · up to 54ddf

DNS failures should now be logged accurately without changing how callers handle them. No merge-blocking risk is identified.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 8 files. (4 skipped: 4… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: separate DNS lookup failure logs from disallowed URL logs.
Description check ✅ Passed The description directly explains the affected callers, logging behavior, preserved control flow, and test coverage for the changeset.
Linked Issues check ✅ Passed The changes satisfy issue #1062. All four listed callers inspect UrlError.reason. DNS failures log DNS lookup failed for {url} with the original error. Disallowed URLs retain their existing error …
Out of Scope Changes check ✅ Passed The changes stay within issue #1062. The added tests verify the required DNS and disallowed-URL behavior. The changelog entries document the same behavior. No unrelated functional change is identified…
Full details: Docstring Coverage

Explanation

Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 8 files. (4 skipped: 4 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@dahlia

dahlia commented Sep 25, 2026

Copy link
Copy Markdown
Member Author

@codex review

@codecov

codecov Bot commented Sep 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

Files with missing lines Coverage Δ
packages/fedify/src/nodeinfo/client.ts 93.00% <100.00%> (+0.39%) ⬆️
packages/fedify/src/utils/docloader.ts 100.00% <100.00%> (ø)
packages/vocab-runtime/src/docloader.ts 95.79% <100.00%> (+0.12%) ⬆️
packages/webfinger/src/lookup.ts 91.12% <100.00%> (+0.38%) ⬆️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component/nodeinfo NodeInfo related component/vocab Activity Vocabulary related component/webfinger WebFinger related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant