mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
always require integrity checking for certain CDNs
This commit is contained in:
@@ -22,15 +22,27 @@ predicate isLocalhostPrefix(string host) {
|
||||
])
|
||||
}
|
||||
|
||||
bindingset[path]
|
||||
predicate isUntrustedSourcePath(string path) {
|
||||
path.substring(0, 2) = "//"
|
||||
/** A path that is vulnerable to a MITM attack. */
|
||||
bindingset[url]
|
||||
predicate isUntrustedSourceUrl(string url) {
|
||||
url.substring(0, 2) = "//"
|
||||
or
|
||||
exists(string hostPath | hostPath = path.regexpCapture("http://(.*)", 1) |
|
||||
exists(string hostPath | hostPath = url.regexpCapture("http://(.*)", 1) |
|
||||
not isLocalhostPrefix(hostPath)
|
||||
)
|
||||
}
|
||||
|
||||
/** A path that needs an integrity check — even with https. */
|
||||
bindingset[url]
|
||||
predicate isCdnUrlWithCheckingRequired(string url) {
|
||||
// Some CDN URLs are required to have an integrity attribute. We only add CDNs to that list
|
||||
// that recommend integrity-checking.
|
||||
url.regexpMatch([
|
||||
"^https?://code\\.jquery\\.com/.*\\.js$", "^https?://cdnjs\\.cloudflare\\.com/.*\\.js$",
|
||||
"^https?://cdnjs\\.com/.*\\.js$"
|
||||
])
|
||||
}
|
||||
|
||||
abstract class IncludesUntrustedContent extends HTML::Element {
|
||||
/** Gets an explanation why this source is untrusted. */
|
||||
abstract string getProblem();
|
||||
@@ -39,8 +51,12 @@ abstract class IncludesUntrustedContent extends HTML::Element {
|
||||
/** A script element that refers to untrusted content. */
|
||||
class ScriptElementWithUntrustedContent extends IncludesUntrustedContent, HTML::ScriptElement {
|
||||
ScriptElementWithUntrustedContent() {
|
||||
isUntrustedSourcePath(this.getSourcePath()) and
|
||||
not exists(string digest | not digest = "" | this.getIntegrityDigest() = digest)
|
||||
not exists(string digest | not digest = "" | this.getIntegrityDigest() = digest) and
|
||||
(
|
||||
isUntrustedSourceUrl(this.getSourcePath())
|
||||
or
|
||||
isCdnUrlWithCheckingRequired(this.getSourcePath())
|
||||
)
|
||||
}
|
||||
|
||||
override string getProblem() {
|
||||
@@ -50,7 +66,7 @@ class ScriptElementWithUntrustedContent extends IncludesUntrustedContent, HTML::
|
||||
|
||||
/** An iframe element that includes untrusted content. */
|
||||
class IframeElementWithUntrustedContent extends HTML::IframeElement, IncludesUntrustedContent {
|
||||
IframeElementWithUntrustedContent() { isUntrustedSourcePath(this.getSourcePath()) }
|
||||
IframeElementWithUntrustedContent() { isUntrustedSourceUrl(this.getSourcePath()) }
|
||||
|
||||
override string getProblem() { result = "iframe elements should use an HTTPS url" }
|
||||
}
|
||||
|
||||
@@ -12,5 +12,11 @@
|
||||
<iframe src="http://::1/foo.html"></iframe> <!-- OK (localhost) -->
|
||||
<iframe src="http://[::1]:80/foo.html"></iframe> <!-- OK (localhost) -->
|
||||
<iframe src="http://127.0.0.1:444/foo.html"></iframe> <!-- OK (localhost) -->
|
||||
|
||||
<!-- Some CDNs recommend using the integrity attribute — for those, we demand it even with https links -->
|
||||
<!-- OK (digest present) -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.8.2/angular.min.js" integrity="sha512-7oYXeK0OxTFxndh0erL8FsjGvrl2VMDor6fVqzlLGfwOQQqTbYsGPv4ZZ15QHfSk80doyaM0ZJdvkyDcVO7KFA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<!-- NOT OK (digest missing) -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.8.2/angular.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user