Files
codeql/javascript/ql/src/DOM/TargetBlank.ql
2018-08-02 17:53:23 +01:00

57 lines
2.2 KiB
Plaintext

/**
* @name Potentially unsafe external link
* @description External links that open in a new tab or window but do not specify
* link type 'noopener' or 'noreferrer' are a potential security risk.
* @kind problem
* @problem.severity warning
* @id js/unsafe-external-link
* @tags maintainability
* security
* external/cwe/cwe-200
* @precision very-high
*/
import javascript
import semmle.javascript.frameworks.Templating
/**
* Holds if the href attribute contains a host that we cannot determine statically.
*/
predicate hasDynamicHrefHostAttributeValue(DOM::ElementDefinition elem) {
exists (DOM::AttributeDefinition attr |
attr = elem.getAnAttribute() and
attr.getName().matches("%href%") |
// unknown string
not exists(attr.getStringValue()) or
exists (string url | url = attr.getStringValue() |
// fixed string with templating
url.regexpMatch(Templating::getDelimiterMatchingRegexp())
and
// ... that does not start with a fixed host or a relative path (common formats)
not url.regexpMatch("(?i)((https?:)?//)?[-a-z0-9.]*/.*")
)
)
}
from DOM::ElementDefinition e
where // `e` is a link that opens in a new browsing context (that is, it has `target="_blank"`)
e.getName() = "a" and
// and the host in the href is not hard-coded
hasDynamicHrefHostAttributeValue(e) and
e.getAttributeByName("target").getStringValue() = "_blank" and
// there is no `rel` attribute specifying link type `noopener`/`noreferrer`;
// `rel` attributes with non-constant value are handled conservatively
forall (DOM::AttributeDefinition relAttr | relAttr = e.getAttributeByName("rel") |
exists (string rel | rel = relAttr.getStringValue() |
not exists (string linkType | linkType = rel.splitAt(" ") |
linkType = "noopener" or
linkType = "noreferrer"
)
)
) and
// exclude elements with spread attributes or dynamically computed attribute names
not exists (DOM::AttributeDefinition attr | attr = e.getAnAttribute() |
not exists(attr.getName())
)
select e, "External links without noopener/noreferrer are a potential security risk."