Skip to content

caddyfile: reject site blocks with unbalanced braces - #8375

Merged
steadytao merged 2 commits into
caddyserver:masterfrom
0xABCD01:caddyfile-unbalanced-braces
Nov 8, 2026
Merged

steadytao merged 2 commits into
caddyserver:masterfrom
0xABCD01:caddyfile-unbalanced-braces

Conversation

@0xABCD01

@0xABCD01 0xABCD01 commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

Fixes #8374

The Caddyfile parser accepted two unbalanced-brace shapes:

  • A braced site block missing its closing brace, when the last directive had its own block — the directive's closing brace was counted as the site block's close, because Dispenser.Next() at EOF leaves the cursor on the last token.
  • A stray } after a braceless site, which directives() treated as the end of the block.

Parse now tracks whether the directives of a block were terminated by the block's own closing brace. Running out of tokens inside a braced block returns unexpected EOF, and a } in a braceless block returns Unexpected '}' because no matching opening brace, the same message directive() already used for that shape.

Tests: new cases in the TestParseAll table (6 error cases covering both issue shapes, plus an unclosed global options block, and 2 valid controls with nested directive blocks). go test ./caddyconfig/caddyfile/ -count=1 and go test -short ./caddyconfig/... . pass. With the patched binary, caddy adapt rejects both examples from the issue (exit 1) and adapts a valid nested config cleanly (exit 0).

Three things worth calling out:

  1. This PR also flips the premise of the existing TestWrapUnbracedSiteIdempotentReproducer: its fuzz-derived input is the issue's case-2 shape (a stray } after a braceless site), so Parse now rejects it; the formatter-idempotency assertion on the same input is kept unchanged.
  2. For a site block missing its closing brace where the last directive has no block of its own (:8080 { file_server), the error changes from the previous incidental syntax error: unexpected token 'file_server', expecting '}' to unexpected EOF, so all missing-close shapes report the same error.
  3. Out of scope, unchanged by this PR: a } appearing where a site address is expected (e.g. a lone } or a stray } after a properly closed site block) is still read by Parse as a site key, exactly as on master; caddy adapt rejects such blocks downstream. That is a separate address-parsing behaviour, not one of the shapes in this issue.

Assistance Disclosure

This change was prepared with AI assistance (Claude). I reviewed the diff, reproduced the bug on master before the fix, and verified the fix with the package tests and caddy adapt runs described above.

A braced site block whose last directive has its own block was
accepted with its closing brace missing, because the directive's
closing brace satisfied the check for the site block's. A stray
closing brace after a braceless site was likewise accepted as the
end of the block.

Track whether the directives of a block were terminated by the
block's own closing brace: running out of tokens in a braced block
is an error, and a closing brace in a braceless block is an error.

Fixes caddyserver#8374
@caddy-cla

caddy-cla Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

✅ Contributor License Agreement

All identified contributors have signed the CLA. Thank you!

@francislavoie francislavoie added this to the v2.12.0 milestone Nov 7, 2026
@steadytao steadytao added the bug 🐞 Something isn't working label Nov 8, 2026
@steadytao
steadytao enabled auto-merge (squash) November 8, 2026 11:10
@steadytao
steadytao merged commit 2563d48 into caddyserver:master Nov 8, 2026
27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug 🐞 Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

caddyfile: parser accepts site blocks with unbalanced braces

3 participants