Unable to set header containing JSON in Caddy v2 b15

1. My Caddy version (caddy version):

v2.0.0-beta.15 h1:Td1esMk7bebftnoBuT3gOqUGxew5HqdIKw3s36S8tNw=

2. How I run Caddy:

a. System environment:

Linux blog 4.15.0-74-generic #84-Ubuntu SMP Thu Dec 19 08:06:28 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

I’m using the DIgital Ocean image but have upgraded Caddy to the latest version v2.0.0-beta.15.

b. Command:

I’m using systemctl. The following command is how I reload after a configuration change.

systemctl reload caddy

c. Service/unit/compose file:

cat /etc/systemd/system/caddy.service

Description=Caddy Web Server

ExecStart=/usr/bin/caddy run --config /etc/caddy/Caddyfile --adapter caddyfile --resume --environ
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile --adapter caddyfile


d. My complete Caddyfile or JSON config:

blog.glvr.io {
  root * /var/www/html
  encode gzip zstd

  header {
    Referrer-Policy no-referrer
    X-Xss-Protection "1; mode=block; report='https://bill.report-uri.com/r/d/xss/enforce'"
    Report-To "\{'group':'default','max_age':3600,'endpoints':[\{'url':'https://bill.report-uri.com/a/d/g'\}],'include_subdomains':true\}"
    X-Content-Type-Options nosniff
    Content-Security-Policy "default-src 'self'"

3. The problem I’m having:

I’m trying to set the Report-To header to a value that is JSON.


I’ve tried various attempts at escaping braces and quotes but have been unable to set the header value to valid JSON. For more details on the attempts I have tried, see below.

4. Error messages and/or full log output:

~# curl -XGET -I https://blog.glvr.io

HTTP/2 200 
accept-ranges: bytes
content-security-policy: default-src 'self'
content-type: text/html; charset=utf-8
etag: "q6kdmr6l9"
last-modified: Mon, 02 Mar 2020 11:37:39 GMT
referrer-policy: no-referrer
report-to: \],'include_subdomains':true\}
x-content-type-options: nosniff
x-xss-protection: 1; mode=block; report='https://bill.report-uri.com/r/d/xss/enforce'
content-length: 8541
date: Wed, 04 Mar 2020 10:50:52 GMT

5. What I already tried:

I’ve tried a couple of things:

  1. No escaping at all

    config: Report-To "{'group':'default','max_age':3600,'endpoints':[{'url':'https://bill.report-uri.com/a/d/g'}],'include_subdomains':true}"
    result: report-to: ],'include_subdomains':true}

  2. Escape all the {

    config: Report-To "\{'group':'default','max_age':3600,'endpoints':[{'url':'https://bill.report-uri.com/a/d/g'}],'include_subdomains':true\}"
    result: report-to: ],'include_subdomains':true}

  3. Escape the outer {

    config: Report-To "\{'group':'default','max_age':3600,'endpoints':[{'url':'https://bill.report-uri.com/a/d/g'}],'include_subdomains':true\}"
    result: report-to: \],'include_subdomains':true\}

6. Links to relevant resources:

I’ve found this previous question that appears to describe the same issue: Header containing JSON.

This question links through to this PR: httpserver.Replacer: Rework loop to ignore escaped placeholder braces which has been merged.

This fix does not appear to have made it into the v2 branch: https://github.com/caddyserver/caddy/blob/v2/modules/caddyhttp/replacer.go

1 Like

Thanks for the report! Do you want to open an issue to track this? Shouldn’t be too difficult to make it possible to escape placeholders.

Another option we can do is to replace only known placeholders. However, this means that if a header config uses a placeholder that isn’t set (for some reason – ultimately depends what the placeholder is), it will still appear in the header as opposed to an empty string.

I think escaping is a fair idea though.

I’ve raised issue #3116. Many thanks.

1 Like

PR containing a fix for this has been merged: #3121.


This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.