generic.html-templates.security.unquoted-attribute-var.unquoted-attribute-var

Community Favorite
profile photo of semgrepsemgrep
Author
76,191
Download Count*

Detected a unquoted template variable as an attribute. If unquoted, a malicious actor could inject custom JavaScript handlers. To fix this, add quotes around the template expression, like this: "{{ expr }}".

Run Locally

Run in CI

Defintion

rules:
  - id: unquoted-attribute-var
    message: 'Detected a unquoted template variable as an attribute. If unquoted, a
      malicious actor could inject custom JavaScript handlers. To fix this, add
      quotes around the template expression, like this: "{{ expr }}".'
    metadata:
      cwe:
        - "CWE-79: Improper Neutralization of Input During Web Page Generation
          ('Cross-site Scripting')"
      owasp:
        - A07:2017 - Cross-Site Scripting (XSS)
        - A03:2021 - Injection
      references:
        - https://flask.palletsprojects.com/en/1.1.x/security/#cross-site-scripting-xss
      category: security
      technology:
        - html-templates
      confidence: LOW
      cwe2022-top25: true
      cwe2021-top25: true
      subcategory:
        - audit
      likelihood: LOW
      impact: MEDIUM
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Cross-Site-Scripting (XSS)
    languages:
      - generic
    paths:
      include:
        - "*.html"
        - "*.mustache"
        - "*.hbs"
    severity: WARNING
    patterns:
      - pattern-inside: <$TAG ...>
      - pattern-not-inside: ="..."
      - pattern-not-inside: ='...'
      - pattern: "{{ ... }}"
    fix-regex:
      regex: "{{(.*?)}}"
      replacement: '"{{\1}}"'

Examples

unquoted-attribute-var.html

{% extends "container.html" %}

{% block opengraph %}

<meta property="og:locale" content="en_US" />
<meta property="og:type" content="website" />
<meta property="og:site_name" content="semgrep" />
<meta property="og:description" content="content" />
<!-- ruleid: unquoted-attribute-var -->
<meta property="og:image" content={{ url_for('static', filename='picture.jpg', _external=True) }} />
<meta property="og:image:type" content="image/jpeg" />
<meta property="og:image:width" content="600" />
<meta property="og:image:height" content="600" />
<!-- ok -->
<meta property="not-real-only-for-testing" content="{{ safe }}" />

<!-- Google OAuth sign-in -->
<meta name="google-signin-scope" content="profile email openid">
<!-- ruleid: unquoted-attribute-var -->
<meta name="google-signin-client_id" content={{ client_id  }}>
<!-- ok: unquoted-attribute-var -->
<script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?serve={{ carbonad_serve }}&placement={{ carbonad_placement }}" id="_carbonads_js"></script>

{% endblock %}


<!-- extra tests -->

<!-- ok: unquoted-attribute-var -->
<script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?serve={{carbonad_serve}}&placement={{carbonad_placement}}" id="_carbonads_js"></script>

<!-- ruleid: unquoted-attribute-var -->
<script async type="text/javascript" src= {{ link }} id="_carbonads_js"></script>
<!-- ruleid: unquoted-attribute-var -->
<script async type="text/javascript" src={{ link }} id="_carbonads_js"></script>
<!-- ruleid: unquoted-attribute-var -->
<script async type="text/javascript" src= {{ link }}
     id="_carbonads_js"></script>
<script
     async
     type="text/javascript"
     // ruleid: unquoted-attribute-var
     src= {{ link }}
     id="_carbonads_js">
</script>


<!-- ok: unquoted-attribute-var -->
<script async type="text/javascript" src=" {{ link }}" id="_carbonads_js"></script>
<!-- ok: unquoted-attribute-var -->
<script async type="text/javascript" src=' {{ link }}' id="_carbonads_js"></script>
<!-- ok: unquoted-attribute-var -->
<script async type="text/javascript" src="{{ link }}" id="_carbonads_js"></script>
<!-- ok: unquoted-attribute-var -->
<script async type="text/javascript" src="{{ link }}"
     id="_carbonads_js"></script>

<!-- ok: unquoted-attribute-var -->
<div class="upper">
     {{ paragraph_text }}
</div>

{% if scan_url %}
    <h2>Semgrep Scan Results for <a href="{{scan_url}}"> {{scan_title}} </a></h2>
{% else %}
    <h2>Semgrep Scan Results for {{scan_title}} </h2>
{% endif %}
{% for check_id, findings in findings_by_id.items() %}
    <!-- ok: unquoted-attribute-var -->
    <h3> rule: <a href="https://semgrep.dev/r?q={{check_id}}"> {{check_id}} </a> </h3>
    <ul>
        {% for finding in findings %}
        <li>
            {% if repo_url %}
            <!-- ok: unquoted-attribute-var -->
            <a href="{{repo_url}}/blob/{{commit}}/{{finding['path']}}#L{{finding['line']}}"> {{finding["path"]}}:{{finding["line"]}} </a>
            {% else %}
            {{finding["path"]}}:{{finding["line"]}}
            {% endif %}
            <p> Finding Message: {{finding["message"]}} </p>
        </li>
        {% endfor %}
    </ul>
    <hr/>
{% endfor %}