# Avoid string variable escaping?

**URL:** <https://discourse.gohugo.io/t/avoid-string-variable-escaping/13244>\
**Category:** support\
**Created:** [July 30, 2018, 10:57pm UTC](https://discourse.gohugo.io/t/avoid-string-variable-escaping/13244 "2018-07-30T22:57:57Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![butaca](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/butaca/32/5159_2.png) [@butaca](https://discourse.gohugo.io/u/butaca)\
**Post date:** [July 30, 2018, 10:57pm UTC](https://discourse.gohugo.io/t/avoid-string-variable-escaping/13244/1 "2018-07-30T22:57:57Z")

</div>

Hi,

I have a string variable `$v` with the value `&#97;` and the template `{{ $v }}` outputs `&amp;#97;`

This doesn’t happen if `&#97;` is directly in the template as html and not in a variable, so I guess there’s some kind of escaping going on when evaluating the variables.

Is there a way to avoid this behavior?

Thanks!

---

<div class="post-metadata">

**Author:** ![bep](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/bep/32/3332_2.png) [@bep](https://discourse.gohugo.io/u/bep)\
**Post date:** [July 30, 2018, 11:16pm UTC](https://discourse.gohugo.io/t/avoid-string-variable-escaping/13244/2 "2018-07-30T23:16:20Z")

</div>

> [@butaca](#):
>
> {{ $v }}

Try  
{{ $v | safeHTML }}

---

<div class="post-metadata">

**Author:** ![butaca](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/butaca/32/5159_2.png) [@butaca](https://discourse.gohugo.io/u/butaca)\
**Post date:** [July 30, 2018, 11:35pm UTC](https://discourse.gohugo.io/t/avoid-string-variable-escaping/13244/3 "2018-07-30T23:35:56Z")

</div>

> [@bep](#):
>
> Try  
> {{ $v | safeHTML }}

Thanks. I tried it but it doesn’t work when inside a href attribute: `<a href='{{ $v | safeHTML }}'>{{ $v | safeHTML }}</a>` outputs `<a href='&amp;#97;'>&#97;</a>`

Also tried with safeHTMLAttr with the same result.

---

<div class="post-metadata">

**Author:** ![pointyfar](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/pointyfar/32/5797_2.png) [@pointyfar](https://discourse.gohugo.io/u/pointyfar)\
**Post date:** [July 31, 2018, 1:36am UTC](https://discourse.gohugo.io/t/avoid-string-variable-escaping/13244/4 "2018-07-31T01:36:47Z")

</div>

Would [htmlUnescape](https://gohugo.io/functions/htmlunescape/) work?

---

<div class="post-metadata">

**Author:** ![butaca](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/butaca/32/5159_2.png) [@butaca](https://discourse.gohugo.io/u/butaca)\
**Post date:** [July 31, 2018, 2:01am UTC](https://discourse.gohugo.io/t/avoid-string-variable-escaping/13244/5 "2018-07-31T02:01:20Z")

</div>

kind of (it works for this minimal example).

I have an obfuscated email address in a param and it always ends escaped no matter what I try. The only solution I found is hardcoding it in the template.

It seems like the template is post processing its dynamic content.

---

<div class="post-metadata">

**Author:** ![kaushalmodi](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/kaushalmodi/32/2567_2.png) [@kaushalmodi](https://discourse.gohugo.io/u/kaushalmodi)\
**Post date:** [July 31, 2018, 10:38am UTC](https://discourse.gohugo.io/t/avoid-string-variable-escaping/13244/6 "2018-07-31T10:38:38Z")

</div>

> [@butaca](#):
>
> kind of (it works for this minimal example).
> 
> I have an obfuscated email address in a param and it always ends escaped no matter what I try.

So it would help to update your minimal example to use a fake email or something that obfuscates to a string that doesn’t work with above suggested solutions.

---

<div class="post-metadata">

**Author:** ![butaca](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/butaca/32/5159_2.png) [@butaca](https://discourse.gohugo.io/u/butaca)\
**Post date:** [July 31, 2018, 4:04pm UTC](https://discourse.gohugo.io/t/avoid-string-variable-escaping/13244/7 "2018-07-31T16:04:50Z")

</div>

> [@kaushalmodi](#):
>
> So it would help to update your minimal example to use a fake email or something that obfuscates to a string that doesn’t work with above suggested solutions.

Sure. The encoded address is [foo@bar.com](mailto:foo@bar.com). The following template:

```
  {{ $href := "m&#97;i&#108;to&#58;f&#37;6Fo&#64;&#98;ar&#46;com" }}
  {{ $address := "&#102;oo&#64;ba&#114;&#46;co&#109;"}}
  <div id="variables">
    <a href="{{ $href }}">{{ $address }}</a>
  </div>
  <div id="variables-htmlUnescape ">
    <a href="{{ $href | htmlUnescape }}">{{ $address | htmlUnescape }}</a>
  </div>
  <div id="variables-safeHTML ">
    <a href="{{ $href | safeHTML }}">{{ $address | safeHTML }}</a>
  </div>
  <div id="variables-safeHTMLAttr ">
    <a href="{{ $href | safeHTMLAttr }}">{{ $address | safeHTMLAttr }}</a>
  </div>
  <div id="variables-html ">
    <a href="{{ $href | html }}">{{ $address | html }}</a>
  </div>
  <div id="hardcoded">
    <a href="m&#97;i&#108;to&#58;f&#37;6Fo&#64;&#98;ar&#46;com">&#102;oo&#64;ba&#114;&#46;co&#109;</a>
  </div>

```

Generates:

```
  <div id="variables">
    <a href="m&amp;#97;i&amp;#108;to&amp;#58;f&amp;#37;6Fo&amp;#64;&amp;#98;ar&amp;#46;com">&amp;#102;oo&amp;#64;ba&amp;#114;&amp;#46;co&amp;#109;</a>
  </div>
  <div id="variables-htmlUnescape ">
    <a href="mailto:f%6Fo@bar.com">foo@bar.com</a>
  </div>
  <div id="variables-safeHTML ">
    <a href="m&amp;#97;i&amp;#108;to&amp;#58;f&amp;#37;6Fo&amp;#64;&amp;#98;ar&amp;#46;com">&#102;oo&#64;ba&#114;&#46;co&#109;</a>
  </div>
  <div id="variables-safeHTMLAttr ">
    <a href="m&amp;#97;i&amp;#108;to&amp;#58;f&amp;#37;6Fo&amp;#64;&amp;#98;ar&amp;#46;com">&amp;#102;oo&amp;#64;ba&amp;#114;&amp;#46;co&amp;#109;</a>
  </div>
  <div id="variables-html ">
    <a href="m&amp;#97;i&amp;#108;to&amp;#58;f&amp;#37;6Fo&amp;#64;&amp;#98;ar&amp;#46;com">&amp;#102;oo&amp;#64;ba&amp;#114;&amp;#46;co&amp;#109;</a>
  </div>
  <div id="hardcoded">
    <a href="m&#97;i&#108;to&#58;f&#37;6Fo&#64;&#98;ar&#46;com">&#102;oo&#64;ba&#114;&#46;co&#109;</a>
  </div>

```

The desired output is in the “hardcoded” div (the values are the same as the declared). I can get it to work for the address, but the href is being treated differently and always gets escaped. I even tried using the $href as the content of the `<a>` element instead of the href attribute and the output is different:

```
  <div id="href-safeHTML ">
    <a href="{{ $href | safeHTML }}">{{ $href | safeHTML }}</a>
  </div>

```

Results in:

```
  <div id="href-safeHTML ">
    <a href="m&amp;#97;i&amp;#108;to&amp;#58;f&amp;#37;6Fo&amp;#64;&amp;#98;ar&amp;#46;com">m&#97;i&#108;to&#58;f&#37;6Fo&#64;&#98;ar&#46;com</a>
  </div>

```

---

<div class="post-metadata">

**Author:** ![kaushalmodi](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/kaushalmodi/32/2567_2.png) [@kaushalmodi](https://discourse.gohugo.io/u/kaushalmodi)\
**Post date:** [July 31, 2018, 4:16pm UTC](https://discourse.gohugo.io/t/avoid-string-variable-escaping/13244/8 "2018-07-31T16:16:38Z")

</div>

I don’t understand… this:

```auto
{{ $href := "mailto:foo@bar.com" }}
    {{ $address := "foo@bar.com"}}
    <div id="variables-htmlUnescape ">
        <a href="{{ $href | htmlUnescape }}">{{ $address | htmlUnescape }}</a>
    </div>

```

gives:

```auto
<div id="variables-htmlUnescape ">
        <a href="mailto:foo@bar.com">foo@bar.com</a>
    </div>

```

Seems to work fine… So do you want to escape each and every letter as in your hardcoded div?

---

<div class="post-metadata">

**Author:** ![butaca](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/butaca/32/5159_2.png) [@butaca](https://discourse.gohugo.io/u/butaca)\
**Post date:** [July 31, 2018, 4:39pm UTC](https://discourse.gohugo.io/t/avoid-string-variable-escaping/13244/9 "2018-07-31T16:39:29Z")

</div>

> [@kaushalmodi](#):
>
> \<div id="variables-htmlUnescape “\> \<a [href="mailto:foo@bar.com](mailto:href=%22mailto:foo@bar.com)”\>foo@bar.com\</a\> \</div\>

It works in the sense that the resulting email is valid but misses the point of obfuscation.

> [@kaushalmodi](#):
>
> Seems to work fine… So do you want to escape each and every letter as in your hardcoded div?

What I want is the values preserved as in the “hardcoded” div but without hardcoding them.

---

<div class="post-metadata">

**Author:** ![butaca](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/butaca/32/5159_2.png) [@butaca](https://discourse.gohugo.io/u/butaca)\
**Post date:** [August 1, 2018, 4:48pm UTC](https://discourse.gohugo.io/t/avoid-string-variable-escaping/13244/10 "2018-08-01T16:48:44Z")

</div>

> [@butaca](#):
>
> It seems like the template is post processing its dynamic content.

I read a bit about go html/template package and it escaping the content contextually, trusting the template and not trusting the dynamic content. About href, taken from [template package - html/template - Go Packages](https://golang.org/pkg/html/template/) :

> ```
> This package understands HTML, CSS, JavaScript, and URIs. It adds sanitizing functions to each simple action pipeline, so given the excerpt
> 
> <a href="/search?q={{.}}">{{.}}</a>
> At parse time each {{.}} is overwritten to add escaping functions as necessary. In this case it becomes
> 
> <a href="/search?q={{. | urlescaper | attrescaper}}">{{. | htmlescaper}}</a>
> where urlescaper, attrescaper, and htmlescaper are aliases for internal escaping functions.
> 
> ```

I tried to bypass it without success (sorry for my go, I’m new to it): [Go Playground - The Go Programming Language](https://play.golang.org/p/xE0W1fwp9nj)

Maybe @bep knows a way to bypass the escaping?

---

<div class="post-metadata">

**Author:** ![rhcarvalho](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/rhcarvalho/32/8482_2.png) [@rhcarvalho](https://discourse.gohugo.io/u/rhcarvalho)\
**Post date:** [April 22, 2019, 4:07pm UTC](https://discourse.gohugo.io/t/avoid-string-variable-escaping/13244/11 "2019-04-22T16:07:14Z")

</div>

_Reviving for the sake of documenting a solution._

@butaca you’re absolutely spot on regarding the contextual awareness of `html/template`. That’s one of the features that makes it great!

Here’s how you can bypass it for an arbitrary HTML attribute:

**Template**

```auto
{{ $v := "&#97;" }}
<a {{ printf "href=%q" $v | safeHTMLAttr }}>{{ $v | safeHTML }}</a>

```

**Output**

```auto
<a href="&#97;">&#97;</a>

```

* * *

Note that whenever you use the `safe*` functions ( `safeHTML` , `safeHTMLAttr` , etc), it means you fully trust the input.

A malicious input could infect your website. Compare what happens when you mark unsafe values as safe:

**Template**

```auto
{{ $v := "\"><script>alert('hello')</script>" }}
<p>Safe: <a {{ printf "href=%q" $v }}>{{ $v }}</a></p>
<p>Unsafe use of safe*: <a {{ printf "href=%q" $v | safeHTMLAttr }}>{{ $v | safeHTML }}</a></p>

```

**Output**

```auto
<p>Safe: <a ZgotmplZ>&#34;&gt;&lt;script&gt;alert(&#39;hello&#39;)&lt;/script&gt;</a></p>
<p>Unsafe use of safe*: <a href="\"><script>alert('hello')</script>">"><script>alert('hello')</script></a></p>

```
