Skip to content

Consolidate application security guidance into a dedicated manual chapter #942

Description

@SJang1

Background

Fedify already documents several important security considerations, but the
guidance is distributed across multiple manual chapters.

For example:

  • the deployment guide discusses
    sanitizing federated HTML, Content Security Policy, SSRF prevention, secret
    management, worker isolation, and production hardening;
  • the access control guide
    explains authorized fetch and application-level authorization;
  • the vocabulary guide describes Fedify's
    origin-based security model;
  • the message queue guide covers background
    processing and queue backends; and
  • the integration guide explains how
    Fedify and application routes can share the same HTTP service.

Because these responsibilities are documented alongside individual features,
there is no single manual chapter that presents the overall threat model of a
Fedify application, explains which protections Fedify provides, and identifies
which security boundaries remain the application's responsibility.

This can be especially difficult for developers who are new to ActivityPub or
distributed deployments. It is also easy for generated code or coding agents
to produce an implementation that works functionally while missing an
application-level trust boundary.

For example, applications may separate public HTTP handling from queue and
background processing. A background worker may later need to communicate with
a web or stateful component to broadcast streaming updates, deliver
notifications, invalidate caches, or invoke another application-specific
operation.

A tempting implementation is to expose an HTTP endpoint under a path such as
/internal/* and call it from the background worker. However, an internal
path name does not establish an access-control boundary. If the endpoint is
registered on the same router or service that handles public traffic, it may
also be reachable from the public internet.

Similarly, CORS is a browser policy rather than a service authentication
mechanism. Non-browser clients can call such endpoints directly.

These concerns are not specific to one runtime or deployment platform. Similar
trust boundaries exist when using separate processes, containers, Kubernetes
services, queue consumers, or serverless platforms.

Proposal

Add a dedicated application security chapter to the Fedify manual.

Rather than duplicating every existing document, the chapter could provide a
central threat-model and shared-responsibility overview, summarize the
important security invariants, and link to the existing detailed
documentation.

A possible outline follows.

Fedify's security boundary

  • Explain which protocol-level protections Fedify provides.
  • Identify which data must still be treated as untrusted.
  • Clarify that a valid HTTP signature authenticates a key or actor but does not
    guarantee that the sender is benign or that supplied content is safe.
  • Explain which validation, authorization, rendering, and deployment decisions
    remain application responsibilities.
  • Distinguish Fedify's built-in protections from protections that must be
    implemented by the surrounding application.

Federated input and content rendering

  • Validate ActivityPub objects and application-specific fields before use.
  • Sanitize federated HTML before rendering it in a browser.
  • Apply output encoding appropriate to each rendering context.
  • Avoid treating content as trusted solely because it came from a signed
    activity, queue, or internal service.
  • Use Content Security Policy as defense in depth rather than as a replacement
    for sanitization.

Remote resource fetching and SSRF

  • Use Fedify's protected document loaders where possible.
  • Apply equivalent URL validation to application-managed fetches.
  • Validate redirect targets rather than validating only the initial URL.
  • Avoid production use of development-oriented security bypasses such as
    allowPrivateAddress.
  • Document which application-level fetches are not covered by Fedify's built-in
    protections.

Authentication and authorization

  • Distinguish HTTP signature verification from application authorization.
  • Explain authorized fetch and when it may be appropriate.
  • Apply explicit authorization to application-defined API, administrative, and
    maintenance operations.
  • Avoid relying on path names, request origin assumptions, or CORS as access
    controls.
  • Prefer deny-by-default behavior for privileged operations.

Web and background-processing boundaries

  • Keep background workers and internal application handlers outside public
    ingress.
  • Avoid using unauthenticated public HTTP routes for internal operations.
  • Prefer queue-native processing or capability-scoped private transports.
  • Validate queue and RPC payloads at the receiving boundary, including
    allowlisting supported operations and targets.
  • Avoid treating messages as trusted solely because they arrived through an
    internal queue, RPC interface, or private network.
  • Define clear ownership for application control operations so that they are
    not accidentally registered on a public router.

When HTTP cannot be avoided, the guide could recommend:

  • authenticating the calling service;
  • verifying request integrity;
  • limiting the caller's authority;
  • including freshness information such as timestamps;
  • preventing replay with nonces or equivalent mechanisms; and
  • failing closed when authentication or validation cannot be completed.

Secrets and cryptographic keys

  • Distinguish instance-wide secrets from per-actor signing keys.
  • Explain recommended storage, backup, and rotation practices.
  • Avoid secrets in source control, logs, public Worker configuration, or queue
    payloads.
  • Minimize which components receive each secret or privileged binding.
  • Consider deployment-specific secret managers where available.

Platform-specific guidance

The guide could keep its core security invariants platform-independent while
also documenting stronger implementation patterns available in particular
deployment environments.

Examples could include:

  • Cloudflare Workers Service Bindings and named WorkerEntrypoint RPC
    interfaces for capability-scoped communication between Workers;
  • Cloudflare Queue handlers for background processing without introducing
    additional public HTTP endpoints;
  • Kubernetes ClusterIP services combined with NetworkPolicies, workload
    identities, or service-mesh mTLS;
  • loopback interfaces or private container networks for separately deployed
    web and worker processes;
  • private service integrations offered by other serverless platforms;
  • authenticated message brokers or dedicated queues for background work; and
  • platform-specific secret stores and workload identity mechanisms.

These sections would make the guidance actionable without presenting one
platform's solution as a universal requirement.

Each platform-specific section could describe:

  • the preferred security mechanism;
  • which trust boundary it establishes;
  • important limitations and residual risks;
  • fallback approaches when the preferred mechanism is unavailable;
  • recommended deployment configuration; and
  • positive and negative tests that verify the boundary.

A central application security chapter would provide a natural place to
collect and link these recommendations as support for additional runtimes and
deployment platforms is added to Fedify.

Documentation and contribution structure

The documentation should distinguish between platform-independent security
guidance and environment-specific implementation guidance.

This distinction would allow users who operate Fedify in different
environments to contribute practical solutions without requiring every
platform detail to be added to the central security chapter.

General security guidance

The central application security chapter should contain guidance that applies
regardless of runtime, hosting provider, framework, or orchestration system.

Examples include:

  • the overall Fedify application threat model;
  • the distinction between authentication and authorization;
  • treating federated and remotely supplied data as untrusted;
  • sanitizing content before rendering;
  • preventing SSRF in application-managed fetches;
  • keeping privileged operations outside public ingress;
  • validating queue, RPC, and internal service payloads;
  • avoiding path names or CORS as access controls;
  • applying least privilege to services, credentials, and bindings; and
  • testing both successful operations and rejected public access.

The general chapter should describe the security property that an application
needs to preserve without requiring one platform-specific implementation.

Environment-specific guidance

Guidance that depends on a particular runtime, hosting provider, network
model, queue implementation, or platform capability should be documented in a
separate environment-specific document.

Examples include:

  • Cloudflare Workers Service Bindings, named WorkerEntrypoint RPC methods,
    Worker routes, and Cloudflare Queue behavior;
  • Kubernetes Services, NetworkPolicies, workload identities, ingress
    configuration, and service-mesh mTLS;
  • container network configuration and loopback-only worker processes;
  • serverless platform private service integrations;
  • provider-specific secret stores and identity mechanisms; and
  • environment-specific WAF, proxy, routing, or queue behavior.

Environment-specific documents could also describe security problems that are
unique to, or especially easy to introduce in, that environment.

Each document should identify:

  • the environment and supported versions;
  • the security boundary being protected;
  • common insecure implementation patterns;
  • the recommended platform-native solution;
  • alternative solutions when the preferred mechanism is unavailable;
  • configuration or code examples;
  • deployment and regression tests;
  • important limitations and residual risks; and
  • links back to the relevant general security invariants.

Deciding where guidance belongs

A contribution could use the following decision process:

  1. If the risk and recommendation apply regardless of deployment environment,
    add them to the general application security chapter.
  2. If the recommendation depends on a platform-specific API, configuration,
    network model, or security feature, add a separate environment-specific
    document.
  3. If a problem has both general and platform-specific aspects, document the
    common risk and invariant in the general chapter, then document each
    concrete implementation in the relevant environment-specific documents.
  4. Avoid repeating the full general security explanation in each platform
    document. Link back to the central chapter instead.
  5. Update the central platform index when adding a new environment-specific
    document.

For example, the general guide could state that privileged communication
between web and background-processing components must not be exposed through
unauthenticated public HTTP routes.

A Cloudflare-specific document could then explain how to preserve that
invariant using Service Bindings and named WorkerEntrypoint RPC methods. A
Kubernetes-specific document could explain the same invariant using internal
Services, NetworkPolicies, workload identities, or mTLS.

Suggested document layout

One possible layout is:

docs/secure-coding/index.md
docs/secure-coding/cloudflare-workers.md
docs/secure-coding/containers.md
docs/secure-coding/kubernetes.md
docs/secure-coding/serverless.md

Deployment verification

The guide could include tests and checks that operators can perform before
deployment.

Examples include:

  • confirm that worker-only components are not reachable through public
    ingress;
  • verify that internal operations cannot be invoked through the public
    application origin;
  • test authorization failure paths in addition to successful internal calls;
  • verify that public requests to reserved internal paths return 404 or
    another non-successful response;
  • confirm that queue and RPC receivers reject unsupported operations or
    malformed payloads;
  • confirm that production configuration does not enable development-only
    security bypasses;
  • verify that secrets and privileged bindings are provided only to components
    that require them; and
  • run a concise pre-deployment application security checklist.

Suggested implementation

The initial change could remain documentation-only:

  1. add a new manual chapter such as docs/manual/security.md;
  2. link it from the manual navigation and relevant feature chapters;
  3. consolidate or summarize general security guidance currently located in
    the deployment guide;
  4. retain detailed feature-specific guidance in its existing chapters while
    linking back to the central security guide;
  5. define the shared application security model and trust boundaries in the
    central chapter;
  6. add platform-specific subsections or linked examples for security
    mechanisms available only in particular environments; and
  7. add a concise application security checklist.

The central chapter would define the common security invariants. Individual
runtime, integration, queue, and deployment chapters could then document the
strongest practical way to preserve those invariants in each supported
environment.

This structure would also make it easier to add new platform-specific guidance
later without reducing the general security model to a lowest-common-
denominator set of recommendations.

Follow-up changes could add or update working examples, such as:

  • a Cloudflare multi-Worker example using a named Service Binding entrypoint;
  • a regression test confirming that the same operation is unavailable through
    the public Worker origin;
  • a container example in which only the web process binds a public port; or
  • a Kubernetes example showing separate public and worker workloads.

Generated project documentation or coding-agent instructions could eventually
include the same invariants so that new applications begin with safer
defaults.

Scope

This proposal is about documenting application-level security responsibilities
and trust boundaries.

It does not suggest that Fedify's current protocol implementation is
vulnerable, and it does not initially require a new public API.

The primary goal is to make existing protections and application
responsibilities easier to discover and to provide a structure for documenting
secure, environment-specific implementation patterns.

AI usage disclosure

This issue draft was mainly assisted-by chatgpt codex:gpt-5-6-sol, and fully reviewed by human, and some fixed.

Fix history

  • As per /docs/manual/ folders are for manual about fedify, changed possible layout folder to /docs/secure-coding/

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Fields

Priority

None yet

Effort

None yet

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions