Fix ActivityPub Follow verification behind a TLS proxy #18

Merged
erik merged 1 commit from task-a12b0016-activitypub-follow into main 2026-10-02 21:17:45 -05:00
Owner

Summary

Fix locally reproduced ActivityPub Follow verification failures without changing actor identity, keys, followers, or automatic acceptance.

  • Use the site's existing compatible acct: signer for authenticated remote actor/key fetching at both inboxes and during queued processing; preserve explicitly supplied other identities and default URL restrictions.
  • Verify against the configured canonical public origin behind a TLS-terminating proxy while preserving path/query/headers/body. Reject conflicting or malformed signed Host authorities; never trust forwarded host/protocol headers.
  • Advertise automatic acceptance explicitly and add narrowly allowlisted, sanitized verification/processing/Accept-delivery diagnostics.
  • Document repository-specific evidence, controlled reproduction, deployment prerequisites, non-durable queue limits, and separate production/live-testing approval gates.

Task: task-a12b0016.

Evidence

Baseline 5e46f65 signed authenticated fetches with the unadvertised primary-actor #main-key identity and received controlled 401 responses. Valid RFC 9421 fixtures passed on the public HTTPS URL but failed with HTTP backend URLs through both application inboxes. These are controlled repository reproductions, not a claim about the historical failure of an unknown sending account.

Production infrastructure inspection was removed from the task at Erik's request. No production deployment, restart, configuration change, or live Follow POST was performed.

Verification

  • npm test: 362 tests across 49 files passed.
  • npm run lint: passed.
  • npm run build: CSS build and TypeScript checks passed.
  • git diff --check: passed.
  • Local production Docker build and scripts/validate-production-image.sh: health, API health, expected version, and homepage checks passed.
  • New regression suites cover both inboxes and HTTP-signature formats, authenticated GET and Accept signature verification, queued processing, state/key/profile persistence across database reopen, invalid/unsigned signatures, actor/key mismatch, unsafe URLs, spoofed forwarding headers, cross-host replay, malformed Host authorities, and sensitive-marker suppression.

No formatter script is configured in this repository; existing style and whitespace checks were used. Existing engagement/reply/following fixtures now explicitly inject authenticated loaders as well as unsigned loaders, without changing production safety options.

Deployment

See docs/activitypub-follow-verification.md. No schema migration, key rotation, actor rename, or follower-data edit is needed. Production deployment and live Follow testing require separate approval; merging this PR does not authorize either.

## Summary Fix locally reproduced ActivityPub Follow verification failures without changing actor identity, keys, followers, or automatic acceptance. - Use the site's existing compatible `acct:` signer for authenticated remote actor/key fetching at both inboxes and during queued processing; preserve explicitly supplied other identities and default URL restrictions. - Verify against the configured canonical public origin behind a TLS-terminating proxy while preserving path/query/headers/body. Reject conflicting or malformed signed Host authorities; never trust forwarded host/protocol headers. - Advertise automatic acceptance explicitly and add narrowly allowlisted, sanitized verification/processing/Accept-delivery diagnostics. - Document repository-specific evidence, controlled reproduction, deployment prerequisites, non-durable queue limits, and separate production/live-testing approval gates. Task: `task-a12b0016`. ## Evidence Baseline `5e46f65` signed authenticated fetches with the unadvertised primary-actor `#main-key` identity and received controlled 401 responses. Valid RFC 9421 fixtures passed on the public HTTPS URL but failed with HTTP backend URLs through both application inboxes. These are controlled repository reproductions, not a claim about the historical failure of an unknown sending account. Production infrastructure inspection was removed from the task at Erik's request. No production deployment, restart, configuration change, or live Follow POST was performed. ## Verification - `npm test`: 362 tests across 49 files passed. - `npm run lint`: passed. - `npm run build`: CSS build and TypeScript checks passed. - `git diff --check`: passed. - Local production Docker build and `scripts/validate-production-image.sh`: health, API health, expected version, and homepage checks passed. - New regression suites cover both inboxes and HTTP-signature formats, authenticated GET and Accept signature verification, queued processing, state/key/profile persistence across database reopen, invalid/unsigned signatures, actor/key mismatch, unsafe URLs, spoofed forwarding headers, cross-host replay, malformed Host authorities, and sensitive-marker suppression. No formatter script is configured in this repository; existing style and whitespace checks were used. Existing engagement/reply/following fixtures now explicitly inject authenticated loaders as well as unsigned loaders, without changing production safety options. ## Deployment See `docs/activitypub-follow-verification.md`. No schema migration, key rotation, actor rename, or follower-data edit is needed. Production deployment and live Follow testing require separate approval; merging this PR does not authorize either.
Fix Follow verification with compatible fetching and canonical URLs
All checks were successful
CI / build-lint-test (push) Successful in 1m11s
5d7ade3e48
Author
Owner

Review update

  • PR: #18 — open; reviewed commit 5d7ade3e4874facfc6c1425560a833149c3ae5f5.
  • Result: approved.
  • Summary: Scoped fixes correctly use the existing compatible primary-actor signer for authenticated loading in both inbox routes and queued processing, reconstruct the trusted canonical origin without trusting forwarding headers, reject conflicting/malformed Host authorities without rewriting signed headers, retain automatic acceptance and signed Accept delivery, and emit narrowly allowlisted diagnostics. No schema, identity, key, or follower migration is introduced.
  • Criteria source: the CURRENT description of task-a12b0016; controlled HTTP-backend/public-HTTPS fixtures satisfy proxy verification. Production infrastructure inspection and live Follow testing are not required.

Acceptance criteria — 8/8 met

  1. met — Repository-specific baseline failures and automatic-approval rule-out are recorded in docs/activitypub-follow-verification.md against 5e46f65; evidence is explicitly distinguished from an unknown historical sending-account failure.
  2. met — Both actor/shared inboxes fetch remote keys and actors using compatible authenticated fixtures and process their queued follows.
  3. met — Both inboxes pass RFC 9421 and legacy Cavage fixtures through application HTTP-backend URLs with the configured public HTTPS origin; canonical reconstruction preserves method, encoded path, query, headers, and body.
  4. met — Tampering, unsigned requests, actor/key mismatch, wrong targets, unsafe URLs, spoofed forwarding, cross-host signatures, and malformed/conflicting Host authorities are rejected. Production authenticated-loader safety defaults and options remain intact; other explicit identities are preserved.
  5. met — Queue processing persists followers automatically, advertises manuallyApprovesFollowers: false, delivers Accept using the existing acct: signer, and cryptographically verifies the delivered signature against the advertised public key.
  6. met — Verification/fetch/processing/delivery failures and successful delivery have scoped sanitized diagnostics. Allowlisted library event templates match the installed Fedify implementation; secret/payload suppression is regression-tested.
  7. met — File-backed SQLite reopen with recreated app/workers preserves follower state and actor/profile/key material and continues automatic acceptance. Existing follower preservation is also tested. The unchanged non-durable in-process queue limitation is documented rather than misrepresented as restart-durable delivery.
  8. met — Reviewer independently ran all 47 tests in the three new regression suites successfully and checked diff whitespace. Forgejo CI task #61 succeeded on 5d7ade3 (build/typecheck, lint, tests). Implementer additionally reports all 362 tests in 49 files and local production Docker health/API/homepage validation passed. Deployment prerequisites and reproducible verification are documented.

Findings

  • Blocking issues: 0.
  • Warnings: 0.
  • Final verdict: approved.
  • Tooling note: installed fj v0.5.0 supports Actions --repo but rejects it for PR commands. PR metadata/diff and this comment use the explicitly scoped Forgejo API repository path; the remote and local diff patch IDs match. Actions status was inspected with --repo erik/erikvancraddock.com.
  • Follow-up: Wait for explicit human merge approval. This review does not authorize merge, deployment, restart, configuration changes, or live Follow testing. No repository files were edited and task status was not changed.
### Review update - PR: https://forge.caradoc.com/erik/erikvancraddock.com/pulls/18 — open; reviewed commit `5d7ade3e4874facfc6c1425560a833149c3ae5f5`. - Result: **approved**. - Summary: Scoped fixes correctly use the existing compatible primary-actor signer for authenticated loading in both inbox routes and queued processing, reconstruct the trusted canonical origin without trusting forwarding headers, reject conflicting/malformed Host authorities without rewriting signed headers, retain automatic acceptance and signed Accept delivery, and emit narrowly allowlisted diagnostics. No schema, identity, key, or follower migration is introduced. - Criteria source: the CURRENT description of `task-a12b0016`; controlled HTTP-backend/public-HTTPS fixtures satisfy proxy verification. Production infrastructure inspection and live Follow testing are not required. #### Acceptance criteria — 8/8 met 1. **met** — Repository-specific baseline failures and automatic-approval rule-out are recorded in `docs/activitypub-follow-verification.md` against `5e46f65`; evidence is explicitly distinguished from an unknown historical sending-account failure. 2. **met** — Both actor/shared inboxes fetch remote keys and actors using compatible authenticated fixtures and process their queued follows. 3. **met** — Both inboxes pass RFC 9421 and legacy Cavage fixtures through application HTTP-backend URLs with the configured public HTTPS origin; canonical reconstruction preserves method, encoded path, query, headers, and body. 4. **met** — Tampering, unsigned requests, actor/key mismatch, wrong targets, unsafe URLs, spoofed forwarding, cross-host signatures, and malformed/conflicting Host authorities are rejected. Production authenticated-loader safety defaults and options remain intact; other explicit identities are preserved. 5. **met** — Queue processing persists followers automatically, advertises `manuallyApprovesFollowers: false`, delivers Accept using the existing `acct:` signer, and cryptographically verifies the delivered signature against the advertised public key. 6. **met** — Verification/fetch/processing/delivery failures and successful delivery have scoped sanitized diagnostics. Allowlisted library event templates match the installed Fedify implementation; secret/payload suppression is regression-tested. 7. **met** — File-backed SQLite reopen with recreated app/workers preserves follower state and actor/profile/key material and continues automatic acceptance. Existing follower preservation is also tested. The unchanged non-durable in-process queue limitation is documented rather than misrepresented as restart-durable delivery. 8. **met** — Reviewer independently ran all 47 tests in the three new regression suites successfully and checked diff whitespace. Forgejo CI task **#61 succeeded on 5d7ade3** (build/typecheck, lint, tests). Implementer additionally reports all 362 tests in 49 files and local production Docker health/API/homepage validation passed. Deployment prerequisites and reproducible verification are documented. #### Findings - Blocking issues: **0**. - Warnings: **0**. - Final verdict: **approved**. - Tooling note: installed `fj v0.5.0` supports Actions `--repo` but rejects it for PR commands. PR metadata/diff and this comment use the explicitly scoped Forgejo API repository path; the remote and local diff patch IDs match. Actions status was inspected with `--repo erik/erikvancraddock.com`. - Follow-up: **Wait for explicit human merge approval.** This review does not authorize merge, deployment, restart, configuration changes, or live Follow testing. No repository files were edited and task status was not changed.
erik merged commit 362d72442e into main 2026-10-02 21:17:45 -05:00
erik deleted branch task-a12b0016-activitypub-follow 2026-10-02 21:17:46 -05:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
erik/erikvancraddock.com!18
No description provided.