mirror of
https://github.com/github/codeql.git
synced 2026-05-01 03:35:13 +02:00
JS: Add more metrics
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
/**
|
||||
* Helpers to generating meta metrics, that is, metrics about the CodeQL analysis and extractor.
|
||||
*/
|
||||
|
||||
private import javascript
|
||||
private import semmle.javascript.dependencies.Dependencies
|
||||
private import semmle.javascript.dependencies.FrameworkLibraries
|
||||
|
||||
@@ -9,7 +9,6 @@ private import semmle.javascript.dependencies.Dependencies
|
||||
private import semmle.javascript.dependencies.FrameworkLibraries
|
||||
private import semmle.javascript.frameworks.Testing
|
||||
private import DataFlow
|
||||
|
||||
import meta.MetaMetrics
|
||||
|
||||
/** An call site that is relevant for analysis quality. */
|
||||
|
||||
17
javascript/ql/src/meta/analysis-quality/ResolvableImports.ql
Normal file
17
javascript/ql/src/meta/analysis-quality/ResolvableImports.ql
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* @name Resolvable imports
|
||||
* @description The number of imports that could be resolved to its target.
|
||||
* @kind metric
|
||||
* @metricType project
|
||||
* @metricAggregate sum
|
||||
* @tags meta
|
||||
* @id js/meta/resolvable-imports
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import CallGraphQuality
|
||||
|
||||
Import relevantImport() { not result.getFile() instanceof IgnoredFile }
|
||||
|
||||
select projectRoot(),
|
||||
count(Import imprt | imprt = relevantImport() and exists(imprt.getImportedModule()))
|
||||
16
javascript/ql/src/meta/analysis-quality/RouteHandlers.ql
Normal file
16
javascript/ql/src/meta/analysis-quality/RouteHandlers.ql
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* @name Route handlers
|
||||
* @description The number of HTTP route handler functions found.
|
||||
* @kind metric
|
||||
* @metricType project
|
||||
* @metricAggregate sum
|
||||
* @tags meta
|
||||
* @id js/meta/route-handlers
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import CallGraphQuality
|
||||
|
||||
HTTP::RouteHandler relevantRouteHandler() { not result.getFile() instanceof IgnoredFile }
|
||||
|
||||
select projectRoot(), count(relevantRouteHandler())
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @name Sanitizers reachable from source
|
||||
* @description The number of sanitizers reachable from a recognized taint source.
|
||||
* @kind metric
|
||||
* @metricType project
|
||||
* @metricAggregate sum
|
||||
* @tags meta
|
||||
* @id js/meta/sanitizers-reachable-from-source
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import TaintMetrics
|
||||
|
||||
class BasicTaintConfiguration extends TaintTracking::Configuration {
|
||||
BasicTaintConfiguration() { this = "BasicTaintConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node node) { node = relevantTaintSource() }
|
||||
|
||||
override predicate isSink(DataFlow::Node node) { node = relevantSanitizerInput() }
|
||||
}
|
||||
|
||||
select projectRoot(), count(DataFlow::Node node | any(BasicTaintConfiguration cfg).hasFlow(_, node))
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @name Sinks reachable from sanitizer
|
||||
* @description The number of sinks reachable from a recognized sanitizer call.
|
||||
* @kind metric
|
||||
* @metricType project
|
||||
* @metricAggregate sum
|
||||
* @tags meta
|
||||
* @id js/meta/sinks-reachable-from-sanitizer
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import TaintMetrics
|
||||
|
||||
class BasicTaintConfiguration extends TaintTracking::Configuration {
|
||||
BasicTaintConfiguration() { this = "BasicTaintConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node node) { node = relevantSanitizerOutput() }
|
||||
|
||||
override predicate isSink(DataFlow::Node node) { node = relevantTaintSink() }
|
||||
}
|
||||
|
||||
select projectRoot(), count(DataFlow::Node node | any(BasicTaintConfiguration cfg).hasFlow(_, node))
|
||||
89
javascript/ql/src/meta/analysis-quality/TaintMetrics.qll
Normal file
89
javascript/ql/src/meta/analysis-quality/TaintMetrics.qll
Normal file
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* Provides predicates for measuring taint-tracking coverage.
|
||||
*/
|
||||
|
||||
private import javascript
|
||||
import meta.MetaMetrics
|
||||
private import semmle.javascript.security.dataflow.ClientSideUrlRedirectCustomizations
|
||||
private import semmle.javascript.security.dataflow.CodeInjectionCustomizations
|
||||
private import semmle.javascript.security.dataflow.CommandInjectionCustomizations
|
||||
private import semmle.javascript.security.dataflow.Xss as Xss
|
||||
private import semmle.javascript.security.dataflow.NosqlInjectionCustomizations
|
||||
private import semmle.javascript.security.dataflow.PrototypePollutionCustomizations
|
||||
private import semmle.javascript.security.dataflow.RegExpInjectionCustomizations
|
||||
private import semmle.javascript.security.dataflow.RequestForgeryCustomizations
|
||||
private import semmle.javascript.security.dataflow.ServerSideUrlRedirectCustomizations
|
||||
private import semmle.javascript.security.dataflow.SqlInjectionCustomizations
|
||||
private import semmle.javascript.security.dataflow.TaintedPathCustomizations
|
||||
private import semmle.javascript.security.dataflow.UnsafeDeserializationCustomizations
|
||||
private import semmle.javascript.security.dataflow.XmlBombCustomizations
|
||||
private import semmle.javascript.security.dataflow.XpathInjectionCustomizations
|
||||
private import semmle.javascript.security.dataflow.XxeCustomizations
|
||||
private import semmle.javascript.security.dataflow.ZipSlipCustomizations
|
||||
|
||||
/**
|
||||
* Gets a relevant taint sink.
|
||||
*
|
||||
* To ensure this metric isn't dominated by a few queries with a huge number of sinks,
|
||||
* we only include sinks for queries that have fairly specific sinks and/or have high severity
|
||||
* relative to the number of sinks.
|
||||
*
|
||||
* Examples of excluded queries:
|
||||
* - UnsafeDynamicMethodAccess: high severity (RCE) but has way too many sinks (every callee).
|
||||
* - ClearTextLogging: not severe enough relative to number of sinks.
|
||||
*/
|
||||
DataFlow::Node relevantTaintSink() {
|
||||
not result.getFile() instanceof IgnoredFile and
|
||||
(
|
||||
result instanceof ClientSideUrlRedirect::Sink or
|
||||
result instanceof CodeInjection::Sink or
|
||||
result instanceof CommandInjection::Sink or
|
||||
result instanceof Xss::Shared::Sink or
|
||||
result instanceof NosqlInjection::Sink or
|
||||
result instanceof PrototypePollution::Sink or
|
||||
result instanceof RegExpInjection::Sink or
|
||||
result instanceof RequestForgery::Sink or
|
||||
result instanceof ServerSideUrlRedirect::Sink or
|
||||
result instanceof SqlInjection::Sink or
|
||||
result instanceof TaintedPath::Sink or
|
||||
result instanceof UnsafeDeserialization::Sink or
|
||||
result instanceof XmlBomb::Sink or
|
||||
result instanceof XpathInjection::Sink or
|
||||
result instanceof Xxe::Sink or
|
||||
result instanceof ZipSlip::Sink
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a remote flow source or `document.location` source.
|
||||
*/
|
||||
DataFlow::Node relevantTaintSource() {
|
||||
not result.getFile() instanceof IgnoredFile and
|
||||
(
|
||||
result instanceof RemoteFlowSource
|
||||
or
|
||||
result = DOM::locationSource()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the output of a call that shows intent to sanitize a value
|
||||
* (indicating a likely vulnerability if the sanitizer was removed).
|
||||
*
|
||||
* Currently we only recognize HTML sanitizers.
|
||||
*/
|
||||
DataFlow::Node relevantSanitizerOutput() {
|
||||
result = any(HtmlSanitizerCall call) and
|
||||
not result.getFile() instanceof IgnoredFile
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the input to a call that shows intent to sanitize a value
|
||||
* (indicating a likely vulnerability if the sanitizer was removed).
|
||||
*
|
||||
* Currently we only recognize HTML sanitizers.
|
||||
*/
|
||||
DataFlow::Node relevantSanitizerInput() {
|
||||
result = any(HtmlSanitizerCall call).getInput() and
|
||||
not result.getFile() instanceof IgnoredFile
|
||||
}
|
||||
14
javascript/ql/src/meta/analysis-quality/TaintSinks.ql
Normal file
14
javascript/ql/src/meta/analysis-quality/TaintSinks.ql
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @name Taint sinks
|
||||
* @description The number of high-severity taint sinks.
|
||||
* @kind metric
|
||||
* @metricType project
|
||||
* @metricAggregate sum
|
||||
* @tags meta
|
||||
* @id js/meta/taint-sinks
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import TaintMetrics
|
||||
|
||||
select projectRoot(), count(relevantTaintSink())
|
||||
14
javascript/ql/src/meta/analysis-quality/TaintSources.ql
Normal file
14
javascript/ql/src/meta/analysis-quality/TaintSources.ql
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @name Taint sources
|
||||
* @description The number of remote flow sources and document.location sources
|
||||
* @kind metric
|
||||
* @metricType project
|
||||
* @metricAggregate sum
|
||||
* @tags meta
|
||||
* @id js/meta/taint-sources
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import TaintMetrics
|
||||
|
||||
select projectRoot(), count(relevantTaintSource())
|
||||
24
javascript/ql/src/meta/analysis-quality/TaintSteps.ql
Normal file
24
javascript/ql/src/meta/analysis-quality/TaintSteps.ql
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* @name Taint steps
|
||||
* @description The number of default taint steps.
|
||||
* @kind metric
|
||||
* @metricType project
|
||||
* @metricAggregate sum
|
||||
* @tags meta
|
||||
* @id js/meta/taint-steps
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import CallGraphQuality
|
||||
|
||||
class BasicTaintConfiguration extends TaintTracking::Configuration {
|
||||
BasicTaintConfiguration() { this = "BasicTaintConfiguration" }
|
||||
}
|
||||
|
||||
predicate relevantStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
any(BasicTaintConfiguration cfg).isAdditionalFlowStep(pred, succ) and
|
||||
not pred.getFile() instanceof IgnoredFile and
|
||||
not succ.getFile() instanceof IgnoredFile
|
||||
}
|
||||
|
||||
select projectRoot(), count(DataFlow::Node pred, DataFlow::Node succ | relevantStep(pred, succ))
|
||||
27
javascript/ql/src/meta/analysis-quality/TaintedNodes.ql
Normal file
27
javascript/ql/src/meta/analysis-quality/TaintedNodes.ql
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* @name Tainted expressions
|
||||
* @description The number of expressions reachable from a remote flow source
|
||||
* via default taint-tracking steps.
|
||||
* @kind metric
|
||||
* @metricType project
|
||||
* @metricAggregate sum
|
||||
* @tags meta
|
||||
* @id js/meta/tainted-nodes
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import TaintMetrics
|
||||
|
||||
class BasicTaintConfiguration extends TaintTracking::Configuration {
|
||||
BasicTaintConfiguration() { this = "BasicTaintConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node node) { node = relevantTaintSource() }
|
||||
|
||||
override predicate isSink(DataFlow::Node node) {
|
||||
// To reduce noise from synthetic nodes, only count value nodes
|
||||
node instanceof DataFlow::ValueNode and
|
||||
not node.getFile() instanceof IgnoredFile
|
||||
}
|
||||
}
|
||||
|
||||
select projectRoot(), count(DataFlow::Node node | any(BasicTaintConfiguration cfg).hasFlow(_, node))
|
||||
@@ -12,8 +12,6 @@
|
||||
import javascript
|
||||
import meta.MetaMetrics
|
||||
|
||||
predicate isProperType(Type t) {
|
||||
not t instanceof AnyType
|
||||
}
|
||||
predicate isProperType(Type t) { not t instanceof AnyType }
|
||||
|
||||
select projectRoot(), count(Expr e | isProperType(e.getType()))
|
||||
|
||||
Reference in New Issue
Block a user