caddy icon indicating copy to clipboard operation
caddy copied to clipboard

Nested execution of {{ directive }} in html loaded via {{httpInclude}}

Open baiomys opened this issue 1 year ago • 16 comments

Is it expected behavior?

How to disable running template code in HTML loaded via {{ httpInclude }} ? It is not secure and could lead to unpredictable results.

baiomys avatar Dec 11 '24 07:12 baiomys

Do you have an example of an httpInclude that is insecure?

The templates HTTP handler intentionally evaluates templates as interpretable HTML so that they can be used in HTML documents. (The intention is to template HTML pages, not just the text that appears within hard-coded HTML.)

I can think of ways that a template could be insecure by allowing untrusted input to be evaluated, but that is nothing new or special to Caddy templates.

mholt avatar Dec 11 '24 17:12 mholt

If content loaded to [div id="email"] contain any {{ }} directives (intentionally or unintentionally), they will be executed as well, it should be avoided.

API call is substituted by UNTRUSTED static content:

Caddyfile

domain.tld {
  tls internal

  handle_path /static/* {
    rewrite * /{uri}
    reverse_proxy destination_static:8888 {
      @error status 520 500 404
      handle_response @error {
        respond "Nothing there" 200
      }
    }
  }

  handle_path /api/* {
    root * /etc/caddy/static/templates
    templates
    file_server
    rewrite * /template.html
  }
}

TEMPLATE

{{$mailid := (.OriginalReq.URL.Path | replace "/api/" "/static/") }}

<script>
   function ifload() {
     var iframe = document.getElementById("frame");
     iframe.contentWindow.document.body.innerHTML = document.getElementById("email").innerHTML;
   }
</script>

<div id="email">
   {{httpInclude $mailid}}
</div>

<iframe id="frame" src="" onload="ifload()"/>

baiomys avatar Dec 11 '24 18:12 baiomys

There's html function to which you can pipe the output of httpInclude. You can just do {{ httpInclude | html }}, and it'll escape the HTML out of the output.

mohammed90 avatar Dec 11 '24 19:12 mohammed90

There's html function to which you can pipe the output of httpInclude. You can just do {{ httpInclude | html }}, and it'll escape the HTML out of the output.

I need to bypass execution of {{ directives }} in httpInclude content. Not escape html.
It seems Caddy engine process directives in loaded HTML code BEFORE pipelining, so this behavior can be switched off only by altering engine GO code.

To clarify situation, this is part of loaded via httpInclude content:

Logs

vzdump 9244 --mode snapshot --node reno --compress zstd --notes-template '{{guestname}}' --storage repo --remove 0 --notification-mode auto


9244: 2024-12-10 10:29:03 INFO: Starting Backup of VM 9244 (lxc)
9244: 2024-12-10 10:29:03 INFO: status = running

Caddy return error 520 function "guestname" not defined

baiomys avatar Dec 11 '24 19:12 baiomys

Ok, now I understand after seeing the example, and the issue title makes sense. Sorry for the confusion.

mohammed90 avatar Dec 11 '24 20:12 mohammed90

You can adjust the delimiters using the between subdirective: between <open_delim> <close_delim> That way you can change them from {{ }} to something else.

mholt avatar Dec 11 '24 22:12 mholt

You can adjust the delimiters using the between subdirective: between <open_delim> <close_delim> That way you can change them from {{ }} to something else.

Loadable content is THOUSANDS of externally provided e-mail messages. So there are NO delimiters that can be treated as safe. =)

Thanks for suggestion, I'll apply it as temporary solution, but creating version of httpIncludeNoscript would be much safer.

baiomys avatar Dec 11 '24 22:12 baiomys

What's a good word other than "include" or "import" for that?

mholt avatar Dec 13 '24 16:12 mholt

What's a good word other than "include" or "import" for that?

How about includeRaw?

mohammed90 avatar Dec 13 '24 18:12 mohammed90

Yeah, that could work. I'll add this enhancement to my list. :+1:

mholt avatar Dec 13 '24 19:12 mholt

Looks promising, tnx!

baiomys avatar Dec 13 '24 19:12 baiomys

Perhaps rawInclude is better to be analogous with httpInclude

mohammed90 avatar Dec 13 '24 19:12 mohammed90

Well, we might want a include variant as well, so I am leaning toward httpIncludeRaw and includeRaw if you're okay with that.

mholt avatar Dec 14 '24 05:12 mholt

Hi, folks, Happy New Year! Any progress on httpIncludeRaw ?

baiomys avatar Jan 01 '25 17:01 baiomys

httpInclude always evaluating templates is wrong IMO, the server configuration (Caddyfile) should declare what is templated and what not, for example with this caddyfile:

:80 {
  handle_path /data/* {
    root * /data
    file_server
  }

  root * /srv

  file_server
  templates
}

If I place this in /srv/index.html:

{{$data := httpInclude "/data/whatever.json"}}
{{/* do something with $data */}}

and this in /data/whatever.json:

{
  "some": { "untrusted_content": "This is an example of {{some-value}}." }
}

I would expect the content of index.html to be templated normally since it has the templates directive, but whatever.json shouldn't be templated since it only has file_server.

I believe the bug is on this line, the content is always just templated without any consideration of what it may be: https://github.com/caddyserver/caddy/blob/b3f2db233b5a71df6680b43d025bdb62ee2a999c/modules/caddyhttp/templates/tplcontext.go#L211

Correct me if I am wrong but this seems like a normal expectation... Also this is a major bug in my opinion as there is currently no way to correct this, our solution, since we have json as data is currently to just replace all instances of {{ in strings with \u007B\u007B, this is kind of a lucky case and not a solution.

davidpanic avatar Nov 13 '25 13:11 davidpanic

PRs welcome to introduce raw include variants which don't run templating, as explained above.

francislavoie avatar Nov 13 '25 13:11 francislavoie