Output Encoding

Overview

This section contains recommendations for implementing output encoding.

General

In many scenarios, an application displays data that was gathered from untrusted sources such as user input. This can lead to vulnerabilities that an attacker leverage to perform attacks such as Cross-Site Scripting. To mitigate such security issues untrusted output must be encoded properly depending on the context it is being used.

  • Use your framework's default output encoding or use a well-vetted output encoding library for each context.

HTML Context

HTML Context is when untrusted data is displayed between two HTML tags such as <div> or <p>. For example:

<div> $untrusted_data </div>
  • All untrusted data that is going to be displayed within an HTML context, must encode all non-alphanumeric characters with their HTML entity before printing. For example:

  • Use your framework's default HTML output encoding or use a well-vetted HTML output encoding library.

HTML Attribute Context

HTML Attribute Context is when untrusted data is displayed within an HTML attribute value such as <div> or <p>. For example:

<div attr="$untrusted_data">
  • Close all HTML attributes with quotation marks such as ' or ".

Clarification

If an HTML attribute is properly quoted, only a few characters need to be encoded. Otherwise, all non-alphanumeric characters need to be encoded by their respective HTML entity.

Properly quoted

<div attr="$untrusted_data">
<div attr='$untrusted_data'>

Not properly quoted

<div attr=$untrusted_data>
  • Do not use not-safe HTML attributes with untrusted data even after output escaping.

List of safe HTML attributes

align, alink, alt, bgcolor, border, cellpadding, cellspacing, class, color, cols, colspan, coords, dir, face, height, hspace, ismap, lang, marginheight, marginwidth, multiple, nohref, noresize, noshade, nowrap, ref, rel, rev, rows, rowspan, scrolling, shape, span, summary, tabindex, title, usemap, valign, value, vlink, vspace, width

  • All untrusted data that is going to be displayed within an HTML attribute context, must encode all non-alphanumeric characters with their HTML entity before printing. For example:

  • Use your framework's default HTML attribute output encoding or use a well-vetted HTML attribute output encoding library.

JavaScript Context

JavaScript Context is when untrusted data is displayed within JavaScript. For example:

<script>
    ...
    alert('$untrusted_data')
    ...
</script>

<div onmouseover="'$untrusted_data'"></div>
  • Display untrusted data only within quoted locations.

Clarification

The only safe location to display untrusted data within JavaScript is at quoted locations. For example:

<script>alert('$untrusted_data')</script>
<script>x='$untrusted_data'</script>
<div onmouseover="'$untrusted_data'"></div>
  • Do not display untrusted data within dangerous JavaScript contexts.

    • Callback functions.

    • JavaScript event handlers: onclick(), onerror(), onmouseover().

    • JavaScript functions that parse and execute JavaScript code: eval(), setInterval(), setTimeout().

  • All untrusted data that is going to be displayed within a JavaScript context, must encode all non-alphanumeric characters with their respective hexadecimal notation \xHH. For example:

  • Use your framework's default JavaScript output encoding or use a well-vetted JavaScript output encoding library.

CSS Context

CSS Context is when untrusted data is displayed within CSS. For example:

<style> selector { property : "$untrusted_data"; } </style>
<span style="property : '$untrusted_data'">Content</span>
  • Display untrusted data only on CSS property values. Other CSS contexts are unsafe.

  • All untrusted data that is going to be displayed within a CSS context, must encode all non-alphanumeric characters in their respective hexadecimal notation \xHH. For example:

  • Do not use expression() function within a CSS property value. In addition, use input validation to ensure that untrusted data displayed in CSS property value does not contain the expression() function.

Example of using expression() within CSS property
background-color: expression( alert(1) );
  • Do not use JavaScript URI scheme javascript: within CSS URL context. In addition, use input validation to ensure that untrusted data displayed in CSS URL context does not contain the javascript: URL scheme.

Example of using javascript URL scheme within CSS URL context
background-image: url("javascript:alert(1)");
  • Use your framework's default CSS output encoding or use a well-vetted CSS output encoding library.

URL Context

URL Context is when untrusted data is displayed within an URL. For example:

<a href="https://website.local?test=$untrusted_data">link</a >
<img src="/images/$untrusted_data" />
  • Encode all non-alphanumeric characters with their percentage-encoding hexadecimal representation %xx. For example:

An example of using the dangerous javascript scheme
<a href='javascript:doSomething()'>...</a>
  • Use your framework's default URL output encoding or use a well-vetted URL output encoding library.

Dangerous Contexts

The following locations are known as dangerous contexts even after performing output encoding, therefore, displaying untrusted data on them must be avoided.

  • Do not display untrusted data within a script tag.

    <script>Directly in a script</script>
  • Do not display untrusted data within HTML comments.

    <!-- Inside an HTML comment -->
  • Do not display untrusted data directly in CSS.

    <style>Directly in CSS</style>
  • Do not display untrusted data to define an HTML attribute name.

    <div ToDefineAnAttribute=test />
  • Do not display untrusted data to define an HTML tag name.

    <ToDefineATag href="/test" />

Untrusted Data that must be encoded

Perform output encoding for all user-controlled data that is displayed within any of the above contexts and are passed in:

  • Query parameters or URL/GET parameters.

    GET /items?sort_by=created_at HTTP/1.1
    Host: website.local
    Cookie: session_id=cf565bc0aaf6560a56c9e6d8632baa58
  • HTTP headers.

    GET /v2/user HTTP/1.1
    Host: api.website.local
    PRIVATE-TOKEN: cf565bc0aaf6560a56c9e6d8632baa58
    GET /v2/user HTTP/1.1
    Host: api.website.local
    Authorization: Bearer cf565bc0aaf6560a56c9e6d8632baa58
  • Cookies.

    GET / HTTP/1.1
    Host: website.local
    Cookie: session_id=cf565bc0aaf6560a56c9e6d8632baa58
  • HTTP body.

    POST /v2/user HTTP/1.1
    Host: api.website.local
    Authorization: Bearer cf565bc0aaf6560a56c9e6d8632baa58
    Content-Type: application/json
    
    {
        "email": "username@domain.local"
    }
    POST /v2/user HTTP/1.1
    Host: api.website.local
    Authorization: Bearer cf565bc0aaf6560a56c9e6d8632baa58
    Content-Type: application/x-www-form-urlencoded
    
    email=username@domain.local

Output encoding implementation

You can use the html/template package to perform output encoding safely in Go. html/template performs contextual escaping, so actions can appear within JavaScript, CSS, and URI contexts.

<h1>{{.PageTitle}}</h1>
<a title='{{.}}'>
<a href="/{{.}}">
<a href="?q={{.}}">
<a onx='f("{{.}}")'>
<a style="align: {{.}}">
<a style="background: '{{.}}'>
<a style="background: url('{{.}}')>
<style>p.{{.}} {color:red}</style>
<script>var pair = {{.}};</script>

See html/template documentation for more detailed use.

References

Last updated