Skip to content

Use the key cache in RequestContext.getSignedKey() - #1209

Open
rewrite0w0 wants to merge 1 commit into
fedify-dev:mainfrom
rewrite0w0:feat/issue-1122
Open

rewrite0w0 wants to merge 1 commit into
fedify-dev:mainfrom
rewrite0w0:feat/issue-1122

Conversation

@rewrite0w0

@rewrite0w0 rewrite0w0 commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Summary

RequestContext.getSignedKey() calls verifyRequest() without a keyCache, so signing keys are fetched again across requests using the same key ID.

This adds the existing KvKeyCache to RequestContext.getSignedKey(), allowing signing keys to be reused across requests while preserving the existing key rotation behavior.

Regression tests were added for positive caching, negative caching of unavailable keys, and refetching a key after verification failure.

Fixes #1122

Test plan

  • deno test -A packages/fedify/src/federation/middleware.test.ts
  • mise check && mise fmt && mise test

AI disclosure

Assisted-by: ChatGPT:gpt-5.6-luna

I used ChatGPT through the regular chat interface (not Codex) and copied the code into my editor manually. ChatGPT implemented the change to RequestContext.getSignedKey() and wrote the regression tests. I manually reviewed the code before committing.

@netlify

netlify Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for fedify-json-schema canceled.

Name Link
🔨 Latest commit 6653c12
🔍 Latest deploy log https://app.netlify.com/projects/fedify-json-schema/deploys/6ac354ca258d1a00088d98df

@coderabbitai

coderabbitai Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

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

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: cf3c56cd-b393-4f65-af86-bff46a782e34
📥 Commits

Reviewing files that changed from the base of the PR and between 2d904bf and 6653c12.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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: 4a05cb27-f849-4ac1-a3be-aedf38c61274
📥 Commits

Reviewing files that changed from the base of the PR and between 49d937e and 89d1f9a.

📒 Files selected for processing (2)
  • packages/fedify/src/federation/middleware.test.ts
  • packages/fedify/src/federation/middleware.ts

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


📝 Walkthrough

Walkthrough

getSignedKey() now creates a KvKeyCache for public-key lookups and passes it to verifyRequest. Tests cover reuse of verified and unavailable keys, and refetching and reuse after key rotation.

Changes

Public-key cache

Layer / File(s) Summary
Configure and verify cached public keys
packages/fedify/src/federation/middleware.ts, packages/fedify/src/federation/middleware.test.ts
getSignedKey() configures a KvKeyCache with the selected loaders, tracer provider, and public-key TTL, then passes it to verifyRequest. Tests check reuse of verified and unavailable keys, plus refetch and reuse after key rotation.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to 89d1f

Signing keys are now reused across requests, and a key that no longer verifies is refetched. Tests cover reuse, unavailable keys, and rotation. No merge-blocking risk was found.

Security Architecture Review

Security architecture risk: 🟡 Moderate · up to 89d1f

Key reuse reduces remote lookups, but a previously trusted key can continue verifying requests after it is withdrawn. Refreshing after a signature mismatch supports rotation but does not detect requests signed with the old private key. Exposure depends on cache lifetime and the application's subsequent ownership checks.

Retained concerns

  • Medium · security · inferred: Cross-request caching extends acceptance of formerly trusted keys. A request signed with an old private key can still verify against its cached public key after authoritative removal or replacement, without triggering rotation refresh. This can preserve access where authorization relies on getSignedKey without a subsequent ownership check. Newly written ordinary entries default to 30 days; legacy entries without expiry may last longer. Separate ownership verification mitigates key removal for callers that use it.
Security review details

Security Blast Radius

  • inferred — The delayed-revocation exposure is tied to a previously cached key and possession of its corresponding private key. It can affect resources whose authorization accepts that sender through getSignedKey, across contexts using the same public-key cache namespace. This does not establish arbitrary-actor impersonation, cross-tenant access, or compromise of every federation endpoint.

Security Findings and Attack Paths

  • inferred — A formerly trusted key is cached; its owner later withdraws or replaces it; a holder of the old private key submits a valid new signed request naming that key URL. The cached key still verifies, so mismatch-triggered refresh does not occur. Access can continue where the consumer treats that result as sufficient authorization. The rotation regression exercises the replacement private key, not this old-key path.

Trust Boundaries and Controls

  • observed — Caching does not remove cryptographic signature verification or fresh-fetch ownership validation. For ordinary keys, getSignedKeyOwner separately resolves the claimed owner and checks its linkage through the selected loader, mitigating removal from that owner's key list. Cache generation 2 also separates entries from earlier versions that did not validate ownership.

Hardening Proposals

  • proposed — Define an explicit authentication-freshness policy, including a cache-bypass option for revocation-sensitive callers or mandatory authoritative revalidation. Bound the accepted stale-key interval and account for legacy entries without expiry. Validate the policy against requests signed with a withdrawn key, not only requests signed with its replacement.
  • proposed — If applications use different document loaders as distinct trust policies, isolate their cache namespaces or revalidate cached keys under the active policy. The shared key-URL namespace is established, but no concrete deployment using loaders as separate security domains was evidenced; this is a conditional hardening proposal, not an observed bypass.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely describes the main change: using the key cache in RequestContext.getSignedKey().
Description check ✅ Passed The description explains the key-cache change, its key-rotation behavior, the regression tests, and the reported test plan. It is directly related to the changeset.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@codecov

codecov Bot commented Oct 3, 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/federation/middleware.ts 87.66% <100.00%> (+0.02%) ⬆️
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@2chanhaeng 2chanhaeng left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the title to summarize the intent of the change, and note which issue the PR addresses in the body. If the title only includes the issue number, GitHub cannot link the issue to the PR.
I think this PR needs a changelog entry because the number of remote lookups and the timing of key updates will change. These changes are visible to users.
I also think users should have an option to disable the cache. However, it doesn’t need to be implemented right away, so you can create a separate issue.
The PR description says AI was used, but the only commit that changed the code, 3ff6fa0, doesn’t have Assisted-by trailers in its message. Please add them.

@dahlia dahlia added this to the Fedify 2.5 milestone Oct 4, 2026
@dahlia dahlia added component/federation Federation object related component/signatures OIP or HTTP/LD Signatures related labels Oct 4, 2026
@dahlia dahlia linked an issue Oct 4, 2026 that may be closed by this pull request
@rewrite0w0 rewrite0w0 changed the title Feat/issue 1122 Use the key cache in RequestContext.getSignedKey() Oct 4, 2026
@coderabbitai

coderabbitai Bot commented Oct 4, 2026

Copy link
Copy Markdown

Note

Unit test generation is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.


Generating unit tests... This may take up to 20 minutes.

@coderabbitai

coderabbitai Bot commented Oct 4, 2026

Copy link
Copy Markdown

🤖 Coding Agent task started for unit test generation.

@rewrite0w0
rewrite0w0 requested a review from 2chanhaeng October 4, 2026 17:31
@dahlia dahlia changed the title Use the key cache in RequestContext.getSignedKey() Use the key cache in RequestContext.getSignedKey() Oct 4, 2026

@dahlia dahlia left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please rebase this branch onto the latest main and remove the back-merge commits to keep the history linear? Please use rebase for future updates as well.

The PR description discloses AI assistance, but the implementation commit is missing the required Assisted-by trailer. Please add it in the Assisted-by: AGENT_NAME:MODEL_VERSION format described in AI_POLICY.md.

@coderabbitai

coderabbitai Bot commented Oct 5, 2026

Copy link
Copy Markdown

Autopilot could not be updated. Open Coding to check access and billing.

@dahlia dahlia left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you confirm whether you used ChatGPT or meant Codex? If you worked through conversations in ChatGPT and manually copied the code into your editor, ChatGPT is fine. Please also describe what the tool helped with in the PR description.

Please use the official model identifier gpt-5.6-luna instead of GPT-5.6-Luna, as required by CONTRIBUTING.md.

@rewrite0w0

Copy link
Copy Markdown
Contributor Author

Thanks for the review :D. I used ChatGPT through the regular chat interface (not Codex) and copied the code into my editor manually. ChatGPT implemented the change and wrote the tests, and I reviewed it manually. I've updated the trailer to Assisted-by: ChatGPT:gpt-5.6-luna and described this in the PR description.

Assisted-by: ChatGPT:gpt-5.6-luna

@dahlia dahlia left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, good job!

@dahlia
dahlia enabled auto-merge October 5, 2026 07:56

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/federation Federation object related component/signatures OIP or HTTP/LD Signatures related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Use the key cache in RequestContext.getSignedKey()

3 participants