> ## Documentation Index
> Fetch the complete documentation index at: https://docs.semgrep.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Prevent XSS for Go

This is a cross-site scripting (XSS) prevention cheat sheet by Semgrep, Inc. It contains code patterns of potential XSS in an application. Instead of scrutinizing code for exploitable vulnerabilities, the recommendations in this cheat sheet pave a safe road for developers that mitigate the possibility of XSS in your code. By following these recommendations, you can be reasonably sure your code is free of XSS.

Learn more about [Cross-site Scripting](/learn/vulnerabilities/cross-site-scripting) vulnerability concepts.

## Mitigation summary

The Go template engine in `html/template` does automatic and contextual autoescaping, which mitigates many common XSS mistakes. Some aspects of the engine are confusingly named; therefore, proper use of the library should be enforced using code scanners. You may also consider using a stricter alternative, such as `safehtml`.

### Check your project using Semgrep

```bash theme={null}
semgrep --config auto .
```

## 1. Server code: Unescaped content

### 1.A. Using the `text/template` package

`text/template` does not perform any HTML escaping.

Example:

```go theme={null}
import "text/template"
```

#### References

* [Common Go security mistakes](https://www.veracode.com/blog/secure-development/use-golang-these-mistakes-could-compromise-your-apps-security)

#### Mitigation

Ban `text/template`. Alternatively, use `html/template`, or a stricter alternative such as `safehtml`.

#### Semgrep rule

[`go.lang.security.audit.xss.import-text-template.import-text-template`](https://semgrep.dev/r/go.lang.security.audit.xss.import-text-template.import-text-template)

### 1.B. Escaped types: `template.HTML`

`template.HTML` is a special type which instructs the template engine not to escape the content.

Example:

```go theme={null}
content := template.HTML("<div>" + user.name + "</div>")
```

#### References

* [`template.HTML` documentation](https://golang.org/pkg/html/template/#HTML)

#### Mitigation

Ban `template.HTML`. Alternatively, if necessary, review each case carefully and exempt with `# nosemgrep`.

#### Semgrep rule

[`go.lang.security.audit.xss.template-html-does-not-escape.unsafe-template-type`](https://semgrep.dev/r/go.lang.security.audit.xss.template-html-does-not-escape.unsafe-template-type)

### 1.C. Escaped types: `template.HTMLAttr`

`template.HTMLAttr` is a special type which instructs the template engine not to escape the content.

Example:

```go theme={null}
content := template.HTMLAttr("class=" + user.role)
```

#### References

* [`template.HTMLAttr` documentation](https://golang.org/pkg/html/template/#HTMLAttr)

#### Mitigation

Ban `template.HTMLAttr`. Alternatively, prefer `template.HTML`, only if necessary.

#### Semgrep rule

[`go.template.security.insecure-types.go-insecure-templates`](https://semgrep.dev/r/go.template.security.insecure-types.go-insecure-templates)

### 1.D. Escaped types: `template.CSS`

`template.CSS` is a special type which instructs the template engine not to escape the content in CSS contexts.

Example:

```go theme={null}
content := template.CSS("body { color: black; }")
```

#### References

* [`template.CSS` documentation](https://golang.org/pkg/html/template/#CSS)

#### Mitigation

Ban `template.CSS`. Alternatively, if necessary, review each case carefully and exempt with `# nosemgrep`.

#### Semgrep rule

[`go.template.security.insecure-types.go-insecure-templates`](https://semgrep.dev/r/go.template.security.insecure-types.go-insecure-templates)

### 1.E. Escaped types: template.JS

The `template.JS` is a special type which instructs the template engine not to escape the content in JavaScript contexts, such as between `script` tags.

Example:

```go theme={null}
content := template.JS("var name = " + user.name)
```

#### References

* [`template.JS` documentation](https://golang.org/pkg/html/template/#JS)
* [Example demonstrating unsafe usage](https://goplay.space/#th5GWEwMck2)
* [Example demonstrating safe usage](https://goplay.space/#SfeTNbNARUq)

#### Mitigation

Ban `template.JS`. Alternatively, place JavaScript code in files separate from HTML and serve them using the `src` attribute.

#### Semgrep rule

[`go.template.security.insecure-types.go-insecure-templates`](https://semgrep.dev/r/go.template.security.insecure-types.go-insecure-templates)

### 1.F. Escaped types: template.JSStr

The `template.JSStr` is a special type which instructs the template engine not to escape the content when in JavaScript contexts and in a string.

Example:

```go theme={null}
content := template.JSStr("Error by: " + user.name)
```

#### References

* [`template.JSStr` documentation](https://golang.org/pkg/html/template/#JSStr)

#### Mitigation

Ban `template.JSStr`. Alternatively, place JavaScript code in files separate from HTML and serve them using the `src` attribute.

#### Semgrep rule

[`go.template.security.insecure-types.go-insecure-templates`](https://semgrep.dev/r/go.template.security.insecure-types.go-insecure-templates)

### 1.G. Escaped types: `template.Srcset`

`template.Srcset` is a special type which instructs the template engine not to escape the content.

Example:

```go theme={null}
content := template.Srcset("https://" + user.stylepageurl)
```

#### References

* [`template.Srcset` documentation](https://golang.org/pkg/html/template/#Srcset)

#### Mitigation

Ban `template.Srcset`. Alternatively, prefer `template.HTML`, only if necessary.

#### Semgrep rule

[`go.template.security.insecure-types.go-insecure-templates`](https://semgrep.dev/r/go.template.security.insecure-types.go-insecure-templates)

### 1.H. Escaped types: template.URL

The `template.URL` is a special type which instructs the template engine not to escape the content.

Example:

```go theme={null}
content := template.URL("https://" + user.stylepageurl)
```

#### References

* [`template.URL` documentation](https://golang.org/pkg/html/template/#URL)

#### Mitigation

Ban `template.URL`. Alternatively, if necessary, review each case carefully and exempt with `# nosem`.

#### Semgrep rule

[`go.template.security.insecure-types.go-insecure-templates`](https://semgrep.dev/r/go.template.security.insecure-types.go-insecure-templates)

## 2. Server code: Bypassing the template engine

### 2.A. Writing directly to the response object: fmt.Fprintf()

Writing directly to the response object bypasses the template engine which means content will not be autoescaped. This could introduce a XSS vulnerability.

Example:

```go theme={null}
fmt.Fprintf(w, "<div>" + user.name + "</div>")
```

#### References

* [Go Security - XSS](https://blogtitle.github.io/robn-go-security-pearls-cross-site-scripting-xss/)

#### Mitigation

Ban using `fmt.Printf` with the HTTP response writer. Alternatively, use `html/template` to render data to users.

#### Semgrep rule

[`go.lang.security.audit.xss.no-fprintf-to-responsewriter.no-fprintf-to-responsewriter`](https://semgrep.dev/r/go.lang.security.audit.xss.no-fprintf-to-responsewriter.no-fprintf-to-responsewriter)

### 2.C. Writing directly to the response object: `io.WriteString()`

Writing directly to the response object bypasses the template engine which means content will not be autoescaped. This could introduce a XSS vulnerability.

Example:

```go theme={null}
io.WriteString(w, "<div>" + user.name + "</div>")
```

#### References

* [Go Security - XSS](https://blogtitle.github.io/robn-go-security-pearls-cross-site-scripting-xss/)
* [`io.WriteString` documentation](https://golang.org/pkg/io/#WriteString)

#### Mitigation

Ban using `io.WriteString` with the HTTP response writer. Alternatively, use `html/template` to render data to users.

#### Semgrep rule

[`go.lang.security.audit.xss.no-io-writestring-to-responsewriter.no-io-writestring-to-responsewriter`](https://semgrep.dev/r/go.lang.security.audit.xss.no-io-writestring-to-responsewriter.no-io-writestring-to-responsewriter)

### 2.C. Writing directly to the response object: w\.Write() method

Writing directly to the response object bypasses the template engine which means content will not be autoescaped. This could introduce a XSS vulnerability.

Example:

```go theme={null}
writer.Write([]byte("<div>" + user.name + "</div>"))
```

#### References

* [Go Security - XSS](https://blogtitle.github.io/robn-go-security-pearls-cross-site-scripting-xss/)
* [Sample vulnerable app](https://gist.github.com/minusworld/62d30f299072bc6c0979778f4c00242f)

#### Mitigation

Ban using the `Write` method of the HTTP response writer. Alternatively, use `html/template` to render data to users.

#### Semgrep rule

[`go.lang.security.audit.xss.no-direct-write-to-responsewriter.no-direct-write-to-responsewriter`](https://semgrep.dev/r/go.lang.security.audit.xss.no-direct-write-to-responsewriter.no-direct-write-to-responsewriter)
