Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 780fa97

Browse files
author
Stephan Brandauer
committed
always require integrity checking for certain CDNs
1 parent 83764df commit 780fa97

2 files changed

Lines changed: 29 additions & 7 deletions

File tree

javascript/ql/src/Security/CWE-830/FunctionalityFromUntrustedSource.ql

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,27 @@ predicate isLocalhostPrefix(string host) {
2222
])
2323
}
2424

25-
bindingset[path]
26-
predicate isUntrustedSourcePath(string path) {
27-
path.substring(0, 2) = "//"
25+
/** A path that is vulnerable to a MITM attack. */
26+
bindingset[url]
27+
predicate isUntrustedSourceUrl(string url) {
28+
url.substring(0, 2) = "//"
2829
or
29-
exists(string hostPath | hostPath = path.regexpCapture("http://(.*)", 1) |
30+
exists(string hostPath | hostPath = url.regexpCapture("http://(.*)", 1) |
3031
not isLocalhostPrefix(hostPath)
3132
)
3233
}
3334

35+
/** A path that needs an integrity check — even with https. */
36+
bindingset[url]
37+
predicate isCdnUrlWithCheckingRequired(string url) {
38+
// Some CDN URLs are required to have an integrity attribute. We only add CDNs to that list
39+
// that recommend integrity-checking.
40+
url.regexpMatch([
41+
"^https?://code\\.jquery\\.com/.*\\.js$", "^https?://cdnjs\\.cloudflare\\.com/.*\\.js$",
42+
"^https?://cdnjs\\.com/.*\\.js$"
43+
])
44+
}
45+
3446
abstract class IncludesUntrustedContent extends HTML::Element {
3547
/** Gets an explanation why this source is untrusted. */
3648
abstract string getProblem();
@@ -39,8 +51,12 @@ abstract class IncludesUntrustedContent extends HTML::Element {
3951
/** A script element that refers to untrusted content. */
4052
class ScriptElementWithUntrustedContent extends IncludesUntrustedContent, HTML::ScriptElement {
4153
ScriptElementWithUntrustedContent() {
42-
isUntrustedSourcePath(this.getSourcePath()) and
43-
not exists(string digest | not digest = "" | this.getIntegrityDigest() = digest)
54+
not exists(string digest | not digest = "" | this.getIntegrityDigest() = digest) and
55+
(
56+
isUntrustedSourceUrl(this.getSourcePath())
57+
or
58+
isCdnUrlWithCheckingRequired(this.getSourcePath())
59+
)
4460
}
4561

4662
override string getProblem() {
@@ -50,7 +66,7 @@ class ScriptElementWithUntrustedContent extends IncludesUntrustedContent, HTML::
5066

5167
/** An iframe element that includes untrusted content. */
5268
class IframeElementWithUntrustedContent extends HTML::IframeElement, IncludesUntrustedContent {
53-
IframeElementWithUntrustedContent() { isUntrustedSourcePath(this.getSourcePath()) }
69+
IframeElementWithUntrustedContent() { isUntrustedSourceUrl(this.getSourcePath()) }
5470

5571
override string getProblem() { result = "iframe elements should use an HTTPS url" }
5672
}

javascript/ql/test/query-tests/Security/CWE-830/FunctionalityFromUntrustedSource.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,11 @@
1212
<iframe src="http://::1/foo.html"></iframe> <!-- OK (localhost) -->
1313
<iframe src="http://[::1]:80/foo.html"></iframe> <!-- OK (localhost) -->
1414
<iframe src="http://127.0.0.1:444/foo.html"></iframe> <!-- OK (localhost) -->
15+
16+
<!-- Some CDNs recommend using the integrity attribute — for those, we demand it even with https links -->
17+
<!-- OK (digest present) -->
18+
<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>
19+
<!-- NOT OK (digest missing) -->
20+
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.8.2/angular.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
1521
</body>
1622
</html>

0 commit comments

Comments
 (0)