Skip to content

Commit c736606

Browse files
committed
add support for moment/dayjs/luxon instances returned by @date-io adapters
1 parent 227f61b commit c736606

File tree

5 files changed

+116
-1
lines changed

5 files changed

+116
-1
lines changed

javascript/change-notes/2021-06-21-dates.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,8 @@ lgtm,codescanning
22
* Improved support for date parsing libraries, resulting in more results in security queries.
33
Affected packages are
44
[dayjs](https://npmjs.com/package/dayjs),
5-
[luxon](https://npmjs.com/package/luxon)
5+
[luxon](https://npmjs.com/package/luxon),
6+
[@date-io/moment](https://npmjs.com/package/@date-io/moment),
7+
[@date-io/luxon](https://npmjs.com/package/@date-io/luxon),
8+
[@date-io/dayjs](https://npmjs.com/package/@date-io/dayjs)
69

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,35 @@ private module DateIO {
7373
)
7474
}
7575
}
76+
77+
/** Gets a method name from an `@date-io` adapter that returns an instance of the adapted library. */
78+
private string getAnAdapterMethodName() {
79+
result =
80+
[
81+
"addSeconds", "addMinutes", "addHours", "addDays", "addWeeks", "addMonths", "endOfDay",
82+
"setHours", "setMinutes", "setSeconds", "startOfMonth", "endOfMonth", "startOfWeek",
83+
"endOfWeek", "setYear", "date", "parse", "setMonth", "getNextMonth", "getPreviousMonth"
84+
]
85+
}
86+
87+
/**
88+
* Gets an instance of `library` that has been created by an `@date-io` adapter.
89+
* Library is one of: "moment", "luxon", or "dayjs".
90+
*/
91+
API::Node getAnAdaptedInstance(string library) {
92+
exists(API::Node adapter |
93+
library = "moment" and
94+
adapter = API::moduleImport("@date-io/moment")
95+
or
96+
library = "luxon" and
97+
adapter = API::moduleImport("@date-io/luxon")
98+
or
99+
library = "dayjs" and
100+
adapter = API::moduleImport("@date-io/dayjs")
101+
|
102+
result = adapter.getInstance().getMember(getAnAdapterMethodName()).getReturn()
103+
)
104+
}
76105
}
77106

78107
/**
@@ -99,6 +128,8 @@ private module Luxon {
99128
result = luxonDateTime().getAMember()
100129
or
101130
result = luxonDateTime().getReturn()
131+
or
132+
result = DateIO::getAnAdaptedInstance("luxon")
102133
)
103134
}
104135

@@ -125,6 +156,8 @@ private module Moment {
125156
result = moment().getReturn()
126157
or
127158
result = moment().getAMember()
159+
or
160+
result = DateIO::getAnAdaptedInstance(["moment", "dayjs"])
128161
}
129162

130163
/**

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

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,23 @@ nodes
168168
| dates.js:50:31:50:104 | `Time i ... aint)}` |
169169
| dates.js:50:42:50:102 | DateTim ... (taint) |
170170
| dates.js:50:97:50:101 | taint |
171+
| dates.js:54:9:54:69 | taint |
172+
| dates.js:54:17:54:69 | decodeU ... ing(1)) |
173+
| dates.js:54:36:54:55 | window.location.hash |
174+
| dates.js:54:36:54:55 | window.location.hash |
175+
| dates.js:54:36:54:68 | window. ... ring(1) |
176+
| dates.js:57:31:57:101 | `Time i ... aint)}` |
177+
| dates.js:57:31:57:101 | `Time i ... aint)}` |
178+
| dates.js:57:42:57:99 | moment. ... (taint) |
179+
| dates.js:57:94:57:98 | taint |
180+
| dates.js:59:31:59:87 | `Time i ... aint)}` |
181+
| dates.js:59:31:59:87 | `Time i ... aint)}` |
182+
| dates.js:59:42:59:85 | luxon.e ... (taint) |
183+
| dates.js:59:80:59:84 | taint |
184+
| dates.js:61:31:61:88 | `Time i ... aint)}` |
185+
| dates.js:61:31:61:88 | `Time i ... aint)}` |
186+
| dates.js:61:42:61:86 | dayjs.s ... (taint) |
187+
| dates.js:61:81:61:85 | taint |
171188
| event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
172189
| event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
173190
| event-handler-receiver.js:2:49:2:61 | location.href |
@@ -856,6 +873,22 @@ edges
856873
| dates.js:50:42:50:102 | DateTim ... (taint) | dates.js:50:31:50:104 | `Time i ... aint)}` |
857874
| dates.js:50:42:50:102 | DateTim ... (taint) | dates.js:50:31:50:104 | `Time i ... aint)}` |
858875
| dates.js:50:97:50:101 | taint | dates.js:50:42:50:102 | DateTim ... (taint) |
876+
| dates.js:54:9:54:69 | taint | dates.js:57:94:57:98 | taint |
877+
| dates.js:54:9:54:69 | taint | dates.js:59:80:59:84 | taint |
878+
| dates.js:54:9:54:69 | taint | dates.js:61:81:61:85 | taint |
879+
| dates.js:54:17:54:69 | decodeU ... ing(1)) | dates.js:54:9:54:69 | taint |
880+
| dates.js:54:36:54:55 | window.location.hash | dates.js:54:36:54:68 | window. ... ring(1) |
881+
| dates.js:54:36:54:55 | window.location.hash | dates.js:54:36:54:68 | window. ... ring(1) |
882+
| dates.js:54:36:54:68 | window. ... ring(1) | dates.js:54:17:54:69 | decodeU ... ing(1)) |
883+
| dates.js:57:42:57:99 | moment. ... (taint) | dates.js:57:31:57:101 | `Time i ... aint)}` |
884+
| dates.js:57:42:57:99 | moment. ... (taint) | dates.js:57:31:57:101 | `Time i ... aint)}` |
885+
| dates.js:57:94:57:98 | taint | dates.js:57:42:57:99 | moment. ... (taint) |
886+
| dates.js:59:42:59:85 | luxon.e ... (taint) | dates.js:59:31:59:87 | `Time i ... aint)}` |
887+
| dates.js:59:42:59:85 | luxon.e ... (taint) | dates.js:59:31:59:87 | `Time i ... aint)}` |
888+
| dates.js:59:80:59:84 | taint | dates.js:59:42:59:85 | luxon.e ... (taint) |
889+
| dates.js:61:42:61:86 | dayjs.s ... (taint) | dates.js:61:31:61:88 | `Time i ... aint)}` |
890+
| dates.js:61:42:61:86 | dayjs.s ... (taint) | dates.js:61:31:61:88 | `Time i ... aint)}` |
891+
| dates.js:61:81:61:85 | taint | dates.js:61:42:61:86 | dayjs.s ... (taint) |
859892
| event-handler-receiver.js:2:49:2:61 | location.href | event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
860893
| event-handler-receiver.js:2:49:2:61 | location.href | event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
861894
| event-handler-receiver.js:2:49:2:61 | location.href | event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
@@ -1375,6 +1408,9 @@ edges
13751408
| dates.js:48:31:48:90 | `Time i ... aint)}` | dates.js:46:36:46:55 | window.location.hash | dates.js:48:31:48:90 | `Time i ... aint)}` | Cross-site scripting vulnerability due to $@. | dates.js:46:36:46:55 | window.location.hash | user-provided value |
13761409
| dates.js:49:31:49:89 | `Time i ... aint)}` | dates.js:46:36:46:55 | window.location.hash | dates.js:49:31:49:89 | `Time i ... aint)}` | Cross-site scripting vulnerability due to $@. | dates.js:46:36:46:55 | window.location.hash | user-provided value |
13771410
| dates.js:50:31:50:104 | `Time i ... aint)}` | dates.js:46:36:46:55 | window.location.hash | dates.js:50:31:50:104 | `Time i ... aint)}` | Cross-site scripting vulnerability due to $@. | dates.js:46:36:46:55 | window.location.hash | user-provided value |
1411+
| dates.js:57:31:57:101 | `Time i ... aint)}` | dates.js:54:36:54:55 | window.location.hash | dates.js:57:31:57:101 | `Time i ... aint)}` | Cross-site scripting vulnerability due to $@. | dates.js:54:36:54:55 | window.location.hash | user-provided value |
1412+
| dates.js:59:31:59:87 | `Time i ... aint)}` | dates.js:54:36:54:55 | window.location.hash | dates.js:59:31:59:87 | `Time i ... aint)}` | Cross-site scripting vulnerability due to $@. | dates.js:54:36:54:55 | window.location.hash | user-provided value |
1413+
| dates.js:61:31:61:88 | `Time i ... aint)}` | dates.js:54:36:54:55 | window.location.hash | dates.js:61:31:61:88 | `Time i ... aint)}` | Cross-site scripting vulnerability due to $@. | dates.js:54:36:54:55 | window.location.hash | user-provided value |
13781414
| 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 |
13791415
| 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 |
13801416
| 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: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,23 @@ nodes
168168
| dates.js:50:31:50:104 | `Time i ... aint)}` |
169169
| dates.js:50:42:50:102 | DateTim ... (taint) |
170170
| dates.js:50:97:50:101 | taint |
171+
| dates.js:54:9:54:69 | taint |
172+
| dates.js:54:17:54:69 | decodeU ... ing(1)) |
173+
| dates.js:54:36:54:55 | window.location.hash |
174+
| dates.js:54:36:54:55 | window.location.hash |
175+
| dates.js:54:36:54:68 | window. ... ring(1) |
176+
| dates.js:57:31:57:101 | `Time i ... aint)}` |
177+
| dates.js:57:31:57:101 | `Time i ... aint)}` |
178+
| dates.js:57:42:57:99 | moment. ... (taint) |
179+
| dates.js:57:94:57:98 | taint |
180+
| dates.js:59:31:59:87 | `Time i ... aint)}` |
181+
| dates.js:59:31:59:87 | `Time i ... aint)}` |
182+
| dates.js:59:42:59:85 | luxon.e ... (taint) |
183+
| dates.js:59:80:59:84 | taint |
184+
| dates.js:61:31:61:88 | `Time i ... aint)}` |
185+
| dates.js:61:31:61:88 | `Time i ... aint)}` |
186+
| dates.js:61:42:61:86 | dayjs.s ... (taint) |
187+
| dates.js:61:81:61:85 | taint |
171188
| event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
172189
| event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
173190
| event-handler-receiver.js:2:49:2:61 | location.href |
@@ -874,6 +891,22 @@ edges
874891
| dates.js:50:42:50:102 | DateTim ... (taint) | dates.js:50:31:50:104 | `Time i ... aint)}` |
875892
| dates.js:50:42:50:102 | DateTim ... (taint) | dates.js:50:31:50:104 | `Time i ... aint)}` |
876893
| dates.js:50:97:50:101 | taint | dates.js:50:42:50:102 | DateTim ... (taint) |
894+
| dates.js:54:9:54:69 | taint | dates.js:57:94:57:98 | taint |
895+
| dates.js:54:9:54:69 | taint | dates.js:59:80:59:84 | taint |
896+
| dates.js:54:9:54:69 | taint | dates.js:61:81:61:85 | taint |
897+
| dates.js:54:17:54:69 | decodeU ... ing(1)) | dates.js:54:9:54:69 | taint |
898+
| dates.js:54:36:54:55 | window.location.hash | dates.js:54:36:54:68 | window. ... ring(1) |
899+
| dates.js:54:36:54:55 | window.location.hash | dates.js:54:36:54:68 | window. ... ring(1) |
900+
| dates.js:54:36:54:68 | window. ... ring(1) | dates.js:54:17:54:69 | decodeU ... ing(1)) |
901+
| dates.js:57:42:57:99 | moment. ... (taint) | dates.js:57:31:57:101 | `Time i ... aint)}` |
902+
| dates.js:57:42:57:99 | moment. ... (taint) | dates.js:57:31:57:101 | `Time i ... aint)}` |
903+
| dates.js:57:94:57:98 | taint | dates.js:57:42:57:99 | moment. ... (taint) |
904+
| dates.js:59:42:59:85 | luxon.e ... (taint) | dates.js:59:31:59:87 | `Time i ... aint)}` |
905+
| dates.js:59:42:59:85 | luxon.e ... (taint) | dates.js:59:31:59:87 | `Time i ... aint)}` |
906+
| dates.js:59:80:59:84 | taint | dates.js:59:42:59:85 | luxon.e ... (taint) |
907+
| dates.js:61:42:61:86 | dayjs.s ... (taint) | dates.js:61:31:61:88 | `Time i ... aint)}` |
908+
| dates.js:61:42:61:86 | dayjs.s ... (taint) | dates.js:61:31:61:88 | `Time i ... aint)}` |
909+
| dates.js:61:81:61:85 | taint | dates.js:61:42:61:86 | dayjs.s ... (taint) |
877910
| event-handler-receiver.js:2:49:2:61 | location.href | event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
878911
| event-handler-receiver.js:2:49:2:61 | location.href | event-handler-receiver.js:2:31:2:83 | '<h2><a ... ></h2>' |
879912
| 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: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,13 @@ function luxon() {
5050
document.body.innerHTML = `Time is ${DateTime.fromISO("2020-01-01").startOf('day').toFormat(taint)}`; // NOT OK
5151
}
5252

53+
function dateio2() {
54+
let taint = decodeURIComponent(window.location.hash.substring(1));
55+
56+
const moment = new MomentAdapter();
57+
document.body.innerHTML = `Time is ${moment.addDays(moment.date("2020-06-21"), 1).format(taint)}`; // NOT OK
58+
const luxon = new LuxonAdapter();
59+
document.body.innerHTML = `Time is ${luxon.endOfDay(luxon.date()).toFormat(taint)}`; // NOT OK
60+
const dayjs = new DayJSAdapter();
61+
document.body.innerHTML = `Time is ${dayjs.setHours(dayjs.date(), 4).format(taint)}`; // NOT OK
62+
}

0 commit comments

Comments
 (0)