Skip to content

Commit 525da97

Browse files
committed
changes based on review feedback
1 parent 3b9847e commit 525da97

File tree

1 file changed

+12
-8
lines changed

1 file changed

+12
-8
lines changed

javascript/ql/src/semmle/javascript/security/dataflow/ExceptionXss.qll

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,23 @@ module ExceptionXss {
1717
DataFlow::ExceptionalInvocationReturnNode getCallerExceptionalReturn(Function func) {
1818
exists(DataFlow::InvokeNode call |
1919
not call.isImprecise() and
20-
func = call.(DataFlow::InvokeNode).getACallee() and
20+
func = call.getACallee() and
2121
result = call.getExceptionalReturn()
2222
)
2323
}
2424

2525
DataFlow::Node getExceptionalSuccessor(DataFlow::Node pred) {
2626
if exists(getEnclosingTryStmt(pred.asExpr().getEnclosingStmt()))
2727
then
28-
result.(DataFlow::ParameterNode).getParameter() = getEnclosingTryStmt(pred
28+
result = DataFlow::parameterNode(getEnclosingTryStmt(pred
2929
.asExpr()
30-
.getEnclosingStmt()).getACatchClause().getAParameter()
30+
.getEnclosingStmt()).getACatchClause().getAParameter())
3131
else result = getCallerExceptionalReturn(pred.getContainer())
3232
}
3333

3434
predicate canThrowSensitiveInformation(DataFlow::Node node) {
35-
// i have to do this "dual" check because there are two data-flow nodes associated with reflective calls.
36-
node = any(DataFlow::InvokeNode call).getAnArgument() and
37-
not node = any(DataFlow::InvokeNode call | exists(call.getACallee())).getAnArgument()
35+
// in the case of reflective calls the below ensures that both InvokeNodes have no known callee.
36+
forex(DataFlow::InvokeNode call | node = call.getAnArgument() | not exists(call.getACallee()))
3837
or
3938
node.asExpr().getEnclosingStmt() instanceof ThrowStmt
4039
}
@@ -46,6 +45,12 @@ module ExceptionXss {
4645
)
4746
}
4847

48+
/**
49+
* A FlowLabel representing tainted data that has not been thrown in an exception.
50+
* In the js/xss-through-exception query data-flow can only reach a sink after
51+
* the data has been thrown as an exception, and data that has not been thrown
52+
* as an exception therefore has this flow label, and only this flow label, associated with it.
53+
*/
4954
class NotYetThrown extends DataFlow::FlowLabel {
5055
NotYetThrown() { this = "NotYetThrown" }
5156
}
@@ -67,13 +72,12 @@ module ExceptionXss {
6772
}
6873

6974
override predicate isSanitizer(DataFlow::Node node) {
70-
super.isSanitizer(node) or
7175
node instanceof XSS::Shared::Sanitizer
7276
}
7377

7478
override predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl) {
7579
inlbl instanceof NotYetThrown and (outlbl.isTaint() or outlbl instanceof NotYetThrown) and
76-
succ = getExceptionalSuccssor(pred) and
80+
succ = getExceptionalSuccessor(pred) and
7781
(canThrowSensitiveInformation(pred) or pred = any(DataFlow::InvokeNode c).getExceptionalReturn())
7882
or
7983
// All the usual taint-flow steps apply on data-flow before it has been thrown in an exception.

0 commit comments

Comments
 (0)