typescript.react.security.audit.react-href-var.react-href-var
semgrep
Author
5,893
Download Count*
License
Detected a variable used in an anchor tag with the 'href' attribute. A malicious actor may be able to input the 'javascript:' URI, which could cause cross-site scripting (XSS). It is recommended to disallow 'javascript:' URIs within your application.
Run Locally
Run in CI
Defintion
rules:
- id: react-href-var
message: Detected a variable used in an anchor tag with the 'href' attribute. A
malicious actor may be able to input the 'javascript:' URI, which could
cause cross-site scripting (XSS). It is recommended to disallow
'javascript:' URIs within your application.
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://reactjs.org/blog/2019/08/08/react-v16.9.0.html#deprecating-javascript-urls
- https://pragmaticwebsecurity.com/articles/spasecurity/react-xss-part1.html
category: security
confidence: LOW
technology:
- react
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
cwe2022-top25: true
cwe2021-top25: true
subcategory:
- audit
likelihood: LOW
impact: MEDIUM
vulnerability_class:
- Cross-Site-Scripting (XSS)
languages:
- typescript
- javascript
severity: WARNING
mode: taint
pattern-sources:
- label: TAINTED
patterns:
- pattern-either:
- pattern-inside: |
function ...({..., $X, ...}) { ... }
- pattern-inside: |
function ...(..., $X, ...) { ... }
- focus-metavariable: $X
- pattern-either:
- pattern: $X.$Y
- pattern: $X[...]
- pattern-not-inside: |
$F. ... .$SANITIZEUNC(...)
- label: CONCAT
requires: TAINTED
patterns:
- pattern-either:
- pattern: |
`...${$X}...`
- pattern: |
$SANITIZE + <... $X ...>
- pattern-not: |
`${$X}...`
- pattern-not: |
$X + ...
- focus-metavariable: $X
- label: CLEAN
by-side-effect: true
patterns:
- pattern-either:
- pattern: $A($SOURCE)
- pattern: $SANITIZE. ... .$A($SOURCE)
- pattern: $A. ... .$SANITIZE($SOURCE)
- focus-metavariable: $SOURCE
- metavariable-regex:
metavariable: $A
regex: (?i)(.*valid|.*sanitiz)
pattern-sinks:
- requires: TAINTED and not CONCAT and not CLEAN
patterns:
- focus-metavariable: $X
- pattern-either:
- pattern: |
<$EL href={$X} />
- pattern: |
React.createElement($EL, {href: $X})
- pattern-inside: |
$PARAMS = {href: $X};
...
React.createElement($EL, $PARAMS);
- metavariable-pattern:
patterns:
- pattern-not-regex: (?i)(button)
metavariable: $EL
Examples
react-href-var.jsx
import {
SEMGREP_REPO,
} from "../../util";
import SEMGREP_REPO1 from "../../util1";
// ok: react-href-var
let zzz = <Foo className={"foobar"} href={getQuery()} />;
function test1(input) {
// ruleid: react-href-var
const params = {href: input.a};
return React.createElement("a", params);
}
// ok: react-href-var
{collaborationSectionData.paragraphs.map((item, i) => (
<div> <a href={item.value}>click</a></div>
))}
// ok: react-href-var
let zzz = <Foo className={"foobar"} href={`${input}`} />;
// ok: react-href-var
let zzz = <Foo className={"foobar"} href={SEMGREP_REPO} />;
// ok: react-href-var
let zzz = <Foo className={"foobar"} href={SEMGREP_REPO1} />;
function test1(input) {
// ok: react-href-var
if(input.startsWith("https:")) {
const params = {href: input};
return React.createElement("a", params);
}
}
function test2(input) {
// ok: react-href-var
const params = {href: "#"+input};
return React.createElement("a", params);
}
function test2(input) {
// ok: react-href-var
const params = {href: "#"+input};
return React.createElement("a", params);
}
// ok: react-href-var
const b = <a className={"foobar"} href={"http://www.example.com"}></a>;
// ok: react-href-var
let x = <a className={"foobar"} href={"#"+input}></a>;
// ok: react-href-var
let x = <a className={"foobar"} href={`#${input}`}></a>;
function okTest1() {
// ok: react-href-var
return React.createElement("a", {href: "https://www.example.com"});
}
react-href-var.tsx
import {
SEMGREP_REPO,
} from "../../util";
import SEMGREP_REPO1 from "../../util1";
// ok: react-href-var
let zzz = <Foo className={"foobar"} href={getQuery()} />;
function test1(input) {
// ruleid: react-href-var
const params = {href: input.a};
return React.createElement("a", params);
}
// ok: react-href-var
let zzz = <Foo className={"foobar"} href={`${input}`} />;
// ok: react-href-var
let zzz = <Foo className={"foobar"} href={SEMGREP_REPO} />;
// ok: react-href-var
let zzz = <Foo className={"foobar"} href={SEMGREP_REPO1} />;
function test1(input) {
// ok: react-href-var
if(input.startsWith("https:")) {
const params = {href: input};
return React.createElement("a", params);
}
}
function test2(input) {
// ok: react-href-var
const params = {href: "#"+input};
return React.createElement("a", params);
}
function test2(input) {
// ok: react-href-var
const params = {href: "#"+input};
return React.createElement("a", params);
}
// ok: react-href-var
const b = <a className={"foobar"} href={"http://www.example.com"}></a>;
// ok: react-href-var
let x = <a className={"foobar"} href={"#"+input}></a>;
// ok: react-href-var
let x = <a className={"foobar"} href={`#${input}`}></a>;
function okTest1() {
// ok: react-href-var
return React.createElement("a", {href: "https://www.example.com"});
}
Short Link: https://sg.run/bDZZ