mirror of
https://github.com/github/codeql.git
synced 2026-04-28 18:25:24 +02:00
Merge branch 'main' into js/shared-dataflow-merge-main
This commit is contained in:
36
javascript/ql/src/Security/CWE-693/CUSTOMIZING.md
Normal file
36
javascript/ql/src/Security/CWE-693/CUSTOMIZING.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# Insecure Helmet Configuration - customizations
|
||||
|
||||
You can extend the required [Helmet security settings](https://helmetjs.github.io/) using [data extensions](https://codeql.github.com/docs/codeql-language-guides/customizing-library-models-for-javascript/) in a [CodeQL model pack](https://docs.github.com/en/code-security/codeql-cli/using-the-advanced-functionality-of-the-codeql-cli/creating-and-working-with-codeql-packs#creating-a-codeql-model-pack).
|
||||
|
||||
They are defaulted to just `frameguard` and `contentSecurityPolicy`, but you can add more using this method, to require them not to be set to `false` (which explicitly disables them) in the Helmet configuration.
|
||||
|
||||
For example, this YAML model can be used inside a CodeQL model pack to require `frameguard` and `contentSecurityPolicy`:
|
||||
|
||||
```yaml
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/javascript-all
|
||||
extensible: requiredHelmetSecuritySetting
|
||||
data:
|
||||
- ["frameguard"]
|
||||
- ["contentSecurityPolicy"]
|
||||
```
|
||||
|
||||
Note: Using `frameguard` and `contentSecurityPolicy` is an example: the query already enforces these, so it is not necessary to add it with your own data extension.
|
||||
|
||||
A suitable [model pack](https://docs.github.com/en/code-security/codeql-cli/using-the-advanced-functionality-of-the-codeql-cli/creating-and-working-with-codeql-packs#creating-a-codeql-model-pack) might be:
|
||||
|
||||
```yaml
|
||||
name: my-org/javascript-helmet-insecure-config-model-pack
|
||||
version: 1.0.0
|
||||
extensionTargets:
|
||||
codeql/java-all: '*'
|
||||
dataExtensions:
|
||||
- models/**/*.yml
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [Helmet security settings](https://helmetjs.github.io/)
|
||||
- [Customizing library models for javascript](https://codeql.github.com/docs/codeql-language-guides/customizing-library-models-for-javascript/)
|
||||
- [Creating and working with CodeQL packs](https://docs.github.com/en/code-security/codeql-cli/using-the-advanced-functionality-of-the-codeql-cli/creating-and-working-with-codeql-packs#creating-a-codeql-model-pack)
|
||||
71
javascript/ql/src/Security/CWE-693/InsecureHelmet.qhelp
Normal file
71
javascript/ql/src/Security/CWE-693/InsecureHelmet.qhelp
Normal file
@@ -0,0 +1,71 @@
|
||||
<!DOCTYPE qhelp SYSTEM "qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
<a href="https://helmetjs.github.io/">Helmet</a> is a collection of middleware functions for securing Express apps. It sets various HTTP headers to guard against common web vulnerabilities.
|
||||
|
||||
This query detects Helmet misconfigurations that can lead to security vulnerabilities, specifically:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Disabling frame protection</li>
|
||||
<li>Disabling Content Security Policy</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Content Security Policy (CSP) helps spot and prevent injection attacks such as Cross-Site Scripting (XSS).
|
||||
|
||||
Removing frame protections exposes an application to attacks such as clickjacking, where an attacker can trick a user into clicking on a button or link on a targeted page when they intended to click on the page carrying out the attack.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Users of the query can extend the set of required Helmet features by adding additional checks for them, using CodeQL <a href="https://codeql.github.com/docs/codeql-language-guides/customizing-library-models-for-javascript/">data extensions</a> in a <a href="https://docs.github.com/en/code-security/codeql-cli/using-the-advanced-functionality-of-the-codeql-cli/creating-and-working-with-codeql-packs#creating-a-codeql-model-pack">CodeQL model pack</a>. See <code>CUSTOMIZING.md</code> in the query source for more information.
|
||||
</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
<p>
|
||||
To help mitigate these vulnerabilities, ensure that the following Helmet functions are not disabled, and are configured appropriately to your application:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li><code>frameguard</code></li>
|
||||
<li><code>contentSecurityPolicy</code></li>
|
||||
</ul>
|
||||
</recommendation>
|
||||
<example>
|
||||
<p>
|
||||
The following code snippet demonstrates Helmet configured in an insecure manner:
|
||||
</p>
|
||||
|
||||
<sample src="examples/helmet_insecure.js" />
|
||||
|
||||
<p>
|
||||
In this example, the defaults are used, which enables frame protection and a default Content Security Policy.
|
||||
</p>
|
||||
|
||||
<sample src="examples/helmet_default.js" />
|
||||
|
||||
<p>
|
||||
You can also enable a custom Content Security Policy by passing an object to the <code>contentSecurityPolicy</code> key. For example, taken from the <a href="https://helmetjs.github.io/#content-security-policy">Helmet docs</a>:
|
||||
</p>
|
||||
|
||||
<sample src="examples/helmet_custom.js" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
<li>
|
||||
<a href="https://helmetjs.github.io/">helmet.js website</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy">Content Security Policy (CSP) | MDN</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://infosec.mozilla.org/guidelines/web_security">Mozilla Web Security Guidelines</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://developer.mozilla.org/en-US/docs/Web/Security#protect_against_clickjacking">Protect against clickjacking | MDN</a>
|
||||
</li>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
47
javascript/ql/src/Security/CWE-693/InsecureHelmet.ql
Normal file
47
javascript/ql/src/Security/CWE-693/InsecureHelmet.ql
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* @name Insecure configuration of Helmet security middleware
|
||||
* @description The Helmet middleware is used to set security-related HTTP headers in Express applications. This query finds instances where the middleware is configured with important security features disabled.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 7.0
|
||||
* @precision high
|
||||
* @id js/insecure-helmet-configuration
|
||||
* @tags security
|
||||
* external/cwe/cwe-693
|
||||
* external/cwe/cwe-1021
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import DataFlow
|
||||
import semmle.javascript.frameworks.ExpressModules
|
||||
|
||||
class HelmetProperty extends DataFlow::Node instanceof DataFlow::PropWrite {
|
||||
ExpressLibraries::HelmetRouteHandler helmet;
|
||||
|
||||
HelmetProperty() {
|
||||
this = helmet.(DataFlow::CallNode).getAnArgument().getALocalSource().getAPropertyWrite()
|
||||
}
|
||||
|
||||
ExpressLibraries::HelmetRouteHandler getHelmet() { result = helmet }
|
||||
|
||||
predicate isFalse() { DataFlow::PropWrite.super.getRhs().mayHaveBooleanValue(false) }
|
||||
|
||||
string getName() { result = DataFlow::PropWrite.super.getPropertyName() }
|
||||
|
||||
predicate isImportantSecuritySetting() {
|
||||
// read from data extensions to allow enforcing custom settings
|
||||
// defaults are located in javascript/ql/lib/semmle/frameworks/helmet/Helmet.Required.Setting.model.yml
|
||||
requiredHelmetSecuritySetting(this.getName())
|
||||
}
|
||||
}
|
||||
|
||||
extensible predicate requiredHelmetSecuritySetting(string name);
|
||||
|
||||
from HelmetProperty helmetProperty, ExpressLibraries::HelmetRouteHandler helmet
|
||||
where
|
||||
helmetProperty.isFalse() and
|
||||
helmetProperty.isImportantSecuritySetting() and
|
||||
helmetProperty.getHelmet() = helmet
|
||||
select helmet,
|
||||
"Helmet security middleware, configured with security setting $@ set to 'false', which disables enforcing that feature.",
|
||||
helmetProperty, helmetProperty.getName()
|
||||
10
javascript/ql/src/Security/CWE-693/examples/helmet_custom.js
Normal file
10
javascript/ql/src/Security/CWE-693/examples/helmet_custom.js
Normal file
@@ -0,0 +1,10 @@
|
||||
app.use(
|
||||
helmet({
|
||||
contentSecurityPolicy: {
|
||||
directives: {
|
||||
"script-src": ["'self'", "example.com"],
|
||||
"style-src": null,
|
||||
},
|
||||
},
|
||||
})
|
||||
);
|
||||
@@ -0,0 +1 @@
|
||||
app.use(helmet());
|
||||
@@ -0,0 +1,6 @@
|
||||
const helmet = require('helmet');
|
||||
|
||||
app.use(helmet({
|
||||
frameguard: false,
|
||||
contentSecurityPolicy: false
|
||||
}));
|
||||
43
javascript/ql/src/Security/CWE-830/CUSTOMIZING.md
Normal file
43
javascript/ql/src/Security/CWE-830/CUSTOMIZING.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Extending the library list of untrusted sources and domains
|
||||
|
||||
You can expand the list of untrusted domains in the CodeQL library used by the `js/functionality-from-untrusted-source` and `js/functionality-from-untrusted-domain` queries using [CodeQL data extensions](https://codeql.github.com/docs/codeql-language-guides/customizing-library-models-for-javascript/).
|
||||
|
||||
This allows you to add additional domains to warn users about and to require Subresource Integrity (SRI) checks on specific content delivery network (CDN) hostnames.
|
||||
|
||||
For example, this YAML model can be used inside a CodeQL model pack to alert on uses of `example.com` in imported functionality, extending the `js/functionality-from-untrusted-domain` query:
|
||||
|
||||
```yaml
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/javascript-all
|
||||
extensible: untrustedDomain
|
||||
data:
|
||||
- ["example.com"]
|
||||
```
|
||||
|
||||
To add new hostnames that always require SRI checking, this YAML model can be used to require SRI on `cdn.example.com`, extending the `js/functionality-from-untrusted-source` query:
|
||||
|
||||
```yaml
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/javascript-all
|
||||
extensible: isCdnDomainWithCheckingRequired
|
||||
data:
|
||||
- ["cdn.example.com"]
|
||||
```
|
||||
|
||||
You would create a model pack with this information using metadata similar to that in the example below:
|
||||
|
||||
```yaml
|
||||
name: my-org/javascript-untrusted-functionality-model-pack
|
||||
version: 1.0.0
|
||||
extensionTargets:
|
||||
codeql/java-all: '*'
|
||||
dataExtensions:
|
||||
- models/**/*.yml
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [Customizing library models for javascript](https://codeql.github.com/docs/codeql-language-guides/customizing-library-models-for-javascript/)
|
||||
- [Creating and working with CodeQL packs](https://docs.github.com/en/code-security/codeql-cli/using-the-advanced-functionality-of-the-codeql-cli/creating-and-working-with-codeql-packs#creating-a-codeql-model-pack)
|
||||
@@ -0,0 +1,102 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
Content Delivery Networks (CDNs) are used to deliver content to users quickly and efficiently.
|
||||
|
||||
However, they can change hands or be operated by untrustworthy owners, risking the security of the sites that use them.
|
||||
|
||||
Some CDN domains are operated by entities that have used CDNs to deliver malware, which this query identifies.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For example, <code>polyfill.io</code> was a popular JavaScript CDN,
|
||||
used to support new web browser standards on older browsers.
|
||||
|
||||
In February 2024 the domain was sold, and in June 2024 it was publicised that the domain
|
||||
had been used to serve malicious scripts. It was taken down later in that month, leaving a window
|
||||
where sites that used the service could have been compromised.
|
||||
|
||||
The same operator runs several other CDNs, undermining trust in those too.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Including a resource from an untrusted source or using an untrusted channel may
|
||||
allow an attacker to include arbitrary code in the response.
|
||||
When including an external resource (for example, a <code>script</code> element) on a page,
|
||||
it is important to ensure that the received data is not malicious.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Even when <code>https</code> is used, an untrustworthy operator might deliver malware.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
See the [`CUSTOMIZING.md`](https://github.com/github/codeql/blob/main/javascript/ql/src/Security/CWE-830/CUSTOMIZING.md) file in the source code for this query for information on how to extend the list of untrusted domains used by this query.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
Carefully research the ownership of a Content Delivery Network (CDN) before using it in your application.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If you find code that originated from an untrusted domain in your application, you should review your logs to check for compromise.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To help mitigate the risk of including a script that could be compromised in the future, consider whether you need to
|
||||
use polyfill or another library at all. Modern browsers do not require a polyfill, and other popular libraries were made redundant by enhancements to HTML 5.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If you do need a polyfill service or library, move to using a CDN that you trust.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
When you use a <code>script</code> or <code>link</code> element,
|
||||
you should check for <a href="https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity">subresource integrity (SRI)</a>,
|
||||
and pin to a hash of a version of the service that you can trust (for example, because you have audited it for security and unwanted features).
|
||||
|
||||
A dynamic service cannot be easily used with SRI. Nevertheless,
|
||||
it is possible to list multiple acceptable SHA hashes in the <code>integrity</code> attribute,
|
||||
such as hashes for the content required for the major browsers used by your users.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You can also choose to self-host an uncompromised version of the service or library.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following example loads the Polyfill.io library from the <code>polyfill.io</code> CDN. This use was open to malicious scripts being served by the CDN.
|
||||
</p>
|
||||
|
||||
<sample src="polyfill-compromised.html" />
|
||||
|
||||
<p>
|
||||
Instead, load the Polyfill library from a trusted CDN, as in the next example:
|
||||
</p>
|
||||
|
||||
<sample src="polyfill-trusted.html" />
|
||||
|
||||
<p>
|
||||
If you know which browsers are used by the majority of your users, you can list the hashes of the polyfills for those browsers:
|
||||
</p>
|
||||
|
||||
<sample src="polyfill-sri.html" />
|
||||
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>Sansec: <a href="https://sansec.io/research/polyfill-supply-chain-attack">Polyfill supply chain attack hits 100K+ sites</a></li>
|
||||
<li>Cloudflare: <a href="https://cdnjs.cloudflare.com/polyfill">Upgrade the web. Automatically. Delivers only the polyfills required by the user's web browser.</a></li>
|
||||
<li>Fastly: <a href="https://community.fastly.com/t/new-options-for-polyfill-io-users/2540">New options for Polyfill.io users</a></li>
|
||||
<li>Wikipedia: <a href="https://en.wikipedia.org/wiki/Polyfill_(programming)">Polyfill (programming)</a></li>
|
||||
<li>MDN Web Docs: <a href="https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity">Subresource Integrity</a></li>
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* @name Untrusted domain used in script or other content
|
||||
* @description Using a resource from an untrusted or compromised domain makes your code vulnerable to receiving malicious code.
|
||||
* @kind problem
|
||||
* @security-severity 7.2
|
||||
* @problem.severity error
|
||||
* @id js/functionality-from-untrusted-domain
|
||||
* @precision high
|
||||
* @tags security
|
||||
* external/cwe/cwe-830
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import semmle.javascript.security.FunctionalityFromUntrustedSource
|
||||
|
||||
from AddsUntrustedUrl s
|
||||
where isUrlWithUntrustedDomain(s.getUrl())
|
||||
select s, "Content loaded from untrusted domain with no integrity check."
|
||||
@@ -28,11 +28,21 @@
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Subresource integrity checking is commonly recommended when importing a fixed version of
|
||||
Subresource integrity (SRI) checking is commonly recommended when importing a fixed version of
|
||||
a library - for example, from a CDN (content-delivery network). Then, the fixed digest
|
||||
of that version of the library can easily be added to the <code>script</code> element's
|
||||
<code>integrity</code> attribute.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A dynamic service cannot be easily used with SRI. Nevertheless,
|
||||
it is possible to list multiple acceptable SHA hashes in the <code>integrity</code> attribute,
|
||||
such as those for the content generated for major browers used by your users.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
See the [`CUSTOMIZING.md`](https://github.com/github/codeql/blob/main/javascript/ql/src/Security/CWE-830/CUSTOMIZING.md) file in the source code for this query for information on how to extend the list of hostnames required to use SRI by this query.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
|
||||
@@ -12,158 +12,10 @@
|
||||
*/
|
||||
|
||||
import javascript
|
||||
|
||||
/** A location that adds a reference to an untrusted source. */
|
||||
abstract class AddsUntrustedUrl extends Locatable {
|
||||
/** Gets an explanation why this source is untrusted. */
|
||||
abstract string getProblem();
|
||||
}
|
||||
|
||||
module StaticCreation {
|
||||
/** Holds if `host` is an alias of localhost. */
|
||||
bindingset[host]
|
||||
predicate isLocalhostPrefix(string host) {
|
||||
host.toLowerCase()
|
||||
.regexpMatch([
|
||||
"(?i)localhost(:[0-9]+)?/.*", "127.0.0.1(:[0-9]+)?/.*", "::1/.*", "\\[::1\\]:[0-9]+/.*"
|
||||
])
|
||||
}
|
||||
|
||||
/** Holds if `url` is a url that is vulnerable to a MITM attack. */
|
||||
bindingset[url]
|
||||
predicate isUntrustedSourceUrl(string url) {
|
||||
exists(string hostPath | hostPath = url.regexpCapture("(?i)http://(.*)", 1) |
|
||||
not isLocalhostPrefix(hostPath)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `url` refers to a CDN 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("(?i)^https?://" +
|
||||
[
|
||||
"code\\.jquery\\.com", //
|
||||
"cdnjs\\.cloudflare\\.com", //
|
||||
"cdnjs\\.com" //
|
||||
] + "/.*\\.js$")
|
||||
}
|
||||
|
||||
/** A script element that refers to untrusted content. */
|
||||
class ScriptElementWithUntrustedContent extends AddsUntrustedUrl instanceof HTML::ScriptElement {
|
||||
ScriptElementWithUntrustedContent() {
|
||||
not exists(string digest | not digest = "" | super.getIntegrityDigest() = digest) and
|
||||
isUntrustedSourceUrl(super.getSourcePath())
|
||||
}
|
||||
|
||||
override string getProblem() { result = "Script loaded using unencrypted connection." }
|
||||
}
|
||||
|
||||
/** A script element that refers to untrusted content. */
|
||||
class CdnScriptElementWithUntrustedContent extends AddsUntrustedUrl, HTML::ScriptElement {
|
||||
CdnScriptElementWithUntrustedContent() {
|
||||
not exists(string digest | not digest = "" | this.getIntegrityDigest() = digest) and
|
||||
isCdnUrlWithCheckingRequired(this.getSourcePath())
|
||||
}
|
||||
|
||||
override string getProblem() {
|
||||
result = "Script loaded from content delivery network with no integrity check."
|
||||
}
|
||||
}
|
||||
|
||||
/** An iframe element that includes untrusted content. */
|
||||
class IframeElementWithUntrustedContent extends AddsUntrustedUrl instanceof HTML::IframeElement {
|
||||
IframeElementWithUntrustedContent() { isUntrustedSourceUrl(super.getSourcePath()) }
|
||||
|
||||
override string getProblem() { result = "Iframe loaded using unencrypted connection." }
|
||||
}
|
||||
}
|
||||
|
||||
module DynamicCreation {
|
||||
/** Holds if `call` creates a tag of kind `name`. */
|
||||
predicate isCreateElementNode(DataFlow::CallNode call, string name) {
|
||||
call = DataFlow::globalVarRef("document").getAMethodCall("createElement") and
|
||||
call.getArgument(0).getStringValue().toLowerCase() = name
|
||||
}
|
||||
|
||||
DataFlow::Node getAttributeAssignmentRhs(DataFlow::CallNode createCall, string name) {
|
||||
result = createCall.getAPropertyWrite(name).getRhs()
|
||||
or
|
||||
exists(DataFlow::InvokeNode inv | inv = createCall.getAMemberInvocation("setAttribute") |
|
||||
inv.getArgument(0).getStringValue() = name and
|
||||
result = inv.getArgument(1)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `createCall` creates a `<script ../>` element which never
|
||||
* has its `integrity` attribute set locally.
|
||||
*/
|
||||
predicate isCreateScriptNodeWoIntegrityCheck(DataFlow::CallNode createCall) {
|
||||
isCreateElementNode(createCall, "script") and
|
||||
not exists(getAttributeAssignmentRhs(createCall, "integrity"))
|
||||
}
|
||||
|
||||
DataFlow::Node urlTrackedFromUnsafeSourceLiteral(DataFlow::TypeTracker t) {
|
||||
t.start() and result.getStringValue().regexpMatch("(?i)http:.*")
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2, DataFlow::Node prev |
|
||||
prev = urlTrackedFromUnsafeSourceLiteral(t2)
|
||||
|
|
||||
not exists(string httpsUrl | httpsUrl.toLowerCase() = "https:" + any(string rest) |
|
||||
// when the result may have a string value starting with https,
|
||||
// we're most likely with an assignment like:
|
||||
// e.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'
|
||||
// these assignments, we don't want to fix - once the browser is using http,
|
||||
// MITM attacks are possible anyway.
|
||||
result.mayHaveStringValue(httpsUrl)
|
||||
) and
|
||||
(
|
||||
t2 = t.smallstep(prev, result)
|
||||
or
|
||||
TaintTracking::sharedTaintStep(prev, result) and
|
||||
t = t2
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
DataFlow::Node urlTrackedFromUnsafeSourceLiteral() {
|
||||
result = urlTrackedFromUnsafeSourceLiteral(DataFlow::TypeTracker::end())
|
||||
}
|
||||
|
||||
/** Holds if `sink` is assigned to the attribute `name` of any HTML element. */
|
||||
predicate isAssignedToSrcAttribute(string name, DataFlow::Node sink) {
|
||||
exists(DataFlow::CallNode createElementCall |
|
||||
sink = getAttributeAssignmentRhs(createElementCall, "src") and
|
||||
(
|
||||
name = "script" and
|
||||
isCreateScriptNodeWoIntegrityCheck(createElementCall)
|
||||
or
|
||||
name = "iframe" and
|
||||
isCreateElementNode(createElementCall, "iframe")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
class IframeOrScriptSrcAssignment extends AddsUntrustedUrl {
|
||||
string name;
|
||||
|
||||
IframeOrScriptSrcAssignment() {
|
||||
name = ["script", "iframe"] and
|
||||
exists(DataFlow::Node n | n.asExpr() = this |
|
||||
isAssignedToSrcAttribute(name, n) and
|
||||
n = urlTrackedFromUnsafeSourceLiteral()
|
||||
)
|
||||
}
|
||||
|
||||
override string getProblem() {
|
||||
name = "script" and result = "Script loaded using unencrypted connection."
|
||||
or
|
||||
name = "iframe" and result = "Iframe loaded using unencrypted connection."
|
||||
}
|
||||
}
|
||||
}
|
||||
import semmle.javascript.security.FunctionalityFromUntrustedSource
|
||||
|
||||
from AddsUntrustedUrl s
|
||||
// do not alert on explicitly untrusted domains
|
||||
// another query can alert on these, js/functionality-from-untrusted-domain
|
||||
where not isUrlWithUntrustedDomain(s.getUrl())
|
||||
select s, s.getProblem()
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Polyfill.io demo</title>
|
||||
<script src="https://cdn.polyfill.io/v2/polyfill.min.js" crossorigin="anonymous"></script>
|
||||
</head>
|
||||
<body>
|
||||
...
|
||||
</body>
|
||||
</html>
|
||||
9
javascript/ql/src/Security/CWE-830/polyfill-sri.html
Normal file
9
javascript/ql/src/Security/CWE-830/polyfill-sri.html
Normal file
@@ -0,0 +1,9 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Polyfill demo - Cloudflare hosted with pinned version (with integrity checking for a *very limited* browser set - just an example!)</title>
|
||||
<script src="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?version=4.8.0" integrity="sha384-i0IGVuZBkKZqwXTD4CH4kcksIbFx7WKFMdxN8zUhLFHpLdELF0ym0jxa6UvLhW8/ sha384-3d4jRKquKl90C9aFG+eH4lPJmtbPHgACWHrp+VomFOxF8lzx2jxqeYkhpRg18UWC" crossorigin="anonymous"></script>
|
||||
</head>
|
||||
<body>
|
||||
...
|
||||
</body>
|
||||
</html>
|
||||
9
javascript/ql/src/Security/CWE-830/polyfill-trusted.html
Normal file
9
javascript/ql/src/Security/CWE-830/polyfill-trusted.html
Normal file
@@ -0,0 +1,9 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Polyfill demo - Cloudflare hosted with pinned version (but no integrity checking, since it is dynamically generated)</title>
|
||||
<script src="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?version=4.8.0" crossorigin="anonymous"></script>
|
||||
</head>
|
||||
<body>
|
||||
...
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user