VYPR
Moderate severityNVD Advisory· Published Jun 27, 2022· Updated Aug 3, 2024

Cross-site Scripting (XSS) - Generic in ionicabizau/parse-url

CVE-2022-2217

Description

Cross-site scripting (XSS) vulnerability in parse-url before version 7.0.0 allows attackers to inject arbitrary web scripts via crafted URLs.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Cross-site scripting (XSS) vulnerability in parse-url before version 7.0.0 allows attackers to inject arbitrary web scripts via crafted URLs.

Vulnerability

Description CVE-2022-2217 is a stored or reflected Cross-site Scripting (XSS) vulnerability in the parse-url npm package, used to parse URLs. The issue exists in all versions prior to 7.0.0. It occurs because the package does not properly sanitize URL components (such as the file or protocol fields) when parsing URLs, allowing the injection of malicious JavaScript payloads. The vulnerability was discovered through huntr.dev, a bug bounty platform [1][3].

Exploitation

An attacker can exploit this vulnerability by crafting a URL containing a Cross-site Scripting payload in a component that is later rendered unsanitized in a user's browser. The attack does not require authentication beyond the user visiting the malicious URL. The XSS is generic, meaning it can be triggered through various URL parts like the pathname, search, or hash. The commit that fixes the issue (21c72ab) refactors the codebase and upgrades dependencies to sanitize output, preventing script execution [2].

Impact

Successful exploitation allows an attacker to execute arbitrary JavaScript in the context of the victim's browser session. This can lead to session hijacking, credential theft, phishing, defacement, or redirection to malicious sites. The severity is high because parse-url is widely used in JavaScript applications for URL parsing, making this a supply-chain risk for many downstream projects [1].

Mitigation

The vulnerability is patched in version 7.0.0. Users should update the parse-url package to the latest version immediately. The fix can be found in commit 21c72ab, which updates dependencies and refactors the code to ensure proper output encoding [2]. There are no known workarounds; upgrading is the recommended course of action. The vulnerability is not listed in CISA's Known Exploited Vulnerabilities (KEV) catalog as of publication date.

AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
parse-urlnpm
< 6.0.16.0.1

Affected products

3

Patches

1
21c72ab94122

Refactor codebase, upgrade dependencies

https://github.com/ionicabizau/parse-urlIonică BizăuJun 27, 2022via ghsa
3 files changed · +54 26
  • lib/index.js+33 12 modified
    @@ -1,8 +1,10 @@
     "use strict"
     
    +// Dependencies
     const parsePath = require("parse-path")
         , normalizeUrl = require("normalize-url")
     
    +
     /**
      * parseUrl
      * Parses the input url.
    @@ -12,7 +14,7 @@ const parsePath = require("parse-path")
      * @name parseUrl
      * @function
      * @param {String} url The input url.
    - * @param {Boolean|Object} normalize Wheter to normalize the url or not.
    + * @param {Boolean|Object} normalize Whether to normalize the url or not.
      *                         Default is `false`. If `true`, the url will
      *                         be normalized. If an object, it will be the
      *                         options object sent to [`normalize-url`](https://github.com/sindresorhus/normalize-url).
    @@ -21,21 +23,26 @@ const parsePath = require("parse-path")
      *
      * @return {Object} An object containing the following fields:
      *
    - *  - `protocols` (Array): An array with the url protocols (usually it has one element).
    - *  - `protocol` (String): The first protocol, `"ssh"` (if the url is a ssh url) or `"file"`.
    - *  - `port` (null|Number): The domain port.
    - *  - `resource` (String): The url domain (including subdomains).
    - *  - `user` (String): The authentication user (usually for ssh urls).
    - *  - `pathname` (String): The url pathname.
    - *  - `hash` (String): The url hash.
    - *  - `search` (String): The url querystring value.
    - *  - `href` (String): The input url.
    - *  - `query` (Object): The url querystring, parsed as object.
    + *    - `protocols` (Array): An array with the url protocols (usually it has one element).
    + *    - `protocol` (String): The first protocol, `"ssh"` (if the url is a ssh url) or `"file"`.
    + *    - `port` (null|Number): The domain port.
    + *    - `resource` (String): The url domain (including subdomains).
    + *    - `user` (String): The authentication user (usually for ssh urls).
    + *    - `pathname` (String): The url pathname.
    + *    - `hash` (String): The url hash.
    + *    - `search` (String): The url querystring value.
    + *    - `href` (String): The input url.
    + *    - `query` (Object): The url querystring, parsed as object.
      */
    -function parseUrl(url, normalize = false) {
    +const parseUrl = (url, normalize = false) => {
    +
    +    // Constants
    +    const GIT_RE = /((git@|http(s)?:\/\/)([\w\.@]+)(\/|:))(([\~,\w,\-,\_,\/]+)(.git){0,1}((\/){0,1}))/
    +
         if (typeof url !== "string" || !url.trim()) {
             throw new Error("Invalid url.")
         }
    +
         if (normalize) {
             if (typeof normalize !== "object") {
                 normalize = {
    @@ -44,7 +51,21 @@ function parseUrl(url, normalize = false) {
             }
             url = normalizeUrl(url, normalize)
         }
    +
         const parsed = parsePath(url)
    +
    +    // Potential git-ssh urls
    +    if (parsed.protocol === "file") {
    +        const matched  = parsed.href.match(GIT_RE)
    +        if (matched) {
    +            parsed.protocols = ["ssh"]
    +            parsed.protocol = "ssh"
    +            parsed.resource = matched[4]
    +            parsed.user = "git"
    +            parsed.pathname = `/${matched[6]}`
    +        }
    +    }
    +
         return parsed;
     }
     
    
  • package.json+4 4 modified
    @@ -31,10 +31,10 @@
         "tester": "^1.3.1"
       },
       "dependencies": {
    -    "is-ssh": "^1.3.0",
    +    "is-ssh": "^1.4.0",
         "normalize-url": "^6.1.0",
    -    "parse-path": "^4.0.4",
    -    "protocols": "^1.4.0"
    +    "parse-path": "^5.0.0",
    +    "protocols": "^2.0.1"
       },
       "files": [
         "bin/",
    @@ -56,4 +56,4 @@
           "For low-level path parsing, check out [`parse-path`](https://github.com/IonicaBizau/parse-path). This very module is designed to parse urls. By default the urls are normalized."
         ]
       }
    -}
    \ No newline at end of file
    +}
    
  • test/index.js+17 10 modified
    @@ -2,7 +2,6 @@
     const parseUrl = require("../lib")
         , tester = require("tester")
         , normalizeUrl = require("normalize-url")
    -    , qs = require("querystring")
         ;
     
     const INPUTS = [
    @@ -11,77 +10,83 @@ const INPUTS = [
           , {
                 protocols: [ "http" ]
               , protocol: "http"
    -          , port: null
    +          , port: ""
               , resource: "ionicabizau.net"
               , user: ""
               , pathname: "/blog"
               , hash: ""
               , search: ""
    +          , query: {}
             }
         ]
       , [
             "//ionicabizau.net/foo.js"
           , {
                 protocols: ["http"]
               , protocol: "http"
    -          , port: null
    +          , port: ""
               , resource: "ionicabizau.net"
               , user: ""
               , pathname: "/foo.js"
               , hash: ""
               , search: ""
    +          , query: {}
             }
         ]
       , [
             "http://domain.com/path/name#some-hash?foo=bar"
           , {
                 protocols: ["http"]
               , protocol: "http"
    -          , port: null
    +          , port: ""
               , resource: "domain.com"
               , user: ""
               , pathname: "/path/name"
               , hash: "some-hash?foo=bar"
               , search: ""
    +          , query: {}
             }
         ]
       , [
             ["git+ssh://git@host.xz/path/name.git", false]
           , {
                 protocols: ["git", "ssh"]
               , protocol: "git"
    -          , port: null
    +          , port: ""
               , resource: "host.xz"
               , user: "git"
               , pathname: "/path/name.git"
               , hash: ""
               , search: ""
    +          , query: {}
             }
         ]
       , [
             ["git@github.com:IonicaBizau/git-stats.git", false]
           , {
    -            protocols: []
    +            protocols: ["ssh"]
               , protocol: "ssh"
    -          , port: null
    +          , port: ""
               , resource: "github.com"
               , user: "git"
               , pathname: "/IonicaBizau/git-stats.git"
               , hash: ""
               , search: ""
    +          , query: {}
             }
         ]
       , [
             ["http://ionicabizau.net/with-true-normalize", true]
           , {
                 protocols: [ "http" ]
               , protocol: "http"
    -          , port: null
    +          , port: ""
               , resource: "ionicabizau.net"
               , user: ""
               , pathname: "/with-true-normalize"
               , hash: ""
               , search: ""
    +          , query: {}
             }
         ]
     ];
    @@ -91,13 +96,15 @@ tester.describe("check urls", test => {
             let url = Array.isArray(c[0]) ? c[0][0] : c[0]
             test.should("support " + url, () => {
                 const res = parseUrl(url, c[0][1] !== false);
    +
                 if (c[0][1] !== false) {
                     url = normalizeUrl(url, {
                         stripHash: false
                     })
                 }
    -            c[1].query = qs.parse(c[1].search)
    -            c[1].href = url
    +
    +            c[1].href = c[1].href || url
    +            c[1].password = c[1].password || ""
                 test.expect(res).toEqual(c[1]);
             });
         });
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.