Skip to main content
Redhat Developers  Logo
  • AI

    Get started with AI

    • Red Hat AI
      Accelerate the development and deployment of enterprise AI solutions.
    • AI learning hub
      Explore learning materials and tools, organized by task.
    • AI interactive demos
      Click through scenarios with Red Hat AI, including training LLMs and more.
    • AI/ML learning paths
      Expand your OpenShift AI knowledge using these learning resources.
    • AI quickstarts
      Focused AI use cases designed for fast deployment on Red Hat AI platforms.
    • No-cost AI training
      Foundational Red Hat AI training.

    Featured resources

    • OpenShift AI learning
    • Open source AI for developers
    • AI product application development
    • Open source-powered AI/ML for hybrid cloud
    • AI and Node.js cheat sheet

    Red Hat AI Factory with NVIDIA

    • Red Hat AI Factory with NVIDIA is a co-engineered, enterprise-grade AI solution for building, deploying, and managing AI at scale across hybrid cloud environments.
    • Explore the solution
  • Learn

    Self-guided

    • Documentation
      Find answers, get step-by-step guidance, and learn how to use Red Hat products.
    • Learning paths
      Explore curated walkthroughs for common development tasks.
    • Guided learning
      Receive custom learning paths powered by our AI assistant.
    • See all learning

    Hands-on

    • Developer Sandbox
      Spin up Red Hat's products and technologies without setup or configuration.
    • Interactive labs
      Learn by doing in these hands-on, browser-based experiences.
    • Interactive demos
      Click through product features in these guided tours.

    Browse by topic

    • AI/ML
    • Automation
    • Java
    • Kubernetes
    • Linux
    • See all topics

    Training & certifications

    • Courses and exams
    • Certifications
    • Skills assessments
    • Red Hat Academy
    • Learning subscription
    • Explore training
  • Build

    Get started

    • Red Hat build of Podman Desktop
      A downloadable, local development hub to experiment with our products and builds.
    • Developer Sandbox
      Spin up Red Hat's products and technologies without setup or configuration.

    Download products

    • Access product downloads to start building and testing right away.
    • Red Hat Enterprise Linux
    • Red Hat AI
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform
    • See all products

    Featured

    • Red Hat build of OpenJDK
    • Red Hat JBoss Enterprise Application Platform
    • Red Hat OpenShift Dev Spaces
    • Red Hat Developer Toolset

    References

    • E-books
    • Documentation
    • Cheat sheets
    • Architecture center
  • Community

    Get involved

    • Events
    • Live AI events
    • Red Hat Summit
    • Red Hat Accelerators
    • Community discussions

    Follow along

    • Articles & blogs
    • Developer newsletter
    • Videos
    • Github

    Get help

    • Customer service
    • Customer support
    • Regional contacts
    • Find a partner

    Join the Red Hat Developer program

    • Download Red Hat products and project builds, access support documentation, learning content, and more.
    • Explore the benefits

Cross-site scripting: Explanation and prevention with Go

June 28, 2022
Sandipan Roy
Related topics:
GoSecurity
Related products:
Developer Toolset

    Have you ever encountered a pop-up when visiting a web page or browsing a particular item on a site? Imagine if these pop-ups were carriers that delivered malicious payloads to your devices or captured confidential information. This is a type of cyber attack called cross-site scripting, or XSS. Cross-site scripting is one of the most common attacks in 2022, and it made the OWASP top 10 web application security risks. Let's take a tour of cross-site scripting and learn how an attacker executes malicious JavaScript code on input parameters, creates pop-ups to deface web applications, and can hijack an active user session.

    How JavaScript is used in XSS attacks

    A dynamic web application is set up with three key features:

    1. HTML specifies the complete structure.
    2. CSS configures the overall look and feel.
    3. JavaScript adds powerful interactions to the application, such as warning popups, rollover effects, drop-down menus, and more.

    JavaScript is the most popular scripting language. 95% of all websites are built and run via JavaScript. It implements interesting and powerful interactive features, and acts according to the user's actions.

    Actions associated with executing JavaScript code include:

    • onclick: Executes JavaScript when the user clicks on a box or link.
    • onload: Executes JavaScript after a web page or image is completely loaded. An example:
      <body onload=alert('Welcome to Red Hat')>
    • onmouseover: Triggers JavaScript when the mouse passes over a URL link. An example:
      <a onmouseover=alert("redhat.com")>Contribute</a>
    • onmouseout: Triggers JavaScript if the mouse moves out of the window without clicking a URL.
    • onunload: Triggers JavaScript when the user leaves the web page by closing the browser or clicking a link.

    XSS is a client-side code injection attack. In this kind of attack, websites are injected with malicious JavaScript code. XSS occurs when input parameters have not been correctly handled or validated in web applications, which allows an attacker to send malicious JavaScript code to a different end user. The end user's browser does not recognize it as a malicious script and falls into the XSS trap. This type of attack does not threaten users directly with a payload, but the attacker targets the XSS vulnerability by injecting a malicious script on a web page that seems to be a real part of the website. Thus, when any user visits this website, the XSS-afflicted website sends malicious JavaScript code to the user's browser without their knowledge.

    Types of XSS attacks

    There are a variety of types of XSS attacks, divided into three major categories:

    • Stored XSS, also known as permanent or type I XSS. In stored attacks, target servers store the injected script forever. The scripts maybe be stored in a database, on servers, or in forum comments. The victim unwittingly downloads that stored script from the server when attempting to access these resources.
    • Reflected XSS, also known as type-II or non-persistent XSS. These attacks happen when a web application instantly acknowledges the user's input without inspecting what has been entered. The attacker sends a malicious link via phishing to trick the user, and not store it on the webserver. There are two major types of reflected XSS: reflected XSS GET and reflected XSS POST.
    • DOM-based XSS: DOM-based XSS is a well-known vulnerability that happens in a document object model (DOM). The DOM defines web page segments such as the title, heading, table, forms, or a well-structured HTML page. If HTML documents are loaded into a web browser, they are transformed into a document object.

    3 defense strategies for XSS attacks

    Preventing cross-site scripting (XSS) attacks can be complicated, but these basic defense strategies are effective.

    Have a content security policy

    A content security policy (CSP) is a browser feature that allows you to create source lists for client-side web application resources, including JavaScript, CSS, and images. The CSP directs the browser to execute or display resources from specific sources using a special HTTP header.

    In this example, the server only allows access to documents that are loaded over HTTPS via the single origin developers.redhat.com:

    
    Content-Security-Policy: default-src https://developers.redhat.com
    
    

    Deploy the X-XSS-Protection header

    The XSS filter in recent web browsers is enabled by the X-XSS-Protection HTTP response header. Because the header is normally enabled by default, its function is to re-enable the filter for a specific website if the user has disabled it.

    Make use of modern development frameworks

    Modern JavaScript frameworks like AngularJS and ReactJS, along with server-side templating systems like Go Templates, offer good protection against reflected cross-site scripting.

    Vulnerable code examples

    In the previous sections, we examined JavaScript and its vulnerabilities. But a secure backend system like Go's HTTP Package can block misleading JavaScript functionality. Let's use this package to illustrate some analytic techniques.

    In our first example, the server() method reads the parameter XYZ from the query string and returns it in the HTTP response. This method also handles HTTP GET requests. The http.DetectContentType function determines the default content-type response header.

    
    package main
    import "io"
    import "net/http"
    
    func server(w http.ResponseWriter, r *http.Request) {
     io.WriteString(w, r.URL.Query().Get("XYZ"))
    }
    
    func main() {
     http.HandleFunc("/", server)
     http.ListenAndServe(":5000", nil)
    }
    

    The content-type is set to text/plain when delivering a payload with XYZ=OpenSource, as you can see using a browser's developer tool (see Figure 1). This is not dangerous and is presented by the browser as plain text.

    Firefox developer tool
    Figure 1: Firefox developer tool shows the network header request.
    Figure 1: Firefox's developer tool shows the network header request.

    When I submit a request using XYZ=<script>alert("RedHat")</script>, the response's Content-Type is set to text/html, exposing the user to a cross-site scripting attack (see Figure 2).

    Firefox developer tool
    Figure 2: Executing our malicious JavaScript code processed by the backend.

    This JavaScript delivery can do harmful things, and we must fix it. Fortunately, changing a simple package in Go can prevent it.

    The example vulnerability can be minimized by encoding the user-controlled parameter's output. Several output encoding routines are included in the html/template package in Go. The problem in this example can be solved by using the HTMLEscapeString method to perform output encoding on the user-supplied input:

    
    import "io"
    import "net/http"
    
    func server(w http.ResponseWriter, r * http.Request) {
        encodedParam = template.HTMLEscapeString(r.URL.Query().Get("XYZ"))
        io.WriteString(w, encodedParam)
    }
    
    func main() {
        http.HandleFunc("/", server)  http.ListenAndServe(":8080", nil)
    }
    
    

    Now let's consider a second example. The server() function reads the parameter error from the query string and adds it to the template (text/template module) that handles HTTP GET requests. The http.DetectContentType function determines the default content-type response header.

    
    import "net/http"
    import "text/template"
    
    func server(w http.ResponseWriter, r *http.Request) {
    error := r.URL.Query().Get("XYZ")
    tmpl := template.New("ERROR")
    tmpl, _ = tmpl.Parse(`{{define "T"}}{{.}}{{end}}`)
    tmpl.ExecuteTemplate(w, "T", error)
    }
    
    func main() {
    http.HandleFunc("/", server)
    http.ListenAndServe(":5000", nil)
    }
    
    

    When I submit a request using XYZ=<script>alert("RedHat")</script>, the response's content-type sets to text/html, exposing the user to cross-site scripting, as shown in Figure 3.

    Firefox developer tool
    Figure 3: Executing the malicious JavaScript code and successfully injecting our code.

    To fix this vulnerable code, replace the text/template import with html/template with built-in output encoding capabilities:

    
    import "net/http"
    import "html/template"
    
    func server(w http.ResponseWriter, r *http.Request) {
        error: = r.URL.Query().Get("XYZ")
        tmpl: = template.New("ERROR")
        tmpl, _ = tmpl.Parse(`{{define "T"}}{{.}}{{end}}`)
        tmpl.ExecuteTemplate(w, "T", error)
    }
    
    func main() {
        http.HandleFunc("/", server)
        http.ListenAndServe(":5000", nil)
    }

    When a request with XYZ=<script>alert("RedHat")</script> is sent, the updated code successfully encodes the payload (see Figure 4). The fixed backend code has successfully filtered the attack, preventing it from executing malicious JavaScript code.

    Firefox developer tool
    Figure 4: Executing malicious JavaScript code but backend blocked the request.
    Figure 4: The backend blocks a request for malicious JavaScript code.

    Conclusion

    Cutting-edge programming languages like Go make it easy to fix security issues such as cross-site scripting, server-side request forgery, and comment injections. With secure coding practices and continuous security testing, you can prevent various cyber-attacks. Learn more about secure coding practice by reviewing the OWASP secure coding practice guide, or read Black Hat Go for information about security penetration testing.

    Last updated: February 5, 2024

    Recent Posts

    • Debugging image mode with Red Hat OpenShift 4.20: A practical guide

    • EvalHub: Because "looks good to me" isn't a benchmark

    • SQL Server HA on RHEL: Meet Pacemaker HA Agent v2 (tech preview)

    • Deploy with confidence: Continuous integration and continuous delivery for agentic AI

    • Every layer counts: Defense in depth for AI agents with Red Hat AI

    What’s up next?

    Podman is one of the next-generation container tools (along with buildah and skopeo) included in Red Hat Enterprise Linux 7 and RHEL 8. The Podman Basics Cheat Sheet covers all of the commands that focus on images, containers, and container resources.

    Get the cheat sheet
    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Platforms

    • Red Hat AI
    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform
    • See all products

    Build

    • Developer Sandbox
    • Developer tools
    • Interactive tutorials
    • API catalog

    Quicklinks

    • Learning resources
    • E-books
    • Cheat sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site status dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit
    © 2026 Red Hat

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility

    Chat Support

    Please log in with your Red Hat account to access chat support.