Skip to content

Commit d916118

Browse files
committed
JS: Move ExceptionXss source into Xss.qll
1 parent fd9604c commit d916118

File tree

3 files changed

+62
-52
lines changed

3 files changed

+62
-52
lines changed

javascript/ql/src/Security/CWE-079/ExceptionXss.ql

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,8 @@ import javascript
1515
import semmle.javascript.security.dataflow.ExceptionXss::ExceptionXss
1616
import DataFlow::PathGraph
1717

18-
/**
19-
* Gets a description of the source.
20-
*/
21-
string getSourceDescription(DataFlow::Node source) {
22-
result = source.(ErrorSource).getDescription()
23-
or
24-
not source instanceof ErrorSource and
25-
result = "Exception text"
26-
}
27-
2818
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
2919
where cfg.hasFlowPath(source, sink)
3020
select sink.getNode(), source, sink,
3121
"$@ is reinterpreted as HTML without escaping meta-characters.", source.getNode(),
32-
getSourceDescription(source.getNode())
22+
source.getNode().(Source).getDescription()

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

Lines changed: 5 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ module ExceptionXss {
1010
import DomBasedXssCustomizations::DomBasedXss as DomBasedXssCustom
1111
import ReflectedXssCustomizations::ReflectedXss as ReflectedXssCustom
1212
import Xss as Xss
13+
import Xss::ExceptionXss
1314
private import semmle.javascript.dataflow.InferredTypes
1415

1516
/**
@@ -71,14 +72,9 @@ module ExceptionXss {
7172
)
7273
}
7374

74-
/**
75-
* A FlowLabel representing tainted data that has not been thrown in an exception.
76-
* In the js/xss-through-exception query data-flow can only reach a sink after
77-
* the data has been thrown as an exception, and data that has not been thrown
78-
* as an exception therefore has this flow label, and only this flow label, associated with it.
79-
*/
80-
class NotYetThrown extends DataFlow::FlowLabel {
81-
NotYetThrown() { this = "NotYetThrown" }
75+
// Materialize flow labels
76+
private class ConcreteNotYetThrown extends Xss::ExceptionXss::NotYetThrown {
77+
ConcreteNotYetThrown() { this = this }
8278
}
8379

8480
/**
@@ -130,35 +126,6 @@ module ExceptionXss {
130126
result = getCallbackErrorParam(pred)
131127
}
132128

133-
/**
134-
* A source of error values that is likely to contain unencoded user input.
135-
*/
136-
abstract class ErrorSource extends DataFlow::Node {
137-
/**
138-
* Gets a human-readable description of what type of error this refers to.
139-
*
140-
* The result should be captialized and usable in the context of a noun.
141-
*/
142-
abstract string getDescription();
143-
}
144-
145-
/**
146-
* An error produced by validating using `ajv`.
147-
*
148-
* Such an error can contain property names from the input if the
149-
* underlying schema uses `additionalProperties` or `propertyPatterns`.
150-
*
151-
* For example, an input of form `{"<img src=x onerror=alert(1)>": 45}` might produce the error
152-
* `data/<img src=x onerror=alert(1)> should be string`.
153-
*/
154-
private class JsonSchemaValidationError extends ErrorSource {
155-
JsonSchemaValidationError() {
156-
this = any(JsonSchema::Ajv::Instance i).getAValidationError().getAnImmediateUse()
157-
}
158-
159-
override string getDescription() { result = "JSON schema validation error" }
160-
}
161-
162129
/**
163130
* A taint-tracking configuration for reasoning about XSS with possible exceptional flow.
164131
* Flow labels are used to ensure that we only report taint-flow that has been thrown in
@@ -168,10 +135,7 @@ module ExceptionXss {
168135
Configuration() { this = "ExceptionXss" }
169136

170137
override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) {
171-
source instanceof Xss::Shared::Source and label instanceof NotYetThrown
172-
or
173-
source instanceof ErrorSource and
174-
label.isTaint()
138+
source.(Xss::ExceptionXss::Source).getAFlowLabel() = label
175139
}
176140

177141
override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) {

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

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,3 +602,59 @@ module XssThroughDom {
602602
/** A data flow source for XSS through DOM vulnerabilities. */
603603
abstract class Source extends Shared::Source { }
604604
}
605+
606+
/** Provides classes for customizing the `ExceptionXss` query. */
607+
module ExceptionXss {
608+
/** A data flow source for XSS caused by interpreting exception or error text as HTML. */
609+
abstract class Source extends DataFlow::Node {
610+
/**
611+
* Gets a flow label to associate with this source.
612+
*
613+
* For sources that should pass through a `throw/catch` before reaching the sink, use the
614+
* `NotYetThrown` labe. Otherwise use `taint` (the default).
615+
*/
616+
DataFlow::FlowLabel getAFlowLabel() { result.isTaint() }
617+
618+
/**
619+
* Gets a human-readable description of what type of error this refers to.
620+
*
621+
* The result should be capitalized and usable in the context of a noun.
622+
*/
623+
string getDescription() { result = "Error text" }
624+
}
625+
626+
/**
627+
* A FlowLabel representing tainted data that has not been thrown in an exception.
628+
* In the js/xss-through-exception query data-flow can only reach a sink after
629+
* the data has been thrown as an exception, and data that has not been thrown
630+
* as an exception therefore has this flow label, and only this flow label, associated with it.
631+
*/
632+
abstract class NotYetThrown extends DataFlow::FlowLabel {
633+
NotYetThrown() { this = "NotYetThrown" }
634+
}
635+
636+
private class XssSourceAsSource extends Source {
637+
XssSourceAsSource() { this instanceof Shared::Source }
638+
639+
override DataFlow::FlowLabel getAFlowLabel() { result instanceof NotYetThrown }
640+
641+
override string getDescription() { result = "Exception text" }
642+
}
643+
644+
/**
645+
* An error produced by validating using `ajv`.
646+
*
647+
* Such an error can contain property names from the input if the
648+
* underlying schema uses `additionalProperties` or `propertyPatterns`.
649+
*
650+
* For example, an input of form `{"<img src=x onerror=alert(1)>": 45}` might produce the error
651+
* `data/<img src=x onerror=alert(1)> should be string`.
652+
*/
653+
private class JsonSchemaValidationError extends Source {
654+
JsonSchemaValidationError() {
655+
this = any(JsonSchema::Ajv::Instance i).getAValidationError().getAnImmediateUse()
656+
}
657+
658+
override string getDescription() { result = "JSON schema validation error" }
659+
}
660+
}

0 commit comments

Comments
 (0)