mirror of
https://github.com/github/codeql.git
synced 2026-04-26 01:05:15 +02:00
Merge branch 'main' into js/shared-dataflow-merge-main
This commit is contained in:
@@ -1,15 +1,14 @@
|
||||
{
|
||||
"timestamp": "2023-03-23T12:04:41.317+00:00",
|
||||
"source": {
|
||||
"id": "js/internal-error",
|
||||
"name": "Internal error",
|
||||
"extractorName": "javascript"
|
||||
},
|
||||
"markdownMessage": "Internal error: com.semmle.util.exception.CatastrophicError: The TypeScript parser wrapper crashed with exit code 1",
|
||||
"severity": "unknown",
|
||||
"visibility": {
|
||||
"cliSummaryTable": true,
|
||||
"statusPage": false,
|
||||
"telemetry": true
|
||||
}
|
||||
}
|
||||
"markdownMessage": "Internal error: com.semmle.util.exception.CatastrophicError: The TypeScript parser wrapper crashed with exit code 1",
|
||||
"severity": "unknown",
|
||||
"source": {
|
||||
"extractorName": "javascript",
|
||||
"id": "js/internal-error",
|
||||
"name": "Internal error"
|
||||
},
|
||||
"visibility": {
|
||||
"cliSummaryTable": true,
|
||||
"statusPage": false,
|
||||
"telemetry": true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,2 @@
|
||||
import os
|
||||
from create_database_utils import *
|
||||
from diagnostics_test_utils import *
|
||||
|
||||
run_codeql_database_create([], lang="javascript", runFunction = runUnsuccessfully, db = None)
|
||||
|
||||
check_diagnostics()
|
||||
def test(codeql, javascript):
|
||||
codeql.database.create(_assert_failure=True)
|
||||
|
||||
@@ -1,7 +1,2 @@
|
||||
import os
|
||||
from create_database_utils import *
|
||||
from diagnostics_test_utils import *
|
||||
|
||||
run_codeql_database_create([], lang="javascript", runFunction = runSuccessfully, db = None)
|
||||
|
||||
check_diagnostics()
|
||||
def test(codeql, javascript):
|
||||
codeql.database.create()
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
from create_database_utils import *
|
||||
|
||||
run_codeql_database_create([], lang="javascript", extra_args=["-Oskip_types=true"])
|
||||
def test(codeql, javascript):
|
||||
codeql.database.create(extractor_option="skip_types=true")
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
dependencies:
|
||||
codeql/javascript-all: '*'
|
||||
codeql/javascript-queries: '*'
|
||||
warnOnImplicitThis: true
|
||||
@@ -1 +0,0 @@
|
||||
These tests are still run with the legacy test runner
|
||||
@@ -1,3 +1,22 @@
|
||||
## 1.1.1
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.1.0
|
||||
|
||||
### Major Analysis Improvements
|
||||
|
||||
* Added support for TypeScript 5.5.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Enabled type-tracking to follow content through array methods
|
||||
* Improved modeling of `Array.prototype.splice` for when it is called with more than two arguments
|
||||
|
||||
## 1.0.2
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.0.1
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
3
javascript/ql/lib/change-notes/released/1.0.2.md
Normal file
3
javascript/ql/lib/change-notes/released/1.0.2.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 1.0.2
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,5 +1,10 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
## 1.1.0
|
||||
|
||||
### Major Analysis Improvements
|
||||
|
||||
* Added support for TypeScript 5.5.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Enabled type-tracking to follow content through array methods
|
||||
* Improved modeling of `Array.prototype.splice` for when it is called with more than two arguments
|
||||
3
javascript/ql/lib/change-notes/released/1.1.1.md
Normal file
3
javascript/ql/lib/change-notes/released/1.1.1.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 1.1.1
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.0.1
|
||||
lastReleaseVersion: 1.1.1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/javascript-all
|
||||
version: 1.0.2-dev
|
||||
version: 1.1.2-dev
|
||||
groups: javascript
|
||||
dbscheme: semmlecode.javascript.dbscheme
|
||||
extractor: javascript
|
||||
@@ -16,4 +16,5 @@ dependencies:
|
||||
dataExtensions:
|
||||
- semmle/javascript/frameworks/**/model.yml
|
||||
- semmle/javascript/frameworks/**/*.model.yml
|
||||
- semmle/javascript/security/domains/**/*.model.yml
|
||||
warnOnImplicitThis: true
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/javascript-queries
|
||||
extensible: requiredHelmetSecuritySetting
|
||||
data:
|
||||
- ["frameguard"]
|
||||
- ["contentSecurityPolicy"]
|
||||
@@ -0,0 +1,208 @@
|
||||
/**
|
||||
* Provides classes for finding functionality that is loaded from untrusted sources and used in script or frame elements.
|
||||
*/
|
||||
|
||||
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();
|
||||
|
||||
/** Gets the URL of the untrusted source. */
|
||||
abstract string getUrl();
|
||||
}
|
||||
|
||||
/** Looks for static creation of an element and source. */
|
||||
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.
|
||||
exists(string hostname, string requiredCheckingHostname |
|
||||
hostname = url.regexpCapture("(?i)^(?:https?:)?//([^/]+)/.*\\.js$", 1) and
|
||||
isCdnDomainWithCheckingRequired(requiredCheckingHostname) and
|
||||
hostname = requiredCheckingHostname
|
||||
)
|
||||
}
|
||||
|
||||
/** 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 getUrl() { result = 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())
|
||||
or
|
||||
isUrlWithUntrustedDomain(super.getSourcePath())
|
||||
)
|
||||
}
|
||||
|
||||
override string getUrl() { result = 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 getUrl() { result = super.getSourcePath() }
|
||||
|
||||
override string getProblem() { result = "Iframe loaded using unencrypted connection." }
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if `url` refers to an URL that uses an untrusted domain. */
|
||||
bindingset[url]
|
||||
predicate isUrlWithUntrustedDomain(string url) {
|
||||
exists(string hostname |
|
||||
hostname = url.regexpCapture("(?i)^(?:https?:)?//([^/]+)/.*", 1) and
|
||||
isUntrustedHostname(hostname)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `hostname` refers to a domain or subdomain that is untrusted. */
|
||||
bindingset[hostname]
|
||||
predicate isUntrustedHostname(string hostname) {
|
||||
exists(string domain |
|
||||
(hostname = domain or hostname.matches("%." + domain)) and
|
||||
isUntrustedDomain(domain)
|
||||
)
|
||||
}
|
||||
|
||||
// The following predicates are extended in data extensions under javascript/ql/lib/semmle/javascript/security/domains/
|
||||
// and can be extended with custom model packs as necessary.
|
||||
/** Holds for hostnames defined in data extensions */
|
||||
extensible predicate isCdnDomainWithCheckingRequired(string hostname);
|
||||
|
||||
/** Holds for domains defined in data extensions */
|
||||
extensible predicate isUntrustedDomain(string domain);
|
||||
|
||||
/** Looks for dyanmic creation of an element and source. */
|
||||
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
|
||||
}
|
||||
|
||||
/** Get the right-hand side of an assignment to a named attribute. */
|
||||
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"))
|
||||
}
|
||||
|
||||
/** Holds if `t` tracks a URL that is loaded from an untrusted source. */
|
||||
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
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds a dataflow node is traked from an untrusted source. */
|
||||
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")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/** A script or iframe element that refers to untrusted content. */
|
||||
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 getUrl() {
|
||||
exists(DataFlow::Node n | n.asExpr() = this |
|
||||
isAssignedToSrcAttribute(name, n) and
|
||||
result = n.getStringValue()
|
||||
)
|
||||
}
|
||||
|
||||
override string getProblem() {
|
||||
name = "script" and result = "Script loaded using unencrypted connection."
|
||||
or
|
||||
name = "iframe" and result = "Iframe loaded using unencrypted connection."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/javascript-all
|
||||
extensible: isCdnDomainWithCheckingRequired
|
||||
data:
|
||||
- ["code.jquery.com"]
|
||||
- ["cdnjs.cloudflare.com"]
|
||||
- ["cdnjs.com"]
|
||||
@@ -0,0 +1,6 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/javascript-all
|
||||
extensible: isUntrustedDomain
|
||||
data:
|
||||
- ["polyfill.io"]
|
||||
@@ -0,0 +1,14 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/javascript-all
|
||||
extensible: isUntrustedDomain
|
||||
data:
|
||||
# new location of the polyfill.io CDN, which was used to serve malware. See: https://www.cside.dev/blog/the-polyfill-attack-explained
|
||||
- ["polyfill.com"]
|
||||
- ["polyfillcache.com"]
|
||||
|
||||
# domains operated by the same owner as polyfill.io, which was used to serve malware. See: https://www.cside.dev/blog/the-polyfill-attack-explained
|
||||
- ["bootcdn.net"]
|
||||
- ["bootcss.com"]
|
||||
- ["staticfile.net"]
|
||||
- ["staticfile.org"]
|
||||
@@ -1,3 +1,27 @@
|
||||
## 1.1.0
|
||||
|
||||
### New Queries
|
||||
|
||||
* Added a new query, `js/insecure-helmet-configuration`, to detect instances where Helmet middleware is configured with important security features disabled.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Added a new query, `js/functionality-from-untrusted-domain`, which detects uses in HTML and JavaScript scripts from untrusted domains, including the `polyfill.io` content delivery network
|
||||
* it can be extended to detect other compromised scripts using user-provided data extensions of the `untrustedDomain` predicate, which takes one string argument with the domain to warn on (and will warn on any subdomains too).
|
||||
* Modified existing query, `js/functionality-from-untrusted-source`, to allow adding this new query, but reusing the same logic
|
||||
* Added the ability to use data extensions to require SRI on CDN hostnames using the `isCdnDomainWithCheckingRequired` predicate, which takes one string argument of the full hostname to require SRI for.
|
||||
* Created a new library, `semmle.javascript.security.FunctionalityFromUntrustedSource`, to support both queries.
|
||||
|
||||
## 1.0.3
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Added a new experimental query, `js/cors-misconfiguration`, which detects misconfigured CORS HTTP headers in the `cors` and `apollo` libraries.
|
||||
|
||||
## 1.0.2
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.0.1
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
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>
|
||||
3
javascript/ql/src/change-notes/released/1.0.2.md
Normal file
3
javascript/ql/src/change-notes/released/1.0.2.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 1.0.2
|
||||
|
||||
No user-facing changes.
|
||||
5
javascript/ql/src/change-notes/released/1.0.3.md
Normal file
5
javascript/ql/src/change-notes/released/1.0.3.md
Normal file
@@ -0,0 +1,5 @@
|
||||
## 1.0.3
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Added a new experimental query, `js/cors-misconfiguration`, which detects misconfigured CORS HTTP headers in the `cors` and `apollo` libraries.
|
||||
13
javascript/ql/src/change-notes/released/1.1.0.md
Normal file
13
javascript/ql/src/change-notes/released/1.1.0.md
Normal file
@@ -0,0 +1,13 @@
|
||||
## 1.1.0
|
||||
|
||||
### New Queries
|
||||
|
||||
* Added a new query, `js/insecure-helmet-configuration`, to detect instances where Helmet middleware is configured with important security features disabled.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Added a new query, `js/functionality-from-untrusted-domain`, which detects uses in HTML and JavaScript scripts from untrusted domains, including the `polyfill.io` content delivery network
|
||||
* it can be extended to detect other compromised scripts using user-provided data extensions of the `untrustedDomain` predicate, which takes one string argument with the domain to warn on (and will warn on any subdomains too).
|
||||
* Modified existing query, `js/functionality-from-untrusted-source`, to allow adding this new query, but reusing the same logic
|
||||
* Added the ability to use data extensions to require SRI on CDN hostnames using the `isCdnDomainWithCheckingRequired` predicate, which takes one string argument of the full hostname to require SRI for.
|
||||
* Created a new library, `semmle.javascript.security.FunctionalityFromUntrustedSource`, to support both queries.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.0.1
|
||||
lastReleaseVersion: 1.1.0
|
||||
|
||||
36
javascript/ql/src/experimental/Security/CWE-942/Apollo.qll
Normal file
36
javascript/ql/src/experimental/Security/CWE-942/Apollo.qll
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Provides classes for working with Apollo GraphQL connectors.
|
||||
*/
|
||||
|
||||
import javascript
|
||||
|
||||
/** Provides classes modeling the apollo packages [@apollo/server](https://npmjs.com/package/@apollo/server`) */
|
||||
module Apollo {
|
||||
/** Get a reference to the `ApolloServer` class. */
|
||||
private API::Node apollo() {
|
||||
result =
|
||||
API::moduleImport([
|
||||
"@apollo/server", "@apollo/apollo-server-express", "@apollo/apollo-server-core",
|
||||
"apollo-server", "apollo-server-express"
|
||||
]).getMember("ApolloServer")
|
||||
}
|
||||
|
||||
/** Gets a reference to the `gql` function that parses GraphQL strings. */
|
||||
private API::Node gql() {
|
||||
result =
|
||||
API::moduleImport([
|
||||
"@apollo/server", "@apollo/apollo-server-express", "@apollo/apollo-server-core",
|
||||
"apollo-server", "apollo-server-express"
|
||||
]).getMember("gql")
|
||||
}
|
||||
|
||||
/** An instantiation of an `ApolloServer`. */
|
||||
class ApolloServer extends API::NewNode {
|
||||
ApolloServer() { this = apollo().getAnInstantiation() }
|
||||
}
|
||||
|
||||
/** A string that is interpreted as a GraphQL query by a `apollo` package. */
|
||||
private class ApolloGraphQLString extends GraphQL::GraphQLString {
|
||||
ApolloGraphQLString() { this = gql().getACall().getArgument(0) }
|
||||
}
|
||||
}
|
||||
24
javascript/ql/src/experimental/Security/CWE-942/Cors.qll
Normal file
24
javascript/ql/src/experimental/Security/CWE-942/Cors.qll
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Provides classes for working with Cors connectors.
|
||||
*/
|
||||
|
||||
import javascript
|
||||
|
||||
/** Provides classes modeling the [cors](https://npmjs.com/package/cors) library. */
|
||||
module Cors {
|
||||
/**
|
||||
* An expression that creates a new CORS configuration.
|
||||
*/
|
||||
class Cors extends DataFlow::CallNode {
|
||||
Cors() { this = DataFlow::moduleImport("cors").getAnInvocation() }
|
||||
|
||||
/** Get the options used to configure Cors */
|
||||
DataFlow::Node getOptionsArgument() { result = this.getArgument(0) }
|
||||
|
||||
/** Holds if cors is using default configuration */
|
||||
predicate isDefault() { this.getNumArgument() = 0 }
|
||||
|
||||
/** Gets the value of the `origin` option used to configure this Cors instance. */
|
||||
DataFlow::Node getOrigin() { result = this.getOptionArgument(0, "origin") }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
|
||||
A server can use <code>CORS</code> (Cross-Origin Resource Sharing) to relax the
|
||||
restrictions imposed by the <code>SOP</code> (Same-Origin Policy), allowing controlled, secure
|
||||
cross-origin requests when necessary.
|
||||
|
||||
A server with an overly permissive <code>CORS</code> configuration may inadvertently
|
||||
expose sensitive data or lead to <code>CSRF</code> which is an attack that allows attackers to trick
|
||||
users into performing unwanted operations in websites they're authenticated to.
|
||||
|
||||
</p>
|
||||
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
|
||||
When the <code>origin</code> is set to <code>true</code>, it signifies that the server
|
||||
is accepting requests from <code>any</code> origin, potentially exposing the system to
|
||||
CSRF attacks. This can be fixed using <code>false</code> as origin value or using a whitelist.
|
||||
|
||||
</p>
|
||||
<p>
|
||||
|
||||
On the other hand, if the <code>origin</code> is
|
||||
set to <code>null</code>, it can be exploited by an attacker to deceive a user into making
|
||||
requests from a <code>null</code> origin form, often hosted within a sandboxed iframe.
|
||||
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
||||
If the <code>origin</code> value is user controlled, make sure that the data
|
||||
is properly sanitized.
|
||||
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
|
||||
In the example below, the <code>server_1</code> accepts requests from any origin
|
||||
since the value of <code>origin</code> is set to <code>true</code>.
|
||||
And <code>server_2</code>'s origin is user-controlled.
|
||||
|
||||
</p>
|
||||
|
||||
<sample src="examples/CorsPermissiveConfigurationBad.js"/>
|
||||
|
||||
<p>
|
||||
|
||||
In the example below, the <code>server_1</code> CORS is restrictive so it's not
|
||||
vulnerable to CSRF attacks. And <code>server_2</code>'s is using properly sanitized
|
||||
user-controlled data.
|
||||
|
||||
</p>
|
||||
|
||||
<sample src="examples/CorsPermissiveConfigurationGood.js"/>
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>Mozilla Developer Network: <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin">CORS, Access-Control-Allow-Origin</a>.</li>
|
||||
<li>W3C: <a href="https://w3c.github.io/webappsec-cors-for-developers/#resources">CORS for developers, Advice for Resource Owners</a></li>
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* @name overly CORS configuration
|
||||
* @description Misconfiguration of CORS HTTP headers allows CSRF attacks.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 7.5
|
||||
* @precision high
|
||||
* @id js/cors-misconfiguration
|
||||
* @tags security
|
||||
* external/cwe/cwe-942
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import CorsPermissiveConfigurationQuery
|
||||
import DataFlow::PathGraph
|
||||
|
||||
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where cfg.hasFlowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "CORS Origin misconfiguration due to a $@.", source.getNode(),
|
||||
"too permissive or user controlled value"
|
||||
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Provides default sources, sinks and sanitizers for reasoning about
|
||||
* overly permissive CORS configurations, as well as
|
||||
* extension points for adding your own.
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import Cors::Cors
|
||||
import Apollo::Apollo
|
||||
|
||||
/** Module containing sources, sinks, and sanitizers for overly permissive CORS configurations. */
|
||||
module CorsPermissiveConfiguration {
|
||||
/**
|
||||
* A data flow source for permissive CORS configuration.
|
||||
*/
|
||||
abstract class Source extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A data flow sink for permissive CORS configuration.
|
||||
*/
|
||||
abstract class Sink extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A sanitizer for permissive CORS configuration.
|
||||
*/
|
||||
abstract class Sanitizer extends DataFlow::Node { }
|
||||
|
||||
/** A source of remote user input, considered as a flow source for CORS misconfiguration. */
|
||||
class RemoteFlowSourceAsSource extends Source instanceof RemoteFlowSource {
|
||||
RemoteFlowSourceAsSource() { not this instanceof ClientSideRemoteFlowSource }
|
||||
}
|
||||
|
||||
/** A flow label representing `true` and `null` values. */
|
||||
abstract class TrueAndNull extends DataFlow::FlowLabel {
|
||||
TrueAndNull() { this = "TrueAndNull" }
|
||||
}
|
||||
|
||||
TrueAndNull truenullLabel() { any() }
|
||||
|
||||
/** A flow label representing `*` value. */
|
||||
abstract class Wildcard extends DataFlow::FlowLabel {
|
||||
Wildcard() { this = "Wildcard" }
|
||||
}
|
||||
|
||||
Wildcard wildcardLabel() { any() }
|
||||
|
||||
/** An overly permissive value for `origin` (Apollo) */
|
||||
class TrueNullValue extends Source {
|
||||
TrueNullValue() { this.mayHaveBooleanValue(true) or this.asExpr() instanceof NullLiteral }
|
||||
}
|
||||
|
||||
/** An overly permissive value for `origin` (Express) */
|
||||
class WildcardValue extends Source {
|
||||
WildcardValue() { this.mayHaveStringValue("*") }
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of cors origin when initializing the application.
|
||||
*/
|
||||
class CorsApolloServer extends Sink, DataFlow::ValueNode {
|
||||
CorsApolloServer() {
|
||||
exists(ApolloServer agql |
|
||||
this =
|
||||
agql.getOptionArgument(0, "cors").getALocalSource().getAPropertyWrite("origin").getRhs()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of cors origin when initializing the application.
|
||||
*/
|
||||
class ExpressCors extends Sink, DataFlow::ValueNode {
|
||||
ExpressCors() {
|
||||
exists(CorsConfiguration config | this = config.getCorsConfiguration().getOrigin())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An express route setup configured with the `cors` package.
|
||||
*/
|
||||
class CorsConfiguration extends DataFlow::MethodCallNode {
|
||||
Cors corsConfig;
|
||||
|
||||
CorsConfiguration() {
|
||||
exists(Express::RouteSetup setup | this = setup |
|
||||
if setup.isUseCall()
|
||||
then corsConfig = setup.getArgument(0)
|
||||
else corsConfig = setup.getArgument(any(int i | i > 0))
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the expression that configures `cors` on this route setup. */
|
||||
Cors getCorsConfiguration() { result = corsConfig }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Provides a dataflow taint tracking configuration for reasoning
|
||||
* about overly permissive CORS configurations.
|
||||
*
|
||||
* Note, for performance reasons: only import this file if
|
||||
* `CorsPermissiveConfiguration::Configuration` is needed,
|
||||
* otherwise `CorsPermissiveConfigurationCustomizations` should
|
||||
* be imported instead.
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import CorsPermissiveConfigurationCustomizations::CorsPermissiveConfiguration
|
||||
|
||||
/**
|
||||
* A data flow configuration for overly permissive CORS configuration.
|
||||
*/
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "CorsPermissiveConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) {
|
||||
source instanceof TrueNullValue and label = truenullLabel()
|
||||
or
|
||||
source instanceof WildcardValue and label = wildcardLabel()
|
||||
or
|
||||
source instanceof RemoteFlowSource and label = DataFlow::FlowLabel::taint()
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) {
|
||||
sink instanceof CorsApolloServer and label = [DataFlow::FlowLabel::taint(), truenullLabel()]
|
||||
or
|
||||
sink instanceof ExpressCors and label = [DataFlow::FlowLabel::taint(), wildcardLabel()]
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
super.isSanitizer(node) or
|
||||
node instanceof Sanitizer
|
||||
}
|
||||
}
|
||||
|
||||
private class WildcardActivated extends DataFlow::FlowLabel, Wildcard {
|
||||
WildcardActivated() { this = this }
|
||||
}
|
||||
|
||||
private class TrueAndNullActivated extends DataFlow::FlowLabel, TrueAndNull {
|
||||
TrueAndNullActivated() { this = this }
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { ApolloServer } from 'apollo-server';
|
||||
var https = require('https'),
|
||||
url = require('url');
|
||||
|
||||
var server = https.createServer(function () { });
|
||||
|
||||
server.on('request', function (req, res) {
|
||||
// BAD: origin is too permissive
|
||||
const server_1 = new ApolloServer({
|
||||
cors: { origin: true }
|
||||
});
|
||||
|
||||
let user_origin = url.parse(req.url, true).query.origin;
|
||||
// BAD: CORS is controlled by user
|
||||
const server_2 = new ApolloServer({
|
||||
cors: { origin: user_origin }
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
import { ApolloServer } from 'apollo-server';
|
||||
var https = require('https'),
|
||||
url = require('url');
|
||||
|
||||
var server = https.createServer(function () { });
|
||||
|
||||
server.on('request', function (req, res) {
|
||||
// GOOD: origin is restrictive
|
||||
const server_1 = new ApolloServer({
|
||||
cors: { origin: false }
|
||||
});
|
||||
|
||||
let user_origin = url.parse(req.url, true).query.origin;
|
||||
// GOOD: user data is properly sanitized
|
||||
const server_2 = new ApolloServer({
|
||||
cors: { origin: (user_origin === "https://allowed1.com" || user_origin === "https://allowed2.com") ? user_origin : false }
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/javascript-queries
|
||||
version: 1.0.2-dev
|
||||
version: 1.1.1-dev
|
||||
groups:
|
||||
- javascript
|
||||
- queries
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
nodes
|
||||
| apollo-test.js:8:9:8:59 | user_origin |
|
||||
| apollo-test.js:8:23:8:46 | url.par ... , true) |
|
||||
| apollo-test.js:8:23:8:52 | url.par ... ).query |
|
||||
| apollo-test.js:8:23:8:59 | url.par ... .origin |
|
||||
| apollo-test.js:8:33:8:39 | req.url |
|
||||
| apollo-test.js:8:33:8:39 | req.url |
|
||||
| apollo-test.js:11:25:11:28 | true |
|
||||
| apollo-test.js:11:25:11:28 | true |
|
||||
| apollo-test.js:11:25:11:28 | true |
|
||||
| apollo-test.js:21:25:21:28 | null |
|
||||
| apollo-test.js:21:25:21:28 | null |
|
||||
| apollo-test.js:21:25:21:28 | null |
|
||||
| apollo-test.js:26:25:26:35 | user_origin |
|
||||
| apollo-test.js:26:25:26:35 | user_origin |
|
||||
| express-test.js:10:9:10:59 | user_origin |
|
||||
| express-test.js:10:23:10:46 | url.par ... , true) |
|
||||
| express-test.js:10:23:10:52 | url.par ... ).query |
|
||||
| express-test.js:10:23:10:59 | url.par ... .origin |
|
||||
| express-test.js:10:33:10:39 | req.url |
|
||||
| express-test.js:10:33:10:39 | req.url |
|
||||
| express-test.js:26:17:26:19 | '*' |
|
||||
| express-test.js:26:17:26:19 | '*' |
|
||||
| express-test.js:26:17:26:19 | '*' |
|
||||
| express-test.js:33:17:33:27 | user_origin |
|
||||
| express-test.js:33:17:33:27 | user_origin |
|
||||
edges
|
||||
| apollo-test.js:8:9:8:59 | user_origin | apollo-test.js:26:25:26:35 | user_origin |
|
||||
| apollo-test.js:8:9:8:59 | user_origin | apollo-test.js:26:25:26:35 | user_origin |
|
||||
| apollo-test.js:8:23:8:46 | url.par ... , true) | apollo-test.js:8:23:8:52 | url.par ... ).query |
|
||||
| apollo-test.js:8:23:8:52 | url.par ... ).query | apollo-test.js:8:23:8:59 | url.par ... .origin |
|
||||
| apollo-test.js:8:23:8:59 | url.par ... .origin | apollo-test.js:8:9:8:59 | user_origin |
|
||||
| apollo-test.js:8:33:8:39 | req.url | apollo-test.js:8:23:8:46 | url.par ... , true) |
|
||||
| apollo-test.js:8:33:8:39 | req.url | apollo-test.js:8:23:8:46 | url.par ... , true) |
|
||||
| apollo-test.js:11:25:11:28 | true | apollo-test.js:11:25:11:28 | true |
|
||||
| apollo-test.js:21:25:21:28 | null | apollo-test.js:21:25:21:28 | null |
|
||||
| express-test.js:10:9:10:59 | user_origin | express-test.js:33:17:33:27 | user_origin |
|
||||
| express-test.js:10:9:10:59 | user_origin | express-test.js:33:17:33:27 | user_origin |
|
||||
| express-test.js:10:23:10:46 | url.par ... , true) | express-test.js:10:23:10:52 | url.par ... ).query |
|
||||
| express-test.js:10:23:10:52 | url.par ... ).query | express-test.js:10:23:10:59 | url.par ... .origin |
|
||||
| express-test.js:10:23:10:59 | url.par ... .origin | express-test.js:10:9:10:59 | user_origin |
|
||||
| express-test.js:10:33:10:39 | req.url | express-test.js:10:23:10:46 | url.par ... , true) |
|
||||
| express-test.js:10:33:10:39 | req.url | express-test.js:10:23:10:46 | url.par ... , true) |
|
||||
| express-test.js:26:17:26:19 | '*' | express-test.js:26:17:26:19 | '*' |
|
||||
#select
|
||||
| apollo-test.js:11:25:11:28 | true | apollo-test.js:11:25:11:28 | true | apollo-test.js:11:25:11:28 | true | CORS Origin misconfiguration due to a $@. | apollo-test.js:11:25:11:28 | true | too permissive or user controlled value |
|
||||
| apollo-test.js:21:25:21:28 | null | apollo-test.js:21:25:21:28 | null | apollo-test.js:21:25:21:28 | null | CORS Origin misconfiguration due to a $@. | apollo-test.js:21:25:21:28 | null | too permissive or user controlled value |
|
||||
| apollo-test.js:26:25:26:35 | user_origin | apollo-test.js:8:33:8:39 | req.url | apollo-test.js:26:25:26:35 | user_origin | CORS Origin misconfiguration due to a $@. | apollo-test.js:8:33:8:39 | req.url | too permissive or user controlled value |
|
||||
| express-test.js:26:17:26:19 | '*' | express-test.js:26:17:26:19 | '*' | express-test.js:26:17:26:19 | '*' | CORS Origin misconfiguration due to a $@. | express-test.js:26:17:26:19 | '*' | too permissive or user controlled value |
|
||||
| express-test.js:33:17:33:27 | user_origin | express-test.js:10:33:10:39 | req.url | express-test.js:33:17:33:27 | user_origin | CORS Origin misconfiguration due to a $@. | express-test.js:10:33:10:39 | req.url | too permissive or user controlled value |
|
||||
@@ -0,0 +1 @@
|
||||
./experimental/Security/CWE-942/CorsPermissiveConfiguration.ql
|
||||
@@ -0,0 +1,28 @@
|
||||
import { ApolloServer } from 'apollo-server';
|
||||
var https = require('https'),
|
||||
url = require('url');
|
||||
|
||||
var server = https.createServer(function () { });
|
||||
|
||||
server.on('request', function (req, res) {
|
||||
let user_origin = url.parse(req.url, true).query.origin;
|
||||
// BAD: CORS too permissive
|
||||
const server_1 = new ApolloServer({
|
||||
cors: { origin: true }
|
||||
});
|
||||
|
||||
// GOOD: restrictive CORS
|
||||
const server_2 = new ApolloServer({
|
||||
cors: false
|
||||
});
|
||||
|
||||
// BAD: CORS too permissive
|
||||
const server_3 = new ApolloServer({
|
||||
cors: { origin: null }
|
||||
});
|
||||
|
||||
// BAD: CORS is controlled by user
|
||||
const server_4 = new ApolloServer({
|
||||
cors: { origin: user_origin }
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
const cors = require('cors');
|
||||
var express = require('express');
|
||||
|
||||
var https = require('https'),
|
||||
url = require('url');
|
||||
|
||||
var server = https.createServer(function () { });
|
||||
|
||||
server.on('request', function (req, res) {
|
||||
let user_origin = url.parse(req.url, true).query.origin;
|
||||
|
||||
// BAD: CORS too permissive, default value is *
|
||||
var app1 = express();
|
||||
app1.use(cors());
|
||||
|
||||
// GOOD: restrictive CORS
|
||||
var app2 = express();
|
||||
var corsOptions2 = {
|
||||
origin: ["https://example1.com", "https://example2.com"],
|
||||
};
|
||||
app2.use(cors(corsOptions2));
|
||||
|
||||
// BAD: CORS too permissive
|
||||
var app3 = express();
|
||||
var corsOption3 = {
|
||||
origin: '*'
|
||||
};
|
||||
app3.use(cors(corsOption3));
|
||||
|
||||
// BAD: CORS is controlled by user
|
||||
var app4 = express();
|
||||
var corsOption4 = {
|
||||
origin: user_origin
|
||||
};
|
||||
app4.use(cors(corsOption4));
|
||||
});
|
||||
@@ -126,6 +126,9 @@ nodes
|
||||
| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
|
||||
| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
|
||||
| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
|
||||
| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
|
||||
| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
|
||||
| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
|
||||
| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
|
||||
| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
|
||||
| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
|
||||
@@ -1817,8 +1820,65 @@ nodes
|
||||
| tst.ts:494:24:494:24 | [Literal] 0 | semmle.label | [Literal] 0 |
|
||||
| tst.ts:494:28:494:33 | [Literal] "even" | semmle.label | [Literal] "even" |
|
||||
| tst.ts:494:36:494:40 | [Literal] "odd" | semmle.label | [Literal] "odd" |
|
||||
| tst.ts:498:1:511:1 | [NamespaceDeclaration] module ... } } } | semmle.label | [NamespaceDeclaration] module ... } } } |
|
||||
| tst.ts:498:1:511:1 | [NamespaceDeclaration] module ... } } } | semmle.order | 91 |
|
||||
| tst.ts:498:8:498:11 | [VarDecl] TS55 | semmle.label | [VarDecl] TS55 |
|
||||
| tst.ts:499:3:500:40 | [DeclStmt] const strings = ... | semmle.label | [DeclStmt] const strings = ... |
|
||||
| tst.ts:499:9:499:15 | [VarDecl] strings | semmle.label | [VarDecl] strings |
|
||||
| tst.ts:499:9:500:39 | [VariableDeclarator] strings ... tring") | semmle.label | [VariableDeclarator] strings ... tring") |
|
||||
| tst.ts:499:19:499:32 | [ParExpr] (["foo", 123]) | semmle.label | [ParExpr] (["foo", 123]) |
|
||||
| tst.ts:499:19:500:11 | [DotExpr] (["foo" ... .filter | semmle.label | [DotExpr] (["foo" ... .filter |
|
||||
| tst.ts:499:19:500:39 | [MethodCallExpr] (["foo" ... tring") | semmle.label | [MethodCallExpr] (["foo" ... tring") |
|
||||
| tst.ts:499:20:499:31 | [ArrayExpr] ["foo", 123] | semmle.label | [ArrayExpr] ["foo", 123] |
|
||||
| tst.ts:499:21:499:25 | [Literal] "foo" | semmle.label | [Literal] "foo" |
|
||||
| tst.ts:499:28:499:30 | [Literal] 123 | semmle.label | [Literal] 123 |
|
||||
| tst.ts:500:6:500:11 | [Label] filter | semmle.label | [Label] filter |
|
||||
| tst.ts:500:13:500:13 | [SimpleParameter] s | semmle.label | [SimpleParameter] s |
|
||||
| tst.ts:500:13:500:38 | [ArrowFunctionExpr] s => ty ... string" | semmle.label | [ArrowFunctionExpr] s => ty ... string" |
|
||||
| tst.ts:500:18:500:25 | [UnaryExpr] typeof s | semmle.label | [UnaryExpr] typeof s |
|
||||
| tst.ts:500:18:500:38 | [BinaryExpr] typeof ... string" | semmle.label | [BinaryExpr] typeof ... string" |
|
||||
| tst.ts:500:25:500:25 | [VarRef] s | semmle.label | [VarRef] s |
|
||||
| tst.ts:500:31:500:38 | [Literal] "string" | semmle.label | [Literal] "string" |
|
||||
| tst.ts:502:3:504:3 | [ForOfStmt] for (co ... 5.4 } | semmle.label | [ForOfStmt] for (co ... 5.4 } |
|
||||
| tst.ts:502:8:502:16 | [DeclStmt] const str = ... | semmle.label | [DeclStmt] const str = ... |
|
||||
| tst.ts:502:14:502:16 | [VarDecl] str | semmle.label | [VarDecl] str |
|
||||
| tst.ts:502:14:502:16 | [VariableDeclarator] str | semmle.label | [VariableDeclarator] str |
|
||||
| tst.ts:502:21:502:27 | [VarRef] strings | semmle.label | [VarRef] strings |
|
||||
| tst.ts:502:30:504:3 | [BlockStmt] { s ... 5.4 } | semmle.label | [BlockStmt] { s ... 5.4 } |
|
||||
| tst.ts:503:5:503:7 | [VarRef] str | semmle.label | [VarRef] str |
|
||||
| tst.ts:503:5:503:19 | [DotExpr] str.toLowerCase | semmle.label | [DotExpr] str.toLowerCase |
|
||||
| tst.ts:503:5:503:21 | [MethodCallExpr] str.toLowerCase() | semmle.label | [MethodCallExpr] str.toLowerCase() |
|
||||
| tst.ts:503:5:503:22 | [ExprStmt] str.toLowerCase(); | semmle.label | [ExprStmt] str.toLowerCase(); |
|
||||
| tst.ts:503:9:503:19 | [Label] toLowerCase | semmle.label | [Label] toLowerCase |
|
||||
| tst.ts:506:3:510:3 | [FunctionDeclStmt] functio ... } } | semmle.label | [FunctionDeclStmt] functio ... } } |
|
||||
| tst.ts:506:12:506:13 | [VarDecl] f1 | semmle.label | [VarDecl] f1 |
|
||||
| tst.ts:506:15:506:17 | [SimpleParameter] obj | semmle.label | [SimpleParameter] obj |
|
||||
| tst.ts:506:20:506:25 | [LocalTypeAccess] Record | semmle.label | [LocalTypeAccess] Record |
|
||||
| tst.ts:506:20:506:42 | [GenericTypeExpr] Record< ... nknown> | semmle.label | [GenericTypeExpr] Record< ... nknown> |
|
||||
| tst.ts:506:27:506:32 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
|
||||
| tst.ts:506:35:506:41 | [KeywordTypeExpr] unknown | semmle.label | [KeywordTypeExpr] unknown |
|
||||
| tst.ts:506:45:506:47 | [SimpleParameter] key | semmle.label | [SimpleParameter] key |
|
||||
| tst.ts:506:50:506:55 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
|
||||
| tst.ts:506:58:510:3 | [BlockStmt] { i ... } } | semmle.label | [BlockStmt] { i ... } } |
|
||||
| tst.ts:507:5:509:5 | [IfStmt] if (typ ... r } | semmle.label | [IfStmt] if (typ ... r } |
|
||||
| tst.ts:507:9:507:23 | [UnaryExpr] typeof obj[key] | semmle.label | [UnaryExpr] typeof obj[key] |
|
||||
| tst.ts:507:9:507:36 | [BinaryExpr] typeof ... string" | semmle.label | [BinaryExpr] typeof ... string" |
|
||||
| tst.ts:507:16:507:18 | [VarRef] obj | semmle.label | [VarRef] obj |
|
||||
| tst.ts:507:16:507:23 | [IndexExpr] obj[key] | semmle.label | [IndexExpr] obj[key] |
|
||||
| tst.ts:507:20:507:22 | [VarRef] key | semmle.label | [VarRef] key |
|
||||
| tst.ts:507:29:507:36 | [Literal] "string" | semmle.label | [Literal] "string" |
|
||||
| tst.ts:507:39:509:5 | [BlockStmt] { ... r } | semmle.label | [BlockStmt] { ... r } |
|
||||
| tst.ts:508:7:508:39 | [DeclStmt] var str = ... | semmle.label | [DeclStmt] var str = ... |
|
||||
| tst.ts:508:11:508:13 | [VarDecl] str | semmle.label | [VarDecl] str |
|
||||
| tst.ts:508:11:508:38 | [VariableDeclarator] str = o ... rCase() | semmle.label | [VariableDeclarator] str = o ... rCase() |
|
||||
| tst.ts:508:17:508:19 | [VarRef] obj | semmle.label | [VarRef] obj |
|
||||
| tst.ts:508:17:508:24 | [IndexExpr] obj[key] | semmle.label | [IndexExpr] obj[key] |
|
||||
| tst.ts:508:17:508:36 | [DotExpr] obj[key].toUpperCase | semmle.label | [DotExpr] obj[key].toUpperCase |
|
||||
| tst.ts:508:17:508:38 | [MethodCallExpr] obj[key ... rCase() | semmle.label | [MethodCallExpr] obj[key ... rCase() |
|
||||
| tst.ts:508:21:508:23 | [VarRef] key | semmle.label | [VarRef] key |
|
||||
| tst.ts:508:26:508:36 | [Label] toUpperCase | semmle.label | [Label] toUpperCase |
|
||||
| tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.label | [ExportDeclaration] export ... 'b'; } |
|
||||
| tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.order | 91 |
|
||||
| tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.order | 92 |
|
||||
| tstModuleCJS.cts:1:8:3:1 | [FunctionDeclStmt] functio ... 'b'; } | semmle.label | [FunctionDeclStmt] functio ... 'b'; } |
|
||||
| tstModuleCJS.cts:1:17:1:28 | [VarDecl] tstModuleCJS | semmle.label | [VarDecl] tstModuleCJS |
|
||||
| tstModuleCJS.cts:1:33:1:35 | [LiteralTypeExpr] 'a' | semmle.label | [LiteralTypeExpr] 'a' |
|
||||
@@ -1836,7 +1896,7 @@ nodes
|
||||
| tstModuleCJS.cts:2:34:2:36 | [Literal] 'a' | semmle.label | [Literal] 'a' |
|
||||
| tstModuleCJS.cts:2:40:2:42 | [Literal] 'b' | semmle.label | [Literal] 'b' |
|
||||
| tstModuleES.mts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.label | [ExportDeclaration] export ... 'b'; } |
|
||||
| tstModuleES.mts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.order | 92 |
|
||||
| tstModuleES.mts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.order | 93 |
|
||||
| tstModuleES.mts:1:16:3:1 | [FunctionDeclStmt] functio ... 'b'; } | semmle.label | [FunctionDeclStmt] functio ... 'b'; } |
|
||||
| tstModuleES.mts:1:25:1:35 | [VarDecl] tstModuleES | semmle.label | [VarDecl] tstModuleES |
|
||||
| tstModuleES.mts:1:40:1:42 | [LiteralTypeExpr] 'a' | semmle.label | [LiteralTypeExpr] 'a' |
|
||||
@@ -1854,7 +1914,7 @@ nodes
|
||||
| tstModuleES.mts:2:34:2:36 | [Literal] 'a' | semmle.label | [Literal] 'a' |
|
||||
| tstModuleES.mts:2:40:2:42 | [Literal] 'b' | semmle.label | [Literal] 'b' |
|
||||
| tstSuffixA.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.label | [ExportDeclaration] export ... .ts'; } |
|
||||
| tstSuffixA.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 93 |
|
||||
| tstSuffixA.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 94 |
|
||||
| tstSuffixA.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | semmle.label | [FunctionDeclStmt] functio ... .ts'; } |
|
||||
| tstSuffixA.ts:1:17:1:28 | [VarDecl] resolvedFile | semmle.label | [VarDecl] resolvedFile |
|
||||
| tstSuffixA.ts:1:33:1:47 | [LiteralTypeExpr] 'tstSuffixA.ts' | semmle.label | [LiteralTypeExpr] 'tstSuffixA.ts' |
|
||||
@@ -1862,7 +1922,7 @@ nodes
|
||||
| tstSuffixA.ts:2:5:2:27 | [ReturnStmt] return ... xA.ts'; | semmle.label | [ReturnStmt] return ... xA.ts'; |
|
||||
| tstSuffixA.ts:2:12:2:26 | [Literal] 'tstSuffixA.ts' | semmle.label | [Literal] 'tstSuffixA.ts' |
|
||||
| tstSuffixB.ios.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.label | [ExportDeclaration] export ... .ts'; } |
|
||||
| tstSuffixB.ios.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 94 |
|
||||
| tstSuffixB.ios.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 95 |
|
||||
| tstSuffixB.ios.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | semmle.label | [FunctionDeclStmt] functio ... .ts'; } |
|
||||
| tstSuffixB.ios.ts:1:17:1:28 | [VarDecl] resolvedFile | semmle.label | [VarDecl] resolvedFile |
|
||||
| tstSuffixB.ios.ts:1:33:1:51 | [LiteralTypeExpr] 'tstSuffixB.ios.ts' | semmle.label | [LiteralTypeExpr] 'tstSuffixB.ios.ts' |
|
||||
@@ -1870,7 +1930,7 @@ nodes
|
||||
| tstSuffixB.ios.ts:2:5:2:31 | [ReturnStmt] return ... os.ts'; | semmle.label | [ReturnStmt] return ... os.ts'; |
|
||||
| tstSuffixB.ios.ts:2:12:2:30 | [Literal] 'tstSuffixB.ios.ts' | semmle.label | [Literal] 'tstSuffixB.ios.ts' |
|
||||
| tstSuffixB.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.label | [ExportDeclaration] export ... .ts'; } |
|
||||
| tstSuffixB.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 95 |
|
||||
| tstSuffixB.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 96 |
|
||||
| tstSuffixB.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | semmle.label | [FunctionDeclStmt] functio ... .ts'; } |
|
||||
| tstSuffixB.ts:1:17:1:28 | [VarDecl] resolvedFile | semmle.label | [VarDecl] resolvedFile |
|
||||
| tstSuffixB.ts:1:33:1:47 | [LiteralTypeExpr] 'tstSuffixB.ts' | semmle.label | [LiteralTypeExpr] 'tstSuffixB.ts' |
|
||||
@@ -1878,16 +1938,16 @@ nodes
|
||||
| tstSuffixB.ts:2:5:2:27 | [ReturnStmt] return ... xB.ts'; | semmle.label | [ReturnStmt] return ... xB.ts'; |
|
||||
| tstSuffixB.ts:2:12:2:26 | [Literal] 'tstSuffixB.ts' | semmle.label | [Literal] 'tstSuffixB.ts' |
|
||||
| type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type B = boolean; |
|
||||
| type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | semmle.order | 96 |
|
||||
| type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | semmle.order | 97 |
|
||||
| type_alias.ts:1:6:1:6 | [Identifier] B | semmle.label | [Identifier] B |
|
||||
| type_alias.ts:1:10:1:16 | [KeywordTypeExpr] boolean | semmle.label | [KeywordTypeExpr] boolean |
|
||||
| type_alias.ts:3:1:3:9 | [DeclStmt] var b = ... | semmle.label | [DeclStmt] var b = ... |
|
||||
| type_alias.ts:3:1:3:9 | [DeclStmt] var b = ... | semmle.order | 97 |
|
||||
| type_alias.ts:3:1:3:9 | [DeclStmt] var b = ... | semmle.order | 98 |
|
||||
| type_alias.ts:3:5:3:5 | [VarDecl] b | semmle.label | [VarDecl] b |
|
||||
| type_alias.ts:3:5:3:8 | [VariableDeclarator] b: B | semmle.label | [VariableDeclarator] b: B |
|
||||
| type_alias.ts:3:8:3:8 | [LocalTypeAccess] B | semmle.label | [LocalTypeAccess] B |
|
||||
| type_alias.ts:5:1:5:50 | [TypeAliasDeclaration,TypeDefinition] type Va ... ay<T>>; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Va ... ay<T>>; |
|
||||
| type_alias.ts:5:1:5:50 | [TypeAliasDeclaration,TypeDefinition] type Va ... ay<T>>; | semmle.order | 98 |
|
||||
| type_alias.ts:5:1:5:50 | [TypeAliasDeclaration,TypeDefinition] type Va ... ay<T>>; | semmle.order | 99 |
|
||||
| type_alias.ts:5:6:5:17 | [Identifier] ValueOrArray | semmle.label | [Identifier] ValueOrArray |
|
||||
| type_alias.ts:5:19:5:19 | [Identifier] T | semmle.label | [Identifier] T |
|
||||
| type_alias.ts:5:19:5:19 | [TypeParameter] T | semmle.label | [TypeParameter] T |
|
||||
@@ -1899,14 +1959,14 @@ nodes
|
||||
| type_alias.ts:5:34:5:48 | [GenericTypeExpr] ValueOrArray<T> | semmle.label | [GenericTypeExpr] ValueOrArray<T> |
|
||||
| type_alias.ts:5:47:5:47 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T |
|
||||
| type_alias.ts:7:1:7:28 | [DeclStmt] var c = ... | semmle.label | [DeclStmt] var c = ... |
|
||||
| type_alias.ts:7:1:7:28 | [DeclStmt] var c = ... | semmle.order | 99 |
|
||||
| type_alias.ts:7:1:7:28 | [DeclStmt] var c = ... | semmle.order | 100 |
|
||||
| type_alias.ts:7:5:7:5 | [VarDecl] c | semmle.label | [VarDecl] c |
|
||||
| type_alias.ts:7:5:7:27 | [VariableDeclarator] c: Valu ... number> | semmle.label | [VariableDeclarator] c: Valu ... number> |
|
||||
| type_alias.ts:7:8:7:19 | [LocalTypeAccess] ValueOrArray | semmle.label | [LocalTypeAccess] ValueOrArray |
|
||||
| type_alias.ts:7:8:7:27 | [GenericTypeExpr] ValueOrArray<number> | semmle.label | [GenericTypeExpr] ValueOrArray<number> |
|
||||
| type_alias.ts:7:21:7:26 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number |
|
||||
| type_alias.ts:9:1:15:13 | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; |
|
||||
| type_alias.ts:9:1:15:13 | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | semmle.order | 100 |
|
||||
| type_alias.ts:9:1:15:13 | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | semmle.order | 101 |
|
||||
| type_alias.ts:9:6:9:9 | [Identifier] Json | semmle.label | [Identifier] Json |
|
||||
| type_alias.ts:10:5:15:12 | [UnionTypeExpr] \| strin ... Json[] | semmle.label | [UnionTypeExpr] \| strin ... Json[] |
|
||||
| type_alias.ts:10:7:10:12 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
|
||||
@@ -1922,12 +1982,12 @@ nodes
|
||||
| type_alias.ts:15:7:15:10 | [LocalTypeAccess] Json | semmle.label | [LocalTypeAccess] Json |
|
||||
| type_alias.ts:15:7:15:12 | [ArrayTypeExpr] Json[] | semmle.label | [ArrayTypeExpr] Json[] |
|
||||
| type_alias.ts:17:1:17:15 | [DeclStmt] var json = ... | semmle.label | [DeclStmt] var json = ... |
|
||||
| type_alias.ts:17:1:17:15 | [DeclStmt] var json = ... | semmle.order | 101 |
|
||||
| type_alias.ts:17:1:17:15 | [DeclStmt] var json = ... | semmle.order | 102 |
|
||||
| type_alias.ts:17:5:17:8 | [VarDecl] json | semmle.label | [VarDecl] json |
|
||||
| type_alias.ts:17:5:17:14 | [VariableDeclarator] json: Json | semmle.label | [VariableDeclarator] json: Json |
|
||||
| type_alias.ts:17:11:17:14 | [LocalTypeAccess] Json | semmle.label | [LocalTypeAccess] Json |
|
||||
| type_alias.ts:19:1:21:57 | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; |
|
||||
| type_alias.ts:19:1:21:57 | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | semmle.order | 102 |
|
||||
| type_alias.ts:19:1:21:57 | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | semmle.order | 103 |
|
||||
| type_alias.ts:19:6:19:16 | [Identifier] VirtualNode | semmle.label | [Identifier] VirtualNode |
|
||||
| type_alias.ts:20:5:21:56 | [UnionTypeExpr] \| strin ... Node[]] | semmle.label | [UnionTypeExpr] \| strin ... Node[]] |
|
||||
| type_alias.ts:20:7:20:12 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
|
||||
@@ -1943,7 +2003,7 @@ nodes
|
||||
| type_alias.ts:21:43:21:53 | [LocalTypeAccess] VirtualNode | semmle.label | [LocalTypeAccess] VirtualNode |
|
||||
| type_alias.ts:21:43:21:55 | [ArrayTypeExpr] VirtualNode[] | semmle.label | [ArrayTypeExpr] VirtualNode[] |
|
||||
| type_alias.ts:23:1:27:6 | [DeclStmt] const myNode = ... | semmle.label | [DeclStmt] const myNode = ... |
|
||||
| type_alias.ts:23:1:27:6 | [DeclStmt] const myNode = ... | semmle.order | 103 |
|
||||
| type_alias.ts:23:1:27:6 | [DeclStmt] const myNode = ... | semmle.order | 104 |
|
||||
| type_alias.ts:23:7:23:12 | [VarDecl] myNode | semmle.label | [VarDecl] myNode |
|
||||
| type_alias.ts:23:7:27:5 | [VariableDeclarator] myNode: ... ] ] | semmle.label | [VariableDeclarator] myNode: ... ] ] |
|
||||
| type_alias.ts:23:15:23:25 | [LocalTypeAccess] VirtualNode | semmle.label | [LocalTypeAccess] VirtualNode |
|
||||
@@ -1968,12 +2028,12 @@ nodes
|
||||
| type_alias.ts:26:23:26:36 | [Literal] "second-child" | semmle.label | [Literal] "second-child" |
|
||||
| type_alias.ts:26:41:26:62 | [Literal] "I'm the second child" | semmle.label | [Literal] "I'm the second child" |
|
||||
| type_definition_objects.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.label | [ImportDeclaration] import ... dummy"; |
|
||||
| type_definition_objects.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 104 |
|
||||
| type_definition_objects.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 105 |
|
||||
| type_definition_objects.ts:1:8:1:17 | [ImportSpecifier] * as dummy | semmle.label | [ImportSpecifier] * as dummy |
|
||||
| type_definition_objects.ts:1:13:1:17 | [VarDecl] dummy | semmle.label | [VarDecl] dummy |
|
||||
| type_definition_objects.ts:1:24:1:32 | [Literal] "./dummy" | semmle.label | [Literal] "./dummy" |
|
||||
| type_definition_objects.ts:3:1:3:17 | [ExportDeclaration] export class C {} | semmle.label | [ExportDeclaration] export class C {} |
|
||||
| type_definition_objects.ts:3:1:3:17 | [ExportDeclaration] export class C {} | semmle.order | 105 |
|
||||
| type_definition_objects.ts:3:1:3:17 | [ExportDeclaration] export class C {} | semmle.order | 106 |
|
||||
| type_definition_objects.ts:3:8:3:17 | [ClassDefinition,TypeDefinition] class C {} | semmle.label | [ClassDefinition,TypeDefinition] class C {} |
|
||||
| type_definition_objects.ts:3:14:3:14 | [VarDecl] C | semmle.label | [VarDecl] C |
|
||||
| type_definition_objects.ts:3:16:3:15 | [BlockStmt] {} | semmle.label | [BlockStmt] {} |
|
||||
@@ -1981,36 +2041,36 @@ nodes
|
||||
| type_definition_objects.ts:3:16:3:15 | [FunctionExpr] () {} | semmle.label | [FunctionExpr] () {} |
|
||||
| type_definition_objects.ts:3:16:3:15 | [Label] constructor | semmle.label | [Label] constructor |
|
||||
| type_definition_objects.ts:4:1:4:17 | [DeclStmt] let classObj = ... | semmle.label | [DeclStmt] let classObj = ... |
|
||||
| type_definition_objects.ts:4:1:4:17 | [DeclStmt] let classObj = ... | semmle.order | 106 |
|
||||
| type_definition_objects.ts:4:1:4:17 | [DeclStmt] let classObj = ... | semmle.order | 107 |
|
||||
| type_definition_objects.ts:4:5:4:12 | [VarDecl] classObj | semmle.label | [VarDecl] classObj |
|
||||
| type_definition_objects.ts:4:5:4:16 | [VariableDeclarator] classObj = C | semmle.label | [VariableDeclarator] classObj = C |
|
||||
| type_definition_objects.ts:4:16:4:16 | [VarRef] C | semmle.label | [VarRef] C |
|
||||
| type_definition_objects.ts:6:1:6:16 | [ExportDeclaration] export enum E {} | semmle.label | [ExportDeclaration] export enum E {} |
|
||||
| type_definition_objects.ts:6:1:6:16 | [ExportDeclaration] export enum E {} | semmle.order | 107 |
|
||||
| type_definition_objects.ts:6:1:6:16 | [ExportDeclaration] export enum E {} | semmle.order | 108 |
|
||||
| type_definition_objects.ts:6:8:6:16 | [EnumDeclaration,TypeDefinition] enum E {} | semmle.label | [EnumDeclaration,TypeDefinition] enum E {} |
|
||||
| type_definition_objects.ts:6:13:6:13 | [VarDecl] E | semmle.label | [VarDecl] E |
|
||||
| type_definition_objects.ts:7:1:7:16 | [DeclStmt] let enumObj = ... | semmle.label | [DeclStmt] let enumObj = ... |
|
||||
| type_definition_objects.ts:7:1:7:16 | [DeclStmt] let enumObj = ... | semmle.order | 108 |
|
||||
| type_definition_objects.ts:7:1:7:16 | [DeclStmt] let enumObj = ... | semmle.order | 109 |
|
||||
| type_definition_objects.ts:7:5:7:11 | [VarDecl] enumObj | semmle.label | [VarDecl] enumObj |
|
||||
| type_definition_objects.ts:7:5:7:15 | [VariableDeclarator] enumObj = E | semmle.label | [VariableDeclarator] enumObj = E |
|
||||
| type_definition_objects.ts:7:15:7:15 | [VarRef] E | semmle.label | [VarRef] E |
|
||||
| type_definition_objects.ts:9:1:9:22 | [ExportDeclaration] export ... e N {;} | semmle.label | [ExportDeclaration] export ... e N {;} |
|
||||
| type_definition_objects.ts:9:1:9:22 | [ExportDeclaration] export ... e N {;} | semmle.order | 109 |
|
||||
| type_definition_objects.ts:9:1:9:22 | [ExportDeclaration] export ... e N {;} | semmle.order | 110 |
|
||||
| type_definition_objects.ts:9:8:9:22 | [NamespaceDeclaration] namespace N {;} | semmle.label | [NamespaceDeclaration] namespace N {;} |
|
||||
| type_definition_objects.ts:9:18:9:18 | [VarDecl] N | semmle.label | [VarDecl] N |
|
||||
| type_definition_objects.ts:9:21:9:21 | [EmptyStmt] ; | semmle.label | [EmptyStmt] ; |
|
||||
| type_definition_objects.ts:10:1:10:21 | [DeclStmt] let namespaceObj = ... | semmle.label | [DeclStmt] let namespaceObj = ... |
|
||||
| type_definition_objects.ts:10:1:10:21 | [DeclStmt] let namespaceObj = ... | semmle.order | 110 |
|
||||
| type_definition_objects.ts:10:1:10:21 | [DeclStmt] let namespaceObj = ... | semmle.order | 111 |
|
||||
| type_definition_objects.ts:10:5:10:16 | [VarDecl] namespaceObj | semmle.label | [VarDecl] namespaceObj |
|
||||
| type_definition_objects.ts:10:5:10:20 | [VariableDeclarator] namespaceObj = N | semmle.label | [VariableDeclarator] namespaceObj = N |
|
||||
| type_definition_objects.ts:10:20:10:20 | [VarRef] N | semmle.label | [VarRef] N |
|
||||
| type_definitions.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.label | [ImportDeclaration] import ... dummy"; |
|
||||
| type_definitions.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 111 |
|
||||
| type_definitions.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 112 |
|
||||
| type_definitions.ts:1:8:1:17 | [ImportSpecifier] * as dummy | semmle.label | [ImportSpecifier] * as dummy |
|
||||
| type_definitions.ts:1:13:1:17 | [VarDecl] dummy | semmle.label | [VarDecl] dummy |
|
||||
| type_definitions.ts:1:24:1:32 | [Literal] "./dummy" | semmle.label | [Literal] "./dummy" |
|
||||
| type_definitions.ts:3:1:5:1 | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | semmle.label | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } |
|
||||
| type_definitions.ts:3:1:5:1 | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | semmle.order | 112 |
|
||||
| type_definitions.ts:3:1:5:1 | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | semmle.order | 113 |
|
||||
| type_definitions.ts:3:11:3:11 | [Identifier] I | semmle.label | [Identifier] I |
|
||||
| type_definitions.ts:3:13:3:13 | [Identifier] S | semmle.label | [Identifier] S |
|
||||
| type_definitions.ts:3:13:3:13 | [TypeParameter] S | semmle.label | [TypeParameter] S |
|
||||
@@ -2018,14 +2078,14 @@ nodes
|
||||
| type_definitions.ts:4:3:4:7 | [FieldDeclaration] x: S; | semmle.label | [FieldDeclaration] x: S; |
|
||||
| type_definitions.ts:4:6:4:6 | [LocalTypeAccess] S | semmle.label | [LocalTypeAccess] S |
|
||||
| type_definitions.ts:6:1:6:16 | [DeclStmt] let i = ... | semmle.label | [DeclStmt] let i = ... |
|
||||
| type_definitions.ts:6:1:6:16 | [DeclStmt] let i = ... | semmle.order | 113 |
|
||||
| type_definitions.ts:6:1:6:16 | [DeclStmt] let i = ... | semmle.order | 114 |
|
||||
| type_definitions.ts:6:5:6:5 | [VarDecl] i | semmle.label | [VarDecl] i |
|
||||
| type_definitions.ts:6:5:6:16 | [VariableDeclarator] i: I<number> | semmle.label | [VariableDeclarator] i: I<number> |
|
||||
| type_definitions.ts:6:8:6:8 | [LocalTypeAccess] I | semmle.label | [LocalTypeAccess] I |
|
||||
| type_definitions.ts:6:8:6:16 | [GenericTypeExpr] I<number> | semmle.label | [GenericTypeExpr] I<number> |
|
||||
| type_definitions.ts:6:10:6:15 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number |
|
||||
| type_definitions.ts:8:1:10:1 | [ClassDefinition,TypeDefinition] class C ... x: T } | semmle.label | [ClassDefinition,TypeDefinition] class C ... x: T } |
|
||||
| type_definitions.ts:8:1:10:1 | [ClassDefinition,TypeDefinition] class C ... x: T } | semmle.order | 114 |
|
||||
| type_definitions.ts:8:1:10:1 | [ClassDefinition,TypeDefinition] class C ... x: T } | semmle.order | 115 |
|
||||
| type_definitions.ts:8:7:8:7 | [VarDecl] C | semmle.label | [VarDecl] C |
|
||||
| type_definitions.ts:8:8:8:7 | [BlockStmt] {} | semmle.label | [BlockStmt] {} |
|
||||
| type_definitions.ts:8:8:8:7 | [ClassInitializedMember,ConstructorDefinition] constructor() {} | semmle.label | [ClassInitializedMember,ConstructorDefinition] constructor() {} |
|
||||
@@ -2037,14 +2097,14 @@ nodes
|
||||
| type_definitions.ts:9:3:9:6 | [FieldDeclaration] x: T | semmle.label | [FieldDeclaration] x: T |
|
||||
| type_definitions.ts:9:6:9:6 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T |
|
||||
| type_definitions.ts:11:1:11:17 | [DeclStmt] let c = ... | semmle.label | [DeclStmt] let c = ... |
|
||||
| type_definitions.ts:11:1:11:17 | [DeclStmt] let c = ... | semmle.order | 115 |
|
||||
| type_definitions.ts:11:1:11:17 | [DeclStmt] let c = ... | semmle.order | 116 |
|
||||
| type_definitions.ts:11:5:11:5 | [VarDecl] c | semmle.label | [VarDecl] c |
|
||||
| type_definitions.ts:11:5:11:16 | [VariableDeclarator] c: C<number> | semmle.label | [VariableDeclarator] c: C<number> |
|
||||
| type_definitions.ts:11:8:11:8 | [LocalTypeAccess] C | semmle.label | [LocalTypeAccess] C |
|
||||
| type_definitions.ts:11:8:11:16 | [GenericTypeExpr] C<number> | semmle.label | [GenericTypeExpr] C<number> |
|
||||
| type_definitions.ts:11:10:11:15 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number |
|
||||
| type_definitions.ts:13:1:15:1 | [EnumDeclaration,TypeDefinition] enum Co ... blue } | semmle.label | [EnumDeclaration,TypeDefinition] enum Co ... blue } |
|
||||
| type_definitions.ts:13:1:15:1 | [EnumDeclaration,TypeDefinition] enum Co ... blue } | semmle.order | 116 |
|
||||
| type_definitions.ts:13:1:15:1 | [EnumDeclaration,TypeDefinition] enum Co ... blue } | semmle.order | 117 |
|
||||
| type_definitions.ts:13:6:13:10 | [VarDecl] Color | semmle.label | [VarDecl] Color |
|
||||
| type_definitions.ts:14:3:14:5 | [EnumMember,TypeDefinition] red | semmle.label | [EnumMember,TypeDefinition] red |
|
||||
| type_definitions.ts:14:3:14:5 | [VarDecl] red | semmle.label | [VarDecl] red |
|
||||
@@ -2053,29 +2113,29 @@ nodes
|
||||
| type_definitions.ts:14:15:14:18 | [EnumMember,TypeDefinition] blue | semmle.label | [EnumMember,TypeDefinition] blue |
|
||||
| type_definitions.ts:14:15:14:18 | [VarDecl] blue | semmle.label | [VarDecl] blue |
|
||||
| type_definitions.ts:16:1:16:17 | [DeclStmt] let color = ... | semmle.label | [DeclStmt] let color = ... |
|
||||
| type_definitions.ts:16:1:16:17 | [DeclStmt] let color = ... | semmle.order | 117 |
|
||||
| type_definitions.ts:16:1:16:17 | [DeclStmt] let color = ... | semmle.order | 118 |
|
||||
| type_definitions.ts:16:5:16:9 | [VarDecl] color | semmle.label | [VarDecl] color |
|
||||
| type_definitions.ts:16:5:16:16 | [VariableDeclarator] color: Color | semmle.label | [VariableDeclarator] color: Color |
|
||||
| type_definitions.ts:16:12:16:16 | [LocalTypeAccess] Color | semmle.label | [LocalTypeAccess] Color |
|
||||
| type_definitions.ts:18:1:18:33 | [EnumDeclaration,TypeDefinition] enum En ... ember } | semmle.label | [EnumDeclaration,TypeDefinition] enum En ... ember } |
|
||||
| type_definitions.ts:18:1:18:33 | [EnumDeclaration,TypeDefinition] enum En ... ember } | semmle.order | 118 |
|
||||
| type_definitions.ts:18:1:18:33 | [EnumDeclaration,TypeDefinition] enum En ... ember } | semmle.order | 119 |
|
||||
| type_definitions.ts:18:6:18:22 | [VarDecl] EnumWithOneMember | semmle.label | [VarDecl] EnumWithOneMember |
|
||||
| type_definitions.ts:18:26:18:31 | [EnumMember,TypeDefinition] member | semmle.label | [EnumMember,TypeDefinition] member |
|
||||
| type_definitions.ts:18:26:18:31 | [VarDecl] member | semmle.label | [VarDecl] member |
|
||||
| type_definitions.ts:19:1:19:25 | [DeclStmt] let e = ... | semmle.label | [DeclStmt] let e = ... |
|
||||
| type_definitions.ts:19:1:19:25 | [DeclStmt] let e = ... | semmle.order | 119 |
|
||||
| type_definitions.ts:19:1:19:25 | [DeclStmt] let e = ... | semmle.order | 120 |
|
||||
| type_definitions.ts:19:5:19:5 | [VarDecl] e | semmle.label | [VarDecl] e |
|
||||
| type_definitions.ts:19:5:19:24 | [VariableDeclarator] e: EnumWithOneMember | semmle.label | [VariableDeclarator] e: EnumWithOneMember |
|
||||
| type_definitions.ts:19:8:19:24 | [LocalTypeAccess] EnumWithOneMember | semmle.label | [LocalTypeAccess] EnumWithOneMember |
|
||||
| type_definitions.ts:21:1:21:20 | [TypeAliasDeclaration,TypeDefinition] type Alias<T> = T[]; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Alias<T> = T[]; |
|
||||
| type_definitions.ts:21:1:21:20 | [TypeAliasDeclaration,TypeDefinition] type Alias<T> = T[]; | semmle.order | 120 |
|
||||
| type_definitions.ts:21:1:21:20 | [TypeAliasDeclaration,TypeDefinition] type Alias<T> = T[]; | semmle.order | 121 |
|
||||
| type_definitions.ts:21:6:21:10 | [Identifier] Alias | semmle.label | [Identifier] Alias |
|
||||
| type_definitions.ts:21:12:21:12 | [Identifier] T | semmle.label | [Identifier] T |
|
||||
| type_definitions.ts:21:12:21:12 | [TypeParameter] T | semmle.label | [TypeParameter] T |
|
||||
| type_definitions.ts:21:17:21:17 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T |
|
||||
| type_definitions.ts:21:17:21:19 | [ArrayTypeExpr] T[] | semmle.label | [ArrayTypeExpr] T[] |
|
||||
| type_definitions.ts:22:1:22:39 | [DeclStmt] let aliasForNumberArray = ... | semmle.label | [DeclStmt] let aliasForNumberArray = ... |
|
||||
| type_definitions.ts:22:1:22:39 | [DeclStmt] let aliasForNumberArray = ... | semmle.order | 121 |
|
||||
| type_definitions.ts:22:1:22:39 | [DeclStmt] let aliasForNumberArray = ... | semmle.order | 122 |
|
||||
| type_definitions.ts:22:5:22:23 | [VarDecl] aliasForNumberArray | semmle.label | [VarDecl] aliasForNumberArray |
|
||||
| type_definitions.ts:22:5:22:38 | [VariableDeclarator] aliasFo ... number> | semmle.label | [VariableDeclarator] aliasFo ... number> |
|
||||
| type_definitions.ts:22:26:22:30 | [LocalTypeAccess] Alias | semmle.label | [LocalTypeAccess] Alias |
|
||||
@@ -2284,6 +2344,8 @@ edges
|
||||
| file://:0:0:0:0 | (Arguments) | tst.ts:493:32:493:49 | [ArrayExpr] [0, 1, 2, 3, 4, 5] | semmle.order | 0 |
|
||||
| file://:0:0:0:0 | (Arguments) | tst.ts:493:52:495:3 | [ArrowFunctionExpr] (num, i ... d"; } | semmle.label | 1 |
|
||||
| file://:0:0:0:0 | (Arguments) | tst.ts:493:52:495:3 | [ArrowFunctionExpr] (num, i ... d"; } | semmle.order | 1 |
|
||||
| file://:0:0:0:0 | (Arguments) | tst.ts:500:13:500:38 | [ArrowFunctionExpr] s => ty ... string" | semmle.label | 0 |
|
||||
| file://:0:0:0:0 | (Arguments) | tst.ts:500:13:500:38 | [ArrowFunctionExpr] s => ty ... string" | semmle.order | 0 |
|
||||
| file://:0:0:0:0 | (Parameters) | tst.ts:14:17:14:17 | [SimpleParameter] x | semmle.label | 0 |
|
||||
| file://:0:0:0:0 | (Parameters) | tst.ts:14:17:14:17 | [SimpleParameter] x | semmle.order | 0 |
|
||||
| file://:0:0:0:0 | (Parameters) | tst.ts:14:28:14:28 | [SimpleParameter] y | semmle.label | 1 |
|
||||
@@ -2390,6 +2452,12 @@ edges
|
||||
| file://:0:0:0:0 | (Parameters) | tst.ts:493:53:493:55 | [SimpleParameter] num | semmle.order | 0 |
|
||||
| file://:0:0:0:0 | (Parameters) | tst.ts:493:58:493:62 | [SimpleParameter] index | semmle.label | 1 |
|
||||
| file://:0:0:0:0 | (Parameters) | tst.ts:493:58:493:62 | [SimpleParameter] index | semmle.order | 1 |
|
||||
| file://:0:0:0:0 | (Parameters) | tst.ts:500:13:500:13 | [SimpleParameter] s | semmle.label | 0 |
|
||||
| file://:0:0:0:0 | (Parameters) | tst.ts:500:13:500:13 | [SimpleParameter] s | semmle.order | 0 |
|
||||
| file://:0:0:0:0 | (Parameters) | tst.ts:506:15:506:17 | [SimpleParameter] obj | semmle.label | 0 |
|
||||
| file://:0:0:0:0 | (Parameters) | tst.ts:506:15:506:17 | [SimpleParameter] obj | semmle.order | 0 |
|
||||
| file://:0:0:0:0 | (Parameters) | tst.ts:506:45:506:47 | [SimpleParameter] key | semmle.label | 1 |
|
||||
| file://:0:0:0:0 | (Parameters) | tst.ts:506:45:506:47 | [SimpleParameter] key | semmle.order | 1 |
|
||||
| file://:0:0:0:0 | (Parameters) | type_alias.ts:14:10:14:17 | [SimpleParameter] property | semmle.label | 0 |
|
||||
| file://:0:0:0:0 | (Parameters) | type_alias.ts:14:10:14:17 | [SimpleParameter] property | semmle.order | 0 |
|
||||
| file://:0:0:0:0 | (Parameters) | type_alias.ts:21:19:21:21 | [SimpleParameter] key | semmle.label | 0 |
|
||||
@@ -5358,6 +5426,114 @@ edges
|
||||
| tst.ts:494:12:494:40 | [ConditionalExpr] num % 2 ... : "odd" | tst.ts:494:28:494:33 | [Literal] "even" | semmle.order | 2 |
|
||||
| tst.ts:494:12:494:40 | [ConditionalExpr] num % 2 ... : "odd" | tst.ts:494:36:494:40 | [Literal] "odd" | semmle.label | 3 |
|
||||
| tst.ts:494:12:494:40 | [ConditionalExpr] num % 2 ... : "odd" | tst.ts:494:36:494:40 | [Literal] "odd" | semmle.order | 3 |
|
||||
| tst.ts:498:1:511:1 | [NamespaceDeclaration] module ... } } } | tst.ts:498:8:498:11 | [VarDecl] TS55 | semmle.label | 1 |
|
||||
| tst.ts:498:1:511:1 | [NamespaceDeclaration] module ... } } } | tst.ts:498:8:498:11 | [VarDecl] TS55 | semmle.order | 1 |
|
||||
| tst.ts:498:1:511:1 | [NamespaceDeclaration] module ... } } } | tst.ts:499:3:500:40 | [DeclStmt] const strings = ... | semmle.label | 2 |
|
||||
| tst.ts:498:1:511:1 | [NamespaceDeclaration] module ... } } } | tst.ts:499:3:500:40 | [DeclStmt] const strings = ... | semmle.order | 2 |
|
||||
| tst.ts:498:1:511:1 | [NamespaceDeclaration] module ... } } } | tst.ts:502:3:504:3 | [ForOfStmt] for (co ... 5.4 } | semmle.label | 3 |
|
||||
| tst.ts:498:1:511:1 | [NamespaceDeclaration] module ... } } } | tst.ts:502:3:504:3 | [ForOfStmt] for (co ... 5.4 } | semmle.order | 3 |
|
||||
| tst.ts:498:1:511:1 | [NamespaceDeclaration] module ... } } } | tst.ts:506:3:510:3 | [FunctionDeclStmt] functio ... } } | semmle.label | 4 |
|
||||
| tst.ts:498:1:511:1 | [NamespaceDeclaration] module ... } } } | tst.ts:506:3:510:3 | [FunctionDeclStmt] functio ... } } | semmle.order | 4 |
|
||||
| tst.ts:499:3:500:40 | [DeclStmt] const strings = ... | tst.ts:499:9:500:39 | [VariableDeclarator] strings ... tring") | semmle.label | 1 |
|
||||
| tst.ts:499:3:500:40 | [DeclStmt] const strings = ... | tst.ts:499:9:500:39 | [VariableDeclarator] strings ... tring") | semmle.order | 1 |
|
||||
| tst.ts:499:9:500:39 | [VariableDeclarator] strings ... tring") | tst.ts:499:9:499:15 | [VarDecl] strings | semmle.label | 1 |
|
||||
| tst.ts:499:9:500:39 | [VariableDeclarator] strings ... tring") | tst.ts:499:9:499:15 | [VarDecl] strings | semmle.order | 1 |
|
||||
| tst.ts:499:9:500:39 | [VariableDeclarator] strings ... tring") | tst.ts:499:19:500:39 | [MethodCallExpr] (["foo" ... tring") | semmle.label | 2 |
|
||||
| tst.ts:499:9:500:39 | [VariableDeclarator] strings ... tring") | tst.ts:499:19:500:39 | [MethodCallExpr] (["foo" ... tring") | semmle.order | 2 |
|
||||
| tst.ts:499:19:499:32 | [ParExpr] (["foo", 123]) | tst.ts:499:20:499:31 | [ArrayExpr] ["foo", 123] | semmle.label | 1 |
|
||||
| tst.ts:499:19:499:32 | [ParExpr] (["foo", 123]) | tst.ts:499:20:499:31 | [ArrayExpr] ["foo", 123] | semmle.order | 1 |
|
||||
| tst.ts:499:19:500:11 | [DotExpr] (["foo" ... .filter | tst.ts:499:19:499:32 | [ParExpr] (["foo", 123]) | semmle.label | 1 |
|
||||
| tst.ts:499:19:500:11 | [DotExpr] (["foo" ... .filter | tst.ts:499:19:499:32 | [ParExpr] (["foo", 123]) | semmle.order | 1 |
|
||||
| tst.ts:499:19:500:11 | [DotExpr] (["foo" ... .filter | tst.ts:500:6:500:11 | [Label] filter | semmle.label | 2 |
|
||||
| tst.ts:499:19:500:11 | [DotExpr] (["foo" ... .filter | tst.ts:500:6:500:11 | [Label] filter | semmle.order | 2 |
|
||||
| tst.ts:499:19:500:39 | [MethodCallExpr] (["foo" ... tring") | file://:0:0:0:0 | (Arguments) | semmle.label | 1 |
|
||||
| tst.ts:499:19:500:39 | [MethodCallExpr] (["foo" ... tring") | file://:0:0:0:0 | (Arguments) | semmle.order | 1 |
|
||||
| tst.ts:499:19:500:39 | [MethodCallExpr] (["foo" ... tring") | tst.ts:499:19:500:11 | [DotExpr] (["foo" ... .filter | semmle.label | 0 |
|
||||
| tst.ts:499:19:500:39 | [MethodCallExpr] (["foo" ... tring") | tst.ts:499:19:500:11 | [DotExpr] (["foo" ... .filter | semmle.order | 0 |
|
||||
| tst.ts:499:20:499:31 | [ArrayExpr] ["foo", 123] | tst.ts:499:21:499:25 | [Literal] "foo" | semmle.label | 1 |
|
||||
| tst.ts:499:20:499:31 | [ArrayExpr] ["foo", 123] | tst.ts:499:21:499:25 | [Literal] "foo" | semmle.order | 1 |
|
||||
| tst.ts:499:20:499:31 | [ArrayExpr] ["foo", 123] | tst.ts:499:28:499:30 | [Literal] 123 | semmle.label | 2 |
|
||||
| tst.ts:499:20:499:31 | [ArrayExpr] ["foo", 123] | tst.ts:499:28:499:30 | [Literal] 123 | semmle.order | 2 |
|
||||
| tst.ts:500:13:500:38 | [ArrowFunctionExpr] s => ty ... string" | file://:0:0:0:0 | (Parameters) | semmle.label | 1 |
|
||||
| tst.ts:500:13:500:38 | [ArrowFunctionExpr] s => ty ... string" | file://:0:0:0:0 | (Parameters) | semmle.order | 1 |
|
||||
| tst.ts:500:13:500:38 | [ArrowFunctionExpr] s => ty ... string" | tst.ts:500:18:500:38 | [BinaryExpr] typeof ... string" | semmle.label | 5 |
|
||||
| tst.ts:500:13:500:38 | [ArrowFunctionExpr] s => ty ... string" | tst.ts:500:18:500:38 | [BinaryExpr] typeof ... string" | semmle.order | 5 |
|
||||
| tst.ts:500:18:500:25 | [UnaryExpr] typeof s | tst.ts:500:25:500:25 | [VarRef] s | semmle.label | 1 |
|
||||
| tst.ts:500:18:500:25 | [UnaryExpr] typeof s | tst.ts:500:25:500:25 | [VarRef] s | semmle.order | 1 |
|
||||
| tst.ts:500:18:500:38 | [BinaryExpr] typeof ... string" | tst.ts:500:18:500:25 | [UnaryExpr] typeof s | semmle.label | 1 |
|
||||
| tst.ts:500:18:500:38 | [BinaryExpr] typeof ... string" | tst.ts:500:18:500:25 | [UnaryExpr] typeof s | semmle.order | 1 |
|
||||
| tst.ts:500:18:500:38 | [BinaryExpr] typeof ... string" | tst.ts:500:31:500:38 | [Literal] "string" | semmle.label | 2 |
|
||||
| tst.ts:500:18:500:38 | [BinaryExpr] typeof ... string" | tst.ts:500:31:500:38 | [Literal] "string" | semmle.order | 2 |
|
||||
| tst.ts:502:3:504:3 | [ForOfStmt] for (co ... 5.4 } | tst.ts:502:8:502:16 | [DeclStmt] const str = ... | semmle.label | 1 |
|
||||
| tst.ts:502:3:504:3 | [ForOfStmt] for (co ... 5.4 } | tst.ts:502:8:502:16 | [DeclStmt] const str = ... | semmle.order | 1 |
|
||||
| tst.ts:502:3:504:3 | [ForOfStmt] for (co ... 5.4 } | tst.ts:502:21:502:27 | [VarRef] strings | semmle.label | 2 |
|
||||
| tst.ts:502:3:504:3 | [ForOfStmt] for (co ... 5.4 } | tst.ts:502:21:502:27 | [VarRef] strings | semmle.order | 2 |
|
||||
| tst.ts:502:3:504:3 | [ForOfStmt] for (co ... 5.4 } | tst.ts:502:30:504:3 | [BlockStmt] { s ... 5.4 } | semmle.label | 3 |
|
||||
| tst.ts:502:3:504:3 | [ForOfStmt] for (co ... 5.4 } | tst.ts:502:30:504:3 | [BlockStmt] { s ... 5.4 } | semmle.order | 3 |
|
||||
| tst.ts:502:8:502:16 | [DeclStmt] const str = ... | tst.ts:502:14:502:16 | [VariableDeclarator] str | semmle.label | 1 |
|
||||
| tst.ts:502:8:502:16 | [DeclStmt] const str = ... | tst.ts:502:14:502:16 | [VariableDeclarator] str | semmle.order | 1 |
|
||||
| tst.ts:502:14:502:16 | [VariableDeclarator] str | tst.ts:502:14:502:16 | [VarDecl] str | semmle.label | 1 |
|
||||
| tst.ts:502:14:502:16 | [VariableDeclarator] str | tst.ts:502:14:502:16 | [VarDecl] str | semmle.order | 1 |
|
||||
| tst.ts:502:30:504:3 | [BlockStmt] { s ... 5.4 } | tst.ts:503:5:503:22 | [ExprStmt] str.toLowerCase(); | semmle.label | 1 |
|
||||
| tst.ts:502:30:504:3 | [BlockStmt] { s ... 5.4 } | tst.ts:503:5:503:22 | [ExprStmt] str.toLowerCase(); | semmle.order | 1 |
|
||||
| tst.ts:503:5:503:19 | [DotExpr] str.toLowerCase | tst.ts:503:5:503:7 | [VarRef] str | semmle.label | 1 |
|
||||
| tst.ts:503:5:503:19 | [DotExpr] str.toLowerCase | tst.ts:503:5:503:7 | [VarRef] str | semmle.order | 1 |
|
||||
| tst.ts:503:5:503:19 | [DotExpr] str.toLowerCase | tst.ts:503:9:503:19 | [Label] toLowerCase | semmle.label | 2 |
|
||||
| tst.ts:503:5:503:19 | [DotExpr] str.toLowerCase | tst.ts:503:9:503:19 | [Label] toLowerCase | semmle.order | 2 |
|
||||
| tst.ts:503:5:503:21 | [MethodCallExpr] str.toLowerCase() | tst.ts:503:5:503:19 | [DotExpr] str.toLowerCase | semmle.label | 0 |
|
||||
| tst.ts:503:5:503:21 | [MethodCallExpr] str.toLowerCase() | tst.ts:503:5:503:19 | [DotExpr] str.toLowerCase | semmle.order | 0 |
|
||||
| tst.ts:503:5:503:22 | [ExprStmt] str.toLowerCase(); | tst.ts:503:5:503:21 | [MethodCallExpr] str.toLowerCase() | semmle.label | 1 |
|
||||
| tst.ts:503:5:503:22 | [ExprStmt] str.toLowerCase(); | tst.ts:503:5:503:21 | [MethodCallExpr] str.toLowerCase() | semmle.order | 1 |
|
||||
| tst.ts:506:3:510:3 | [FunctionDeclStmt] functio ... } } | file://:0:0:0:0 | (Parameters) | semmle.label | 1 |
|
||||
| tst.ts:506:3:510:3 | [FunctionDeclStmt] functio ... } } | file://:0:0:0:0 | (Parameters) | semmle.order | 1 |
|
||||
| tst.ts:506:3:510:3 | [FunctionDeclStmt] functio ... } } | tst.ts:506:12:506:13 | [VarDecl] f1 | semmle.label | 0 |
|
||||
| tst.ts:506:3:510:3 | [FunctionDeclStmt] functio ... } } | tst.ts:506:12:506:13 | [VarDecl] f1 | semmle.order | 0 |
|
||||
| tst.ts:506:3:510:3 | [FunctionDeclStmt] functio ... } } | tst.ts:506:58:510:3 | [BlockStmt] { i ... } } | semmle.label | 5 |
|
||||
| tst.ts:506:3:510:3 | [FunctionDeclStmt] functio ... } } | tst.ts:506:58:510:3 | [BlockStmt] { i ... } } | semmle.order | 5 |
|
||||
| tst.ts:506:15:506:17 | [SimpleParameter] obj | tst.ts:506:20:506:42 | [GenericTypeExpr] Record< ... nknown> | semmle.label | -2 |
|
||||
| tst.ts:506:15:506:17 | [SimpleParameter] obj | tst.ts:506:20:506:42 | [GenericTypeExpr] Record< ... nknown> | semmle.order | -2 |
|
||||
| tst.ts:506:20:506:42 | [GenericTypeExpr] Record< ... nknown> | tst.ts:506:20:506:25 | [LocalTypeAccess] Record | semmle.label | 1 |
|
||||
| tst.ts:506:20:506:42 | [GenericTypeExpr] Record< ... nknown> | tst.ts:506:20:506:25 | [LocalTypeAccess] Record | semmle.order | 1 |
|
||||
| tst.ts:506:20:506:42 | [GenericTypeExpr] Record< ... nknown> | tst.ts:506:27:506:32 | [KeywordTypeExpr] string | semmle.label | 2 |
|
||||
| tst.ts:506:20:506:42 | [GenericTypeExpr] Record< ... nknown> | tst.ts:506:27:506:32 | [KeywordTypeExpr] string | semmle.order | 2 |
|
||||
| tst.ts:506:20:506:42 | [GenericTypeExpr] Record< ... nknown> | tst.ts:506:35:506:41 | [KeywordTypeExpr] unknown | semmle.label | 3 |
|
||||
| tst.ts:506:20:506:42 | [GenericTypeExpr] Record< ... nknown> | tst.ts:506:35:506:41 | [KeywordTypeExpr] unknown | semmle.order | 3 |
|
||||
| tst.ts:506:45:506:47 | [SimpleParameter] key | tst.ts:506:50:506:55 | [KeywordTypeExpr] string | semmle.label | -2 |
|
||||
| tst.ts:506:45:506:47 | [SimpleParameter] key | tst.ts:506:50:506:55 | [KeywordTypeExpr] string | semmle.order | -2 |
|
||||
| tst.ts:506:58:510:3 | [BlockStmt] { i ... } } | tst.ts:507:5:509:5 | [IfStmt] if (typ ... r } | semmle.label | 1 |
|
||||
| tst.ts:506:58:510:3 | [BlockStmt] { i ... } } | tst.ts:507:5:509:5 | [IfStmt] if (typ ... r } | semmle.order | 1 |
|
||||
| tst.ts:507:5:509:5 | [IfStmt] if (typ ... r } | tst.ts:507:9:507:36 | [BinaryExpr] typeof ... string" | semmle.label | 1 |
|
||||
| tst.ts:507:5:509:5 | [IfStmt] if (typ ... r } | tst.ts:507:9:507:36 | [BinaryExpr] typeof ... string" | semmle.order | 1 |
|
||||
| tst.ts:507:5:509:5 | [IfStmt] if (typ ... r } | tst.ts:507:39:509:5 | [BlockStmt] { ... r } | semmle.label | 2 |
|
||||
| tst.ts:507:5:509:5 | [IfStmt] if (typ ... r } | tst.ts:507:39:509:5 | [BlockStmt] { ... r } | semmle.order | 2 |
|
||||
| tst.ts:507:9:507:23 | [UnaryExpr] typeof obj[key] | tst.ts:507:16:507:23 | [IndexExpr] obj[key] | semmle.label | 1 |
|
||||
| tst.ts:507:9:507:23 | [UnaryExpr] typeof obj[key] | tst.ts:507:16:507:23 | [IndexExpr] obj[key] | semmle.order | 1 |
|
||||
| tst.ts:507:9:507:36 | [BinaryExpr] typeof ... string" | tst.ts:507:9:507:23 | [UnaryExpr] typeof obj[key] | semmle.label | 1 |
|
||||
| tst.ts:507:9:507:36 | [BinaryExpr] typeof ... string" | tst.ts:507:9:507:23 | [UnaryExpr] typeof obj[key] | semmle.order | 1 |
|
||||
| tst.ts:507:9:507:36 | [BinaryExpr] typeof ... string" | tst.ts:507:29:507:36 | [Literal] "string" | semmle.label | 2 |
|
||||
| tst.ts:507:9:507:36 | [BinaryExpr] typeof ... string" | tst.ts:507:29:507:36 | [Literal] "string" | semmle.order | 2 |
|
||||
| tst.ts:507:16:507:23 | [IndexExpr] obj[key] | tst.ts:507:16:507:18 | [VarRef] obj | semmle.label | 1 |
|
||||
| tst.ts:507:16:507:23 | [IndexExpr] obj[key] | tst.ts:507:16:507:18 | [VarRef] obj | semmle.order | 1 |
|
||||
| tst.ts:507:16:507:23 | [IndexExpr] obj[key] | tst.ts:507:20:507:22 | [VarRef] key | semmle.label | 2 |
|
||||
| tst.ts:507:16:507:23 | [IndexExpr] obj[key] | tst.ts:507:20:507:22 | [VarRef] key | semmle.order | 2 |
|
||||
| tst.ts:507:39:509:5 | [BlockStmt] { ... r } | tst.ts:508:7:508:39 | [DeclStmt] var str = ... | semmle.label | 1 |
|
||||
| tst.ts:507:39:509:5 | [BlockStmt] { ... r } | tst.ts:508:7:508:39 | [DeclStmt] var str = ... | semmle.order | 1 |
|
||||
| tst.ts:508:7:508:39 | [DeclStmt] var str = ... | tst.ts:508:11:508:38 | [VariableDeclarator] str = o ... rCase() | semmle.label | 1 |
|
||||
| tst.ts:508:7:508:39 | [DeclStmt] var str = ... | tst.ts:508:11:508:38 | [VariableDeclarator] str = o ... rCase() | semmle.order | 1 |
|
||||
| tst.ts:508:11:508:38 | [VariableDeclarator] str = o ... rCase() | tst.ts:508:11:508:13 | [VarDecl] str | semmle.label | 1 |
|
||||
| tst.ts:508:11:508:38 | [VariableDeclarator] str = o ... rCase() | tst.ts:508:11:508:13 | [VarDecl] str | semmle.order | 1 |
|
||||
| tst.ts:508:11:508:38 | [VariableDeclarator] str = o ... rCase() | tst.ts:508:17:508:38 | [MethodCallExpr] obj[key ... rCase() | semmle.label | 2 |
|
||||
| tst.ts:508:11:508:38 | [VariableDeclarator] str = o ... rCase() | tst.ts:508:17:508:38 | [MethodCallExpr] obj[key ... rCase() | semmle.order | 2 |
|
||||
| tst.ts:508:17:508:24 | [IndexExpr] obj[key] | tst.ts:508:17:508:19 | [VarRef] obj | semmle.label | 1 |
|
||||
| tst.ts:508:17:508:24 | [IndexExpr] obj[key] | tst.ts:508:17:508:19 | [VarRef] obj | semmle.order | 1 |
|
||||
| tst.ts:508:17:508:24 | [IndexExpr] obj[key] | tst.ts:508:21:508:23 | [VarRef] key | semmle.label | 2 |
|
||||
| tst.ts:508:17:508:24 | [IndexExpr] obj[key] | tst.ts:508:21:508:23 | [VarRef] key | semmle.order | 2 |
|
||||
| tst.ts:508:17:508:36 | [DotExpr] obj[key].toUpperCase | tst.ts:508:17:508:24 | [IndexExpr] obj[key] | semmle.label | 1 |
|
||||
| tst.ts:508:17:508:36 | [DotExpr] obj[key].toUpperCase | tst.ts:508:17:508:24 | [IndexExpr] obj[key] | semmle.order | 1 |
|
||||
| tst.ts:508:17:508:36 | [DotExpr] obj[key].toUpperCase | tst.ts:508:26:508:36 | [Label] toUpperCase | semmle.label | 2 |
|
||||
| tst.ts:508:17:508:36 | [DotExpr] obj[key].toUpperCase | tst.ts:508:26:508:36 | [Label] toUpperCase | semmle.order | 2 |
|
||||
| tst.ts:508:17:508:38 | [MethodCallExpr] obj[key ... rCase() | tst.ts:508:17:508:36 | [DotExpr] obj[key].toUpperCase | semmle.label | 0 |
|
||||
| tst.ts:508:17:508:38 | [MethodCallExpr] obj[key ... rCase() | tst.ts:508:17:508:36 | [DotExpr] obj[key].toUpperCase | semmle.order | 0 |
|
||||
| tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | tstModuleCJS.cts:1:8:3:1 | [FunctionDeclStmt] functio ... 'b'; } | semmle.label | 1 |
|
||||
| tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | tstModuleCJS.cts:1:8:3:1 | [FunctionDeclStmt] functio ... 'b'; } | semmle.order | 1 |
|
||||
| tstModuleCJS.cts:1:8:3:1 | [FunctionDeclStmt] functio ... 'b'; } | tstModuleCJS.cts:1:17:1:28 | [VarDecl] tstModuleCJS | semmle.label | 0 |
|
||||
|
||||
@@ -692,6 +692,43 @@ getExprType
|
||||
| tst.ts:494:24:494:24 | 0 | 0 |
|
||||
| tst.ts:494:28:494:33 | "even" | "even" |
|
||||
| tst.ts:494:36:494:40 | "odd" | "odd" |
|
||||
| tst.ts:498:8:498:11 | TS55 | typeof TS55 in library-tests/TypeScript/Types/tst.ts |
|
||||
| tst.ts:499:9:499:15 | strings | string[] |
|
||||
| tst.ts:499:19:499:32 | (["foo", 123]) | (string \| number)[] |
|
||||
| tst.ts:499:19:500:11 | (["foo" ... .filter | { <S extends string \| number>(predicate: (value... |
|
||||
| tst.ts:499:19:500:39 | (["foo" ... tring") | string[] |
|
||||
| tst.ts:499:20:499:31 | ["foo", 123] | (string \| number)[] |
|
||||
| tst.ts:499:21:499:25 | "foo" | "foo" |
|
||||
| tst.ts:499:28:499:30 | 123 | 123 |
|
||||
| tst.ts:500:6:500:11 | filter | { <S extends string \| number>(predicate: (value... |
|
||||
| tst.ts:500:13:500:13 | s | string \| number |
|
||||
| tst.ts:500:13:500:38 | s => ty ... string" | (s: string \| number) => s is string |
|
||||
| tst.ts:500:18:500:25 | typeof s | "string" \| "number" \| "bigint" \| "boolean" \| "s... |
|
||||
| tst.ts:500:18:500:38 | typeof ... string" | boolean |
|
||||
| tst.ts:500:25:500:25 | s | string \| number |
|
||||
| tst.ts:500:31:500:38 | "string" | "string" |
|
||||
| tst.ts:502:14:502:16 | str | string |
|
||||
| tst.ts:502:21:502:27 | strings | string[] |
|
||||
| tst.ts:503:5:503:7 | str | string |
|
||||
| tst.ts:503:5:503:19 | str.toLowerCase | () => string |
|
||||
| tst.ts:503:5:503:21 | str.toLowerCase() | string |
|
||||
| tst.ts:503:9:503:19 | toLowerCase | () => string |
|
||||
| tst.ts:506:12:506:13 | f1 | (obj: Record<string, unknown>, key: string) => ... |
|
||||
| tst.ts:506:15:506:17 | obj | Record<string, unknown> |
|
||||
| tst.ts:506:45:506:47 | key | string |
|
||||
| tst.ts:507:9:507:23 | typeof obj[key] | "string" \| "number" \| "bigint" \| "boolean" \| "s... |
|
||||
| tst.ts:507:9:507:36 | typeof ... string" | boolean |
|
||||
| tst.ts:507:16:507:18 | obj | Record<string, unknown> |
|
||||
| tst.ts:507:16:507:23 | obj[key] | unknown |
|
||||
| tst.ts:507:20:507:22 | key | string |
|
||||
| tst.ts:507:29:507:36 | "string" | "string" |
|
||||
| tst.ts:508:11:508:13 | str | string |
|
||||
| tst.ts:508:17:508:19 | obj | Record<string, unknown> |
|
||||
| tst.ts:508:17:508:24 | obj[key] | string |
|
||||
| tst.ts:508:17:508:36 | obj[key].toUpperCase | () => string |
|
||||
| tst.ts:508:17:508:38 | obj[key ... rCase() | string |
|
||||
| tst.ts:508:21:508:23 | key | string |
|
||||
| tst.ts:508:26:508:36 | toUpperCase | () => string |
|
||||
| tstModuleCJS.cts:1:17:1:28 | tstModuleCJS | () => "a" \| "b" |
|
||||
| tstModuleCJS.cts:2:12:2:15 | Math | Math |
|
||||
| tstModuleCJS.cts:2:12:2:22 | Math.random | () => number |
|
||||
@@ -1178,6 +1215,11 @@ getTypeExprType
|
||||
| tst.ts:487:56:487:58 | C[] | C[] |
|
||||
| tst.ts:487:76:487:82 | NoInfer | any |
|
||||
| tst.ts:487:84:487:84 | C | C |
|
||||
| tst.ts:506:20:506:25 | Record | Record<K, T> |
|
||||
| tst.ts:506:20:506:42 | Record< ... nknown> | Record<string, unknown> |
|
||||
| tst.ts:506:27:506:32 | string | string |
|
||||
| tst.ts:506:35:506:41 | unknown | unknown |
|
||||
| tst.ts:506:50:506:55 | string | string |
|
||||
| tstModuleCJS.cts:1:33:1:35 | 'a' | "a" |
|
||||
| tstModuleCJS.cts:1:33:1:41 | 'a' \| 'b' | "a" \| "b" |
|
||||
| tstModuleCJS.cts:1:39:1:41 | 'b' | "b" |
|
||||
@@ -1375,6 +1417,7 @@ unknownType
|
||||
| tst.ts:228:12:228:16 | other | unknown |
|
||||
| tst.ts:229:16:229:20 | other | unknown |
|
||||
| tst.ts:230:20:230:24 | other | unknown |
|
||||
| tst.ts:507:16:507:23 | obj[key] | unknown |
|
||||
abstractSignature
|
||||
| (): HasArea |
|
||||
| new (): HasArea |
|
||||
|
||||
@@ -493,4 +493,19 @@ module TS54 {
|
||||
const myObj = Object.groupBy([0, 1, 2, 3, 4, 5], (num, index) => {
|
||||
return num % 2 === 0 ? "even": "odd";
|
||||
});
|
||||
}
|
||||
|
||||
module TS55 {
|
||||
const strings = (["foo", 123])
|
||||
.filter(s => typeof s === "string");
|
||||
|
||||
for (const str of strings) {
|
||||
str.toLowerCase(); // <- string in 5.5, string | number in 5.4
|
||||
}
|
||||
|
||||
function f1(obj: Record<string, unknown>, key: string) {
|
||||
if (typeof obj[key] === "string") {
|
||||
var str = obj[key].toUpperCase(); // Now okay, previously was error
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
| InsecureHelmetBad.js:6:9:9:2 | helmet( ... uard\\n}) | Helmet security middleware, configured with security setting $@ set to 'false', which disables enforcing that feature. | InsecureHelmetBad.js:7:5:7:32 | content ... : false | contentSecurityPolicy |
|
||||
| InsecureHelmetBad.js:6:9:9:2 | helmet( ... uard\\n}) | Helmet security middleware, configured with security setting $@ set to 'false', which disables enforcing that feature. | InsecureHelmetBad.js:8:5:8:21 | frameguard: false | frameguard |
|
||||
@@ -0,0 +1 @@
|
||||
Security/CWE-693/InsecureHelmet.ql
|
||||
@@ -0,0 +1,17 @@
|
||||
const express = require("express");
|
||||
const helmet = require("helmet");
|
||||
|
||||
const app = express();
|
||||
|
||||
app.use(helmet({
|
||||
contentSecurityPolicy: false, // BAD: switch off default CSP
|
||||
frameguard: false // BAD: switch off default frameguard
|
||||
}));
|
||||
|
||||
app.get("/", (req, res) => {
|
||||
res.send("Hello, world!");
|
||||
});
|
||||
|
||||
app.listen(3000, () => {
|
||||
console.log("App is listening on port 3000");
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
const express = require("express");
|
||||
const helmet = require("helmet");
|
||||
|
||||
const app = express();
|
||||
|
||||
app.use(helmet()); // GOOD: use the defaults
|
||||
|
||||
app.get("/", (req, res) => {
|
||||
res.send("Hello, world!");
|
||||
});
|
||||
|
||||
app.listen(3000, () => {
|
||||
console.log("App is listening on port 3000");
|
||||
});
|
||||
@@ -0,0 +1 @@
|
||||
| polyfill-nocheck.html:4:9:4:98 | <script>...</> | Content loaded from untrusted domain with no integrity check. |
|
||||
@@ -0,0 +1 @@
|
||||
Security/CWE-830/FunctionalityFromUntrustedDomain.ql
|
||||
@@ -0,0 +1,9 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Polyfill demo - Cloudflare hosted with pinned version and integrity checking</title>
|
||||
<script src="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?version=4.8.0" integrity="sha384-3d4jRKquKl90C9aFG+eH4lPJmtbPHgACWHrp+VomFOxF8lzx2jxqeYkhpRg18UWC" crossorigin="anonymous"></script>
|
||||
</head>
|
||||
<body>
|
||||
...
|
||||
</body>
|
||||
</html>
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user