go.lang.security.audit.net.wip-xss-using-responsewriter-and-printf.wip-xss-using-responsewriter-and-printf

Verifed by r2c
Community Favorite
profile photo of semgrepsemgrep
Author
98,168
Download Count*

Found data going from url query parameters into formatted data written to ResponseWriter. This could be XSS and should not be done. If you must do this, ensure your data is sanitized or escaped.

Run Locally

Run in CI

Defintion

rules:
  - id: wip-xss-using-responsewriter-and-printf
    patterns:
      - pattern-inside: |
          func $FUNC(..., $W http.ResponseWriter, ...) {
            ...
            var $TEMPLATE = "..."
            ...
            $W.Write([]byte(fmt.$PRINTF($TEMPLATE, ...)), ...)
            ...
          }
      - pattern-either:
          - pattern: |
              $PARAMS = r.URL.Query()
              ...
              $DATA, $ERR := $PARAMS[...]
              ...
              $INTERM = $ANYTHING(..., $DATA, ...)
              ...
              $W.Write([]byte(fmt.$PRINTF(..., $INTERM, ...)))
          - pattern: |
              $PARAMS = r.URL.Query()
              ...
              $DATA, $ERR := $PARAMS[...]
              ...
              $INTERM = $DATA[...]
              ...
              $W.Write([]byte(fmt.$PRINTF(..., $INTERM, ...)))
          - pattern: |
              $DATA, $ERR := r.URL.Query()[...]
              ...
              $INTERM = $DATA[...]
              ...
              $W.Write([]byte(fmt.$PRINTF(..., $INTERM, ...)))
          - pattern: |
              $DATA, $ERR := r.URL.Query()[...]
              ...
              $INTERM = $ANYTHING(..., $DATA, ...)
              ...
              $W.Write([]byte(fmt.$PRINTF(..., $INTERM, ...)))
          - pattern: |
              $PARAMS = r.URL.Query()
              ...
              $DATA, $ERR := $PARAMS[...]
              ...
              $W.Write([]byte(fmt.$PRINTF(..., $DATA, ...)))
    message: Found data going from url query parameters into formatted data written
      to ResponseWriter. This could be XSS and should not be done. If you must
      do this, ensure your data is sanitized or escaped.
    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
      category: security
      technology:
        - go
      confidence: MEDIUM
      references:
        - https://owasp.org/Top10/A03_2021-Injection
      cwe2022-top25: true
      cwe2021-top25: true
      subcategory:
        - vuln
      likelihood: LOW
      impact: MEDIUM
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Cross-Site-Scripting (XSS)
    severity: WARNING
    languages:
      - go

Examples

wip-xss-using-responsewriter-and-printf.go

package main

import (
	"fmt"
	"log"
	"net/http"
)

func getMovieQuote() map[string]string {
	m := make(map[string]string)
	m["quote"] = "I'll be back."
	m["movie"] = "The Terminator"
	m["year"] = "1984"

	return m
}

func indexPage(w http.ResponseWriter, r *http.Request) {
    const tme = `<html>`

	const template = `
	<html>
	<body>
	  <h1>Random Movie Quotes</h1>
	  <h2>%s</h2>
	  <h4>~%s, %s</h4>
	</body>
	</html>`

	quote := getMovieQuote()

	quoteText := quote["quote"]
	movie := quote["movie"]
	year := quote["year"]

	w.WriteHeader(http.StatusAccepted)
	w.Write([]byte(fmt.Sprintf(template, quoteText, movie, year)))
}

func errorPage(w http.ResponseWriter, r *http.Request) {
    // ruleid: wip-xss-using-responsewriter-and-printf
	params := r.URL.Query()
	urls, ok := params["url"]
	if !ok {
		log.Println("Error")
		return
	}
	url := urls[0]

    const template = `
	<html>
	<body>
	  <h1>error; page not found. <a href="%s">go back</a></h1>
	</body>
	</html>`

	w.WriteHeader(http.StatusAccepted)
	w.Write([]byte(fmt.Sprintf(template, url)))
}

func main() {
	http.HandleFunc("/", indexPage)
	http.HandleFunc("/error", errorPage)
	http.ListenAndServe(":8080", nil)
}