Skip to content

Commit cdf3cdc

Browse files
committed
add model for the formatByString and formatByNumber functions in @date-io
1 parent 2a4570e commit cdf3cdc

File tree

4 files changed

+127
-0
lines changed

4 files changed

+127
-0
lines changed

javascript/ql/src/semmle/javascript/frameworks/DateFunctions.qll

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,28 @@ private module DateFns {
5353
}
5454
}
5555

56+
/**
57+
* Provides classes and predicates modelling the `@date-io` libraries.
58+
*/
59+
private module DateIO {
60+
private class FormatStep extends TaintTracking::SharedTaintStep {
61+
override predicate stringManipulationStep(DataFlow::Node pred, DataFlow::Node succ) {
62+
exists(API::CallNode formatCall |
63+
formatCall =
64+
API::moduleImport("@date-io/" +
65+
["date-fns", "moment", "luxon", "dayjs", "date-fns-jalali", "jalaali", "hijri"])
66+
.getInstance()
67+
// the `format` function only select between a predefined list of formats, but the `formatByString` function formats using any string.
68+
.getMember(["formatByString", "formatNumber"])
69+
.getACall()
70+
|
71+
pred = formatCall.getArgument(1) and
72+
succ = formatCall
73+
)
74+
}
75+
}
76+
}
77+
5678
private module Moment {
5779
/** Gets a reference to a `moment` object. */
5880
private API::Node moment() {

javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/Xss.expected

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,27 @@ nodes
130130
| dates.js:21:31:21:68 | `Time i ... aint)}` |
131131
| dates.js:21:42:21:66 | dayjs(t ... (taint) |
132132
| dates.js:21:61:21:65 | taint |
133+
| dates.js:30:9:30:69 | taint |
134+
| dates.js:30:17:30:69 | decodeU ... ing(1)) |
135+
| dates.js:30:36:30:55 | window.location.hash |
136+
| dates.js:30:36:30:55 | window.location.hash |
137+
| dates.js:30:36:30:68 | window. ... ring(1) |
138+
| dates.js:37:31:37:84 | `Time i ... aint)}` |
139+
| dates.js:37:31:37:84 | `Time i ... aint)}` |
140+
| dates.js:37:42:37:82 | dateFns ... taint) |
141+
| dates.js:37:77:37:81 | taint |
142+
| dates.js:38:31:38:84 | `Time i ... aint)}` |
143+
| dates.js:38:31:38:84 | `Time i ... aint)}` |
144+
| dates.js:38:42:38:82 | luxon.f ... taint) |
145+
| dates.js:38:77:38:81 | taint |
146+
| dates.js:39:31:39:86 | `Time i ... aint)}` |
147+
| dates.js:39:31:39:86 | `Time i ... aint)}` |
148+
| dates.js:39:42:39:84 | moment. ... taint) |
149+
| dates.js:39:79:39:83 | taint |
150+
| dates.js:40:31:40:84 | `Time i ... aint)}` |
151+
| dates.js:40:31:40:84 | `Time i ... aint)}` |
152+
| dates.js:40:42:40:82 | dayjs.f ... taint) |
153+
| dates.js:40:77:40:81 | taint |
133154
| event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
134155
| event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
135156
| event-handler-receiver.js:2:49:2:61 | location.href |
@@ -782,6 +803,26 @@ edges
782803
| dates.js:21:42:21:66 | dayjs(t ... (taint) | dates.js:21:31:21:68 | `Time i ... aint)}` |
783804
| dates.js:21:42:21:66 | dayjs(t ... (taint) | dates.js:21:31:21:68 | `Time i ... aint)}` |
784805
| dates.js:21:61:21:65 | taint | dates.js:21:42:21:66 | dayjs(t ... (taint) |
806+
| dates.js:30:9:30:69 | taint | dates.js:37:77:37:81 | taint |
807+
| dates.js:30:9:30:69 | taint | dates.js:38:77:38:81 | taint |
808+
| dates.js:30:9:30:69 | taint | dates.js:39:79:39:83 | taint |
809+
| dates.js:30:9:30:69 | taint | dates.js:40:77:40:81 | taint |
810+
| dates.js:30:17:30:69 | decodeU ... ing(1)) | dates.js:30:9:30:69 | taint |
811+
| dates.js:30:36:30:55 | window.location.hash | dates.js:30:36:30:68 | window. ... ring(1) |
812+
| dates.js:30:36:30:55 | window.location.hash | dates.js:30:36:30:68 | window. ... ring(1) |
813+
| dates.js:30:36:30:68 | window. ... ring(1) | dates.js:30:17:30:69 | decodeU ... ing(1)) |
814+
| dates.js:37:42:37:82 | dateFns ... taint) | dates.js:37:31:37:84 | `Time i ... aint)}` |
815+
| dates.js:37:42:37:82 | dateFns ... taint) | dates.js:37:31:37:84 | `Time i ... aint)}` |
816+
| dates.js:37:77:37:81 | taint | dates.js:37:42:37:82 | dateFns ... taint) |
817+
| dates.js:38:42:38:82 | luxon.f ... taint) | dates.js:38:31:38:84 | `Time i ... aint)}` |
818+
| dates.js:38:42:38:82 | luxon.f ... taint) | dates.js:38:31:38:84 | `Time i ... aint)}` |
819+
| dates.js:38:77:38:81 | taint | dates.js:38:42:38:82 | luxon.f ... taint) |
820+
| dates.js:39:42:39:84 | moment. ... taint) | dates.js:39:31:39:86 | `Time i ... aint)}` |
821+
| dates.js:39:42:39:84 | moment. ... taint) | dates.js:39:31:39:86 | `Time i ... aint)}` |
822+
| dates.js:39:79:39:83 | taint | dates.js:39:42:39:84 | moment. ... taint) |
823+
| dates.js:40:42:40:82 | dayjs.f ... taint) | dates.js:40:31:40:84 | `Time i ... aint)}` |
824+
| dates.js:40:42:40:82 | dayjs.f ... taint) | dates.js:40:31:40:84 | `Time i ... aint)}` |
825+
| dates.js:40:77:40:81 | taint | dates.js:40:42:40:82 | dayjs.f ... taint) |
785826
| event-handler-receiver.js:2:49:2:61 | location.href | event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
786827
| event-handler-receiver.js:2:49:2:61 | location.href | event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
787828
| event-handler-receiver.js:2:49:2:61 | location.href | event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
@@ -1294,6 +1335,10 @@ edges
12941335
| dates.js:16:31:16:69 | `Time i ... aint)}` | dates.js:9:36:9:55 | window.location.hash | dates.js:16:31:16:69 | `Time i ... aint)}` | Cross-site scripting vulnerability due to $@. | dates.js:9:36:9:55 | window.location.hash | user-provided value |
12951336
| dates.js:18:31:18:66 | `Time i ... aint)}` | dates.js:9:36:9:55 | window.location.hash | dates.js:18:31:18:66 | `Time i ... aint)}` | Cross-site scripting vulnerability due to $@. | dates.js:9:36:9:55 | window.location.hash | user-provided value |
12961337
| dates.js:21:31:21:68 | `Time i ... aint)}` | dates.js:9:36:9:55 | window.location.hash | dates.js:21:31:21:68 | `Time i ... aint)}` | Cross-site scripting vulnerability due to $@. | dates.js:9:36:9:55 | window.location.hash | user-provided value |
1338+
| dates.js:37:31:37:84 | `Time i ... aint)}` | dates.js:30:36:30:55 | window.location.hash | dates.js:37:31:37:84 | `Time i ... aint)}` | Cross-site scripting vulnerability due to $@. | dates.js:30:36:30:55 | window.location.hash | user-provided value |
1339+
| dates.js:38:31:38:84 | `Time i ... aint)}` | dates.js:30:36:30:55 | window.location.hash | dates.js:38:31:38:84 | `Time i ... aint)}` | Cross-site scripting vulnerability due to $@. | dates.js:30:36:30:55 | window.location.hash | user-provided value |
1340+
| dates.js:39:31:39:86 | `Time i ... aint)}` | dates.js:30:36:30:55 | window.location.hash | dates.js:39:31:39:86 | `Time i ... aint)}` | Cross-site scripting vulnerability due to $@. | dates.js:30:36:30:55 | window.location.hash | user-provided value |
1341+
| dates.js:40:31:40:84 | `Time i ... aint)}` | dates.js:30:36:30:55 | window.location.hash | dates.js:40:31:40:84 | `Time i ... aint)}` | Cross-site scripting vulnerability due to $@. | dates.js:30:36:30:55 | window.location.hash | user-provided value |
12971342
| event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' | event-handler-receiver.js:2:49:2:61 | location.href | event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' | Cross-site scripting vulnerability due to $@. | event-handler-receiver.js:2:49:2:61 | location.href | user-provided value |
12981343
| express.js:7:15:7:33 | req.param("wobble") | express.js:7:15:7:33 | req.param("wobble") | express.js:7:15:7:33 | req.param("wobble") | Cross-site scripting vulnerability due to $@. | express.js:7:15:7:33 | req.param("wobble") | user-provided value |
12991344
| jquery.js:7:5:7:34 | "<div i ... + "\\">" | jquery.js:2:17:2:40 | documen ... .search | jquery.js:7:5:7:34 | "<div i ... + "\\">" | Cross-site scripting vulnerability due to $@. | jquery.js:2:17:2:40 | documen ... .search | user-provided value |

javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,27 @@ nodes
130130
| dates.js:21:31:21:68 | `Time i ... aint)}` |
131131
| dates.js:21:42:21:66 | dayjs(t ... (taint) |
132132
| dates.js:21:61:21:65 | taint |
133+
| dates.js:30:9:30:69 | taint |
134+
| dates.js:30:17:30:69 | decodeU ... ing(1)) |
135+
| dates.js:30:36:30:55 | window.location.hash |
136+
| dates.js:30:36:30:55 | window.location.hash |
137+
| dates.js:30:36:30:68 | window. ... ring(1) |
138+
| dates.js:37:31:37:84 | `Time i ... aint)}` |
139+
| dates.js:37:31:37:84 | `Time i ... aint)}` |
140+
| dates.js:37:42:37:82 | dateFns ... taint) |
141+
| dates.js:37:77:37:81 | taint |
142+
| dates.js:38:31:38:84 | `Time i ... aint)}` |
143+
| dates.js:38:31:38:84 | `Time i ... aint)}` |
144+
| dates.js:38:42:38:82 | luxon.f ... taint) |
145+
| dates.js:38:77:38:81 | taint |
146+
| dates.js:39:31:39:86 | `Time i ... aint)}` |
147+
| dates.js:39:31:39:86 | `Time i ... aint)}` |
148+
| dates.js:39:42:39:84 | moment. ... taint) |
149+
| dates.js:39:79:39:83 | taint |
150+
| dates.js:40:31:40:84 | `Time i ... aint)}` |
151+
| dates.js:40:31:40:84 | `Time i ... aint)}` |
152+
| dates.js:40:42:40:82 | dayjs.f ... taint) |
153+
| dates.js:40:77:40:81 | taint |
133154
| event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
134155
| event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
135156
| event-handler-receiver.js:2:49:2:61 | location.href |
@@ -800,6 +821,26 @@ edges
800821
| dates.js:21:42:21:66 | dayjs(t ... (taint) | dates.js:21:31:21:68 | `Time i ... aint)}` |
801822
| dates.js:21:42:21:66 | dayjs(t ... (taint) | dates.js:21:31:21:68 | `Time i ... aint)}` |
802823
| dates.js:21:61:21:65 | taint | dates.js:21:42:21:66 | dayjs(t ... (taint) |
824+
| dates.js:30:9:30:69 | taint | dates.js:37:77:37:81 | taint |
825+
| dates.js:30:9:30:69 | taint | dates.js:38:77:38:81 | taint |
826+
| dates.js:30:9:30:69 | taint | dates.js:39:79:39:83 | taint |
827+
| dates.js:30:9:30:69 | taint | dates.js:40:77:40:81 | taint |
828+
| dates.js:30:17:30:69 | decodeU ... ing(1)) | dates.js:30:9:30:69 | taint |
829+
| dates.js:30:36:30:55 | window.location.hash | dates.js:30:36:30:68 | window. ... ring(1) |
830+
| dates.js:30:36:30:55 | window.location.hash | dates.js:30:36:30:68 | window. ... ring(1) |
831+
| dates.js:30:36:30:68 | window. ... ring(1) | dates.js:30:17:30:69 | decodeU ... ing(1)) |
832+
| dates.js:37:42:37:82 | dateFns ... taint) | dates.js:37:31:37:84 | `Time i ... aint)}` |
833+
| dates.js:37:42:37:82 | dateFns ... taint) | dates.js:37:31:37:84 | `Time i ... aint)}` |
834+
| dates.js:37:77:37:81 | taint | dates.js:37:42:37:82 | dateFns ... taint) |
835+
| dates.js:38:42:38:82 | luxon.f ... taint) | dates.js:38:31:38:84 | `Time i ... aint)}` |
836+
| dates.js:38:42:38:82 | luxon.f ... taint) | dates.js:38:31:38:84 | `Time i ... aint)}` |
837+
| dates.js:38:77:38:81 | taint | dates.js:38:42:38:82 | luxon.f ... taint) |
838+
| dates.js:39:42:39:84 | moment. ... taint) | dates.js:39:31:39:86 | `Time i ... aint)}` |
839+
| dates.js:39:42:39:84 | moment. ... taint) | dates.js:39:31:39:86 | `Time i ... aint)}` |
840+
| dates.js:39:79:39:83 | taint | dates.js:39:42:39:84 | moment. ... taint) |
841+
| dates.js:40:42:40:82 | dayjs.f ... taint) | dates.js:40:31:40:84 | `Time i ... aint)}` |
842+
| dates.js:40:42:40:82 | dayjs.f ... taint) | dates.js:40:31:40:84 | `Time i ... aint)}` |
843+
| dates.js:40:77:40:81 | taint | dates.js:40:42:40:82 | dayjs.f ... taint) |
803844
| event-handler-receiver.js:2:49:2:61 | location.href | event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
804845
| event-handler-receiver.js:2:49:2:61 | location.href | event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
805846
| event-handler-receiver.js:2:49:2:61 | location.href | event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |

javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/dates.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,22 @@ function main() {
2020
import dayjs from 'dayjs';
2121
document.body.innerHTML = `Time is ${dayjs(time).format(taint)}`; // NOT OK
2222
}
23+
24+
import LuxonAdapter from "@date-io/luxon";
25+
import DateFnsAdapter from "@date-io/date-fns";
26+
import MomentAdapter from "@date-io/moment";
27+
import DayJSAdapter from "@date-io/dayjs"
28+
29+
function dateio() {
30+
let taint = decodeURIComponent(window.location.hash.substring(1));
31+
32+
const dateFns = new DateFnsAdapter();
33+
const luxon = new LuxonAdapter();
34+
const moment = new MomentAdapter();
35+
const dayjs = new DayJSAdapter();
36+
37+
document.body.innerHTML = `Time is ${dateFns.formatByString(new Date(), taint)}`; // NOT OK
38+
document.body.innerHTML = `Time is ${luxon.formatByString(luxon.date(), taint)}`; // NOT OK
39+
document.body.innerHTML = `Time is ${moment.formatByString(moment.date(), taint)}`; // NOT OK
40+
document.body.innerHTML = `Time is ${dayjs.formatByString(dayjs.date(), taint)}`; // NOT OK
41+
}

0 commit comments

Comments
 (0)