Merge pull request #8604 from erik-krogh/httpNode

JS: refactor most library models away from AST nodes
This commit is contained in:
Erik Krogh Kristensen
2022-09-09 10:04:17 +02:00
committed by GitHub
153 changed files with 1924 additions and 1163 deletions

View File

@@ -42,17 +42,19 @@ predicate isABuiltinEventName(string name) {
* Holds if user code emits or broadcasts an event named `name`.
*/
predicate isAUserDefinedEventName(string name) {
exists(string methodName, MethodCallExpr mce | methodName = "$emit" or methodName = "$broadcast" |
mce.getArgument(0).mayHaveStringValue(name) and
exists(string methodName, DataFlow::MethodCallNode mcn |
methodName = "$emit" or methodName = "$broadcast"
|
mcn.getArgument(0).mayHaveStringValue(name) and
(
// dataflow based scope resolution
mce = any(AngularJS::ScopeServiceReference scope).getAMethodCall(methodName)
mcn = any(AngularJS::ScopeServiceReference scope).getAMethodCall(methodName)
or
// heuristic scope resolution: assume parameters like `$scope` or `$rootScope` are AngularJS scope objects
exists(SimpleParameter param |
exists(DataFlow::ParameterNode param |
param.getName() = any(AngularJS::ScopeServiceReference scope).getName() and
mce.getReceiver().mayReferToParameter(param) and
mce.getMethodName() = methodName
param.getAMethodCall() = mcn and
mcn.getMethodName() = methodName
)
or
// a call in an AngularJS expression
@@ -64,7 +66,7 @@ predicate isAUserDefinedEventName(string name) {
)
}
from AngularJS::ScopeServiceReference scope, MethodCallExpr mce, string eventName
from AngularJS::ScopeServiceReference scope, DataFlow::MethodCallNode mce, string eventName
where
mce = scope.getAMethodCall("$on") and
mce.getArgument(0).mayHaveStringValue(eventName) and

View File

@@ -14,7 +14,7 @@
import javascript
from AngularJS::InjectableFunction f, SimpleParameter p, string msg
from AngularJS::InjectableFunction f, DataFlow::ParameterNode p, string msg
where
p = f.asFunction().getAParameter() and
(

View File

@@ -14,7 +14,7 @@
import javascript
from MethodCallExpr mce, AngularJS::BuiltinServiceReference service
from DataFlow::MethodCallNode mce, AngularJS::BuiltinServiceReference service
where
service.getName() = "$sceProvider" and
mce = service.getAMethodCall("enabled") and

View File

@@ -15,7 +15,7 @@
import javascript
from AngularJS::ServiceReference compile, SimpleParameter elem, CallExpr c
from AngularJS::ServiceReference compile, DataFlow::ParameterNode elem, DataFlow::CallNode c
where
compile.getName() = "$compile" and
elem =
@@ -24,7 +24,7 @@ where
.(AngularJS::LinkFunction)
.getElementParameter() and
c = compile.getACall() and
c.getArgument(0).mayReferToParameter(elem) and
elem.flowsTo(c.getArgument(0)) and
// don't flag $compile calls that specify a `maxPriority`
c.getNumArgument() < 3
select c, "This call to $compile may cause double compilation of '" + elem + "'."

View File

@@ -12,16 +12,17 @@
import javascript
import semmle.javascript.RestrictedLocations
predicate isRepeatedDependency(AngularJS::InjectableFunction f, string name, AstNode location) {
predicate isRepeatedDependency(AngularJS::InjectableFunction f, string name, DataFlow::Node node) {
exists(int i, int j |
i < j and
exists(f.getDependencyDeclaration(i, name)) and
location = f.getDependencyDeclaration(j, name)
node = f.getDependencyDeclaration(j, name)
)
}
from AngularJS::InjectableFunction f, AstNode node, string name
from AngularJS::InjectableFunction f, DataFlow::Node node, string name
where
isRepeatedDependency(f, name, node) and
not count(f.asFunction().getParameterByName(name)) > 1 // avoid duplicating reports from js/duplicate-parameter-name
select f.asFunction().(FirstLineOf), "This function has a duplicate dependency '$@'.", node, name
select f.asFunction().getFunction().(FirstLineOf), "This function has a duplicate dependency '$@'.",
node, name

View File

@@ -23,7 +23,7 @@ predicate isResourceUrlWhitelist(
) {
exists(AngularJS::ServiceReference service |
service.getName() = "$sceDelegateProvider" and
setupCall.asExpr() = service.getAMethodCall("resourceUrlWhitelist") and
setupCall = service.getAMethodCall("resourceUrlWhitelist") and
list.flowsTo(setupCall.getArgument(0))
)
}

View File

@@ -12,9 +12,9 @@
import javascript
import semmle.javascript.RestrictedLocations
from AngularJS::InjectableFunction f, AstNode explicitInjection
from AngularJS::InjectableFunction f, DataFlow::Node explicitInjection
where
count(f.getAnExplicitDependencyInjection()) > 1 and
explicitInjection = f.getAnExplicitDependencyInjection()
select f.asFunction().(FirstLineOf), "This function has $@ defined in multiple places.",
explicitInjection, "dependency injections"
select f.asFunction().getFunction().(FirstLineOf),
"This function has $@ defined in multiple places.", explicitInjection, "dependency injections"

View File

@@ -13,9 +13,9 @@ import javascript
import Declarations.UnusedParameter
import semmle.javascript.RestrictedLocations
predicate isUnusedParameter(Function f, string msg, Parameter parameter) {
predicate isUnusedParameter(DataFlow::FunctionNode f, string msg, Parameter parameter) {
exists(Variable pv |
isUnused(f, parameter, pv, _) and
isUnused(f.getFunction(), parameter, pv, _) and
not isAnAccidentallyUnusedParameter(parameter) and // avoid double alerts
msg = "Unused dependency " + pv.getName() + "."
)

View File

@@ -135,7 +135,7 @@ DataFlow::CallNode servesAPrivateFolder(string description) {
*/
Express::RouteSetup getAnExposingExpressSetup(string path) {
result.isUseCall() and
result.getArgument([0 .. 1]) = servesAPrivateFolder(path).getEnclosingExpr()
result.getArgument([0 .. 1]) = servesAPrivateFolder(path)
}
/**
@@ -149,7 +149,7 @@ DataFlow::CallNode getAnExposingServeSetup(string path) {
from DataFlow::Node node, string path
where
node = getAnExposingExpressSetup(path).flow()
node = getAnExposingExpressSetup(path)
or
node = getAnExposingServeSetup(path)
select node, "Serves " + path + ", which can contain private information."

View File

@@ -19,7 +19,7 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where
cfg.hasFlowPath(source, sink) and
not source.getNode().asExpr() instanceof CleartextPasswordExpr // flagged by js/insufficient-password-hash
not source.getNode() instanceof CleartextPasswordExpr // flagged by js/insufficient-password-hash
select sink.getNode(), source, sink,
"Sensitive data from $@ is used in a broken or weak cryptographic algorithm.", source.getNode(),
source.getNode().(Source).describe()

View File

@@ -15,13 +15,13 @@ import javascript
from
Routing::RouteSetup setup, Routing::RouteHandler handler, HTTP::RequestInputAccess input,
SensitiveExpr sensitive
SensitiveNode sensitive
where
setup.getOwnHttpMethod() = "GET" and
setup.getAChild+() = handler and
input.getRouteHandler() = handler.getFunction() and
input.getKind() = "parameter" and
input.(DataFlow::SourceNode).flowsToExpr(sensitive) and
input.(DataFlow::SourceNode).flowsTo(sensitive) and
not sensitive.getClassification() = SensitiveDataClassification::id()
select input, "$@ for GET requests uses query parameter as sensitive data.", handler,
"Route handler"

View File

@@ -77,7 +77,7 @@ private module StandardPoIs {
UnpromotedRouteSetupPoI() { this = "UnpromotedRouteSetupPoI" }
override predicate is(Node l0) {
l0 instanceof HTTP::RouteSetupCandidate and not l0.asExpr() instanceof HTTP::RouteSetup
l0 instanceof HTTP::RouteSetupCandidate and not l0 instanceof HTTP::RouteSetup
}
}

View File

@@ -13,7 +13,7 @@ import CandidateTracking
from HTTP::RouteSetupCandidate setup
where
not setup.asExpr() instanceof HTTP::RouteSetup and
not setup instanceof HTTP::RouteSetup and
exists(HTTP::RouteHandlerCandidate rh |
track(rh, DataFlow::TypeTracker::end()).flowsTo(setup.getARouteHandlerArg())
)