Skip to content

Serve /.well-known files by default#313

Open
kklem0 wants to merge 1 commit into
pillarjs:masterfrom
kklem0:well-known-default
Open

Serve /.well-known files by default#313
kklem0 wants to merge 1 commit into
pillarjs:masterfrom
kklem0:well-known-default

Conversation

@kklem0

@kklem0 kklem0 commented Jul 22, 2026

Copy link
Copy Markdown

Problem

Since 1.0, the default dotfiles handling ignores every dot-segment path. The removal of the deprecated hidden option ("Remove deprecated hidden option") also removed the long-standing default of not ignoring files nested inside dot directories — the behavior the README still documents today:

The default value is similar to 'ignore', with the exception that this default will not ignore the files within a directory that begins with a dot, for backward-compatibility.

So current master has a code/docs mismatch, and the behavior change silently broke RFC 8615 well-known URIs for every consumer of the default (including serve-static/express.static in Express 5):

  • ACME HTTP-01 challenges (/.well-known/acme-challenge/…, Let's Encrypt)
  • Android App Links (/.well-known/assetlinks.json)
  • iOS Universal Links (/.well-known/apple-app-site-association)
  • security.txt, OIDC discovery, and the rest of the well-known registry

These requests now 404 (or fall through to an app handler) with no diagnostics. Back in expressjs/serve-static#54, "don't ignore .well-known by default" was closed precisely because the old default served it — that resolution no longer holds.

Fix

When no explicit dotfiles option is provided, serve files under the top-level .well-known directory; everything else about dotfile handling is unchanged:

  • Other dotfiles (and dot directories) remain ignored — this deliberately does not restore the full pre-1.0 dot-directory allowance, which could expose things like /.git/config.
  • A dotfile nested inside .well-known (e.g. /.well-known/.hidden) is still ignored.
  • The check is segment-exact (parts[0] === '.well-known'), so /.well-known-evil/… gets no special treatment.
  • Any explicit dotfiles: 'allow' | 'deny' | 'ignore' behaves exactly as before — the exception only applies to the default.

This matches what sirv does by default (lukeed/sirv#50), and the README's dotfiles section is updated to describe the new (narrower) exception instead of the removed pre-1.0 one.

Testing

Added cases to the existing dotfiles suite (all 143 tests pass, eslint clean):

  • default serves /.well-known/security.txt
  • default still ignores /.well-known/.hidden
  • explicit 'ignore' 404s /.well-known/security.txt
  • explicit 'deny' 403s /.well-known/security.txt

Semver: this loosens default behavior, so it's presumably a minor (1.3.0) rather than a patch. Happy to adjust the approach (e.g. an opt-in option instead of a default) if the team prefers — though the default is what un-breaks express.static users who can't pass options through, like @react-router/serve (see remix-run/react-router#15340).

The 1.0 removal of the deprecated `hidden` option also removed the
documented default of not ignoring files within dot directories, which
silently broke RFC 8615 well-known URIs (ACME challenges, Android's
assetlinks.json, Apple's apple-app-site-association) for consumers of
the default dotfiles handling — while the README still documents the
old default.

Restore the safe subset of that behavior: when no explicit `dotfiles`
option is provided, files within the top-level `.well-known` directory
are served. Other dotfiles remain ignored, and an explicit `dotfiles`
setting behaves exactly as before.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant