mirror of
https://github.com/github/codeql.git
synced 2026-04-30 03:05:15 +02:00
Merge pull request #4567 from asgerf/js/date-functions
Approved by erik-krogh
This commit is contained in:
@@ -79,6 +79,7 @@ import semmle.javascript.frameworks.ClosureLibrary
|
||||
import semmle.javascript.frameworks.CookieLibraries
|
||||
import semmle.javascript.frameworks.Credentials
|
||||
import semmle.javascript.frameworks.CryptoLibraries
|
||||
import semmle.javascript.frameworks.DateFunctions
|
||||
import semmle.javascript.frameworks.DigitalOcean
|
||||
import semmle.javascript.frameworks.Electron
|
||||
import semmle.javascript.frameworks.EventEmitter
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/** Provides taint steps modeling flow through date-manipulation libraries. */
|
||||
|
||||
private import javascript
|
||||
|
||||
private module DateFns {
|
||||
private API::Node formatFunction() {
|
||||
result = API::moduleImport(["date-fns", "date-fns/esm"]).getMember(["format", "lightFormat"])
|
||||
or
|
||||
result =
|
||||
API::moduleImport(["date-fns/format", "date-fns/lightFormat", "date-fns/esm/format",
|
||||
"date-fns/esm/lightFormat"])
|
||||
}
|
||||
|
||||
private API::Node curriedFormatFunction() {
|
||||
result =
|
||||
API::moduleImport(["date-fns/fp", "date-fns/esm/fp"]).getMember(["format", "lightFormat"])
|
||||
or
|
||||
result =
|
||||
API::moduleImport(["date-fns/fp/format", "date-fns/fp/lightFormat", "date-fns/esm/fp/format",
|
||||
"date-fns/esm/fp/lightFormat"])
|
||||
}
|
||||
|
||||
/**
|
||||
* Taint step of form: `f -> format(date, f)`
|
||||
*
|
||||
* A format string can use single-quotes to include mostly arbitrary text.
|
||||
*/
|
||||
private class FormatStep extends TaintTracking::AdditionalTaintStep, DataFlow::CallNode {
|
||||
FormatStep() { this = formatFunction().getACall() }
|
||||
|
||||
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
pred = getArgument(1) and
|
||||
succ = this
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Taint step of form: `f -> format(f)(date)`
|
||||
*/
|
||||
private class CurriedFormatStep extends TaintTracking::AdditionalTaintStep, DataFlow::CallNode {
|
||||
CurriedFormatStep() { this = curriedFormatFunction().getACall() }
|
||||
|
||||
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
pred = getArgument(0) and
|
||||
succ = getACall()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private module Moment {
|
||||
/** Gets a reference to a `moment` object. */
|
||||
private API::Node moment() {
|
||||
result = API::moduleImport(["moment", "moment-timezone"])
|
||||
or
|
||||
result = moment().getReturn()
|
||||
or
|
||||
result = moment().getAMember()
|
||||
}
|
||||
|
||||
/**
|
||||
* Taint step of form: `f -> momentObj.format(f)`
|
||||
*
|
||||
* The format string can use backslash-escaping to include mostly arbitrary text.
|
||||
*/
|
||||
private class MomentFormatStep extends TaintTracking::AdditionalTaintStep, DataFlow::CallNode {
|
||||
MomentFormatStep() { this = moment().getMember("format").getACall() }
|
||||
|
||||
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
pred = getArgument(0) and
|
||||
succ = this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private module DateFormat {
|
||||
/**
|
||||
* Taint step of form: `x -> dateformat(..., x)`
|
||||
*
|
||||
* The format string can use single-quotes to include mostly arbitrary text.
|
||||
*/
|
||||
private class DateFormatStep extends TaintTracking::AdditionalTaintStep, DataFlow::CallNode {
|
||||
DateFormatStep() { this = DataFlow::moduleImport("dateformat").getACall() }
|
||||
|
||||
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
pred = getArgument(1) and
|
||||
succ = this
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,6 +89,32 @@ nodes
|
||||
| classnames.js:15:47:15:63 | clsx(window.name) |
|
||||
| classnames.js:15:52:15:62 | window.name |
|
||||
| classnames.js:15:52:15:62 | window.name |
|
||||
| dates.js:9:9:9:69 | taint |
|
||||
| dates.js:9:17:9:69 | decodeU ... ing(1)) |
|
||||
| dates.js:9:36:9:50 | window.location |
|
||||
| dates.js:9:36:9:50 | window.location |
|
||||
| dates.js:9:36:9:55 | window.location.hash |
|
||||
| dates.js:9:36:9:68 | window. ... ring(1) |
|
||||
| dates.js:11:31:11:70 | `Time i ... aint)}` |
|
||||
| dates.js:11:31:11:70 | `Time i ... aint)}` |
|
||||
| dates.js:11:42:11:68 | dateFns ... taint) |
|
||||
| dates.js:11:63:11:67 | taint |
|
||||
| dates.js:12:31:12:73 | `Time i ... aint)}` |
|
||||
| dates.js:12:31:12:73 | `Time i ... aint)}` |
|
||||
| dates.js:12:42:12:71 | dateFns ... taint) |
|
||||
| dates.js:12:66:12:70 | taint |
|
||||
| dates.js:13:31:13:72 | `Time i ... time)}` |
|
||||
| dates.js:13:31:13:72 | `Time i ... time)}` |
|
||||
| dates.js:13:42:13:70 | dateFns ... )(time) |
|
||||
| dates.js:13:59:13:63 | taint |
|
||||
| dates.js:16:31:16:69 | `Time i ... aint)}` |
|
||||
| dates.js:16:31:16:69 | `Time i ... aint)}` |
|
||||
| dates.js:16:42:16:67 | moment( ... (taint) |
|
||||
| dates.js:16:62:16:66 | taint |
|
||||
| dates.js:18:31:18:66 | `Time i ... aint)}` |
|
||||
| dates.js:18:31:18:66 | `Time i ... aint)}` |
|
||||
| dates.js:18:42:18:64 | datefor ... taint) |
|
||||
| dates.js:18:59:18:63 | taint |
|
||||
| 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") |
|
||||
@@ -688,6 +714,31 @@ edges
|
||||
| classnames.js:15:47:15:63 | clsx(window.name) | classnames.js:15:31:15:78 | `<span ... <span>` |
|
||||
| classnames.js:15:52:15:62 | window.name | classnames.js:15:47:15:63 | clsx(window.name) |
|
||||
| classnames.js:15:52:15:62 | window.name | classnames.js:15:47:15:63 | clsx(window.name) |
|
||||
| dates.js:9:9:9:69 | taint | dates.js:11:63:11:67 | taint |
|
||||
| dates.js:9:9:9:69 | taint | dates.js:12:66:12:70 | taint |
|
||||
| dates.js:9:9:9:69 | taint | dates.js:13:59:13:63 | taint |
|
||||
| dates.js:9:9:9:69 | taint | dates.js:16:62:16:66 | taint |
|
||||
| dates.js:9:9:9:69 | taint | dates.js:18:59:18:63 | taint |
|
||||
| dates.js:9:17:9:69 | decodeU ... ing(1)) | dates.js:9:9:9:69 | taint |
|
||||
| dates.js:9:36:9:50 | window.location | dates.js:9:36:9:55 | window.location.hash |
|
||||
| dates.js:9:36:9:50 | window.location | dates.js:9:36:9:55 | window.location.hash |
|
||||
| dates.js:9:36:9:55 | window.location.hash | dates.js:9:36:9:68 | window. ... ring(1) |
|
||||
| dates.js:9:36:9:68 | window. ... ring(1) | dates.js:9:17:9:69 | decodeU ... ing(1)) |
|
||||
| dates.js:11:42:11:68 | dateFns ... taint) | dates.js:11:31:11:70 | `Time i ... aint)}` |
|
||||
| dates.js:11:42:11:68 | dateFns ... taint) | dates.js:11:31:11:70 | `Time i ... aint)}` |
|
||||
| dates.js:11:63:11:67 | taint | dates.js:11:42:11:68 | dateFns ... taint) |
|
||||
| dates.js:12:42:12:71 | dateFns ... taint) | dates.js:12:31:12:73 | `Time i ... aint)}` |
|
||||
| dates.js:12:42:12:71 | dateFns ... taint) | dates.js:12:31:12:73 | `Time i ... aint)}` |
|
||||
| dates.js:12:66:12:70 | taint | dates.js:12:42:12:71 | dateFns ... taint) |
|
||||
| dates.js:13:42:13:70 | dateFns ... )(time) | dates.js:13:31:13:72 | `Time i ... time)}` |
|
||||
| dates.js:13:42:13:70 | dateFns ... )(time) | dates.js:13:31:13:72 | `Time i ... time)}` |
|
||||
| dates.js:13:59:13:63 | taint | dates.js:13:42:13:70 | dateFns ... )(time) |
|
||||
| dates.js:16:42:16:67 | moment( ... (taint) | dates.js:16:31:16:69 | `Time i ... aint)}` |
|
||||
| dates.js:16:42:16:67 | moment( ... (taint) | dates.js:16:31:16:69 | `Time i ... aint)}` |
|
||||
| dates.js:16:62:16:66 | taint | dates.js:16:42:16:67 | moment( ... (taint) |
|
||||
| dates.js:18:42:18:64 | datefor ... taint) | dates.js:18:31:18:66 | `Time i ... aint)}` |
|
||||
| dates.js:18:42:18:64 | datefor ... taint) | dates.js:18:31:18:66 | `Time i ... aint)}` |
|
||||
| dates.js:18:59:18:63 | taint | dates.js:18:42:18:64 | datefor ... taint) |
|
||||
| express.js:7:15:7:33 | req.param("wobble") | express.js:7:15:7:33 | req.param("wobble") |
|
||||
| jquery.js:2:7:2:40 | tainted | jquery.js:7:20:7:26 | tainted |
|
||||
| jquery.js:2:7:2:40 | tainted | jquery.js:8:28:8:34 | tainted |
|
||||
@@ -1179,6 +1230,11 @@ edges
|
||||
| classnames.js:11:31:11:79 | `<span ... <span>` | classnames.js:10:45:10:55 | window.name | classnames.js:11:31:11:79 | `<span ... <span>` | Cross-site scripting vulnerability due to $@. | classnames.js:10:45:10:55 | window.name | user-provided value |
|
||||
| classnames.js:13:31:13:83 | `<span ... <span>` | classnames.js:13:57:13:67 | window.name | classnames.js:13:31:13:83 | `<span ... <span>` | Cross-site scripting vulnerability due to $@. | classnames.js:13:57:13:67 | window.name | user-provided value |
|
||||
| classnames.js:15:31:15:78 | `<span ... <span>` | classnames.js:15:52:15:62 | window.name | classnames.js:15:31:15:78 | `<span ... <span>` | Cross-site scripting vulnerability due to $@. | classnames.js:15:52:15:62 | window.name | user-provided value |
|
||||
| dates.js:11:31:11:70 | `Time i ... aint)}` | dates.js:9:36:9:50 | window.location | dates.js:11:31:11:70 | `Time i ... aint)}` | Cross-site scripting vulnerability due to $@. | dates.js:9:36:9:50 | window.location | user-provided value |
|
||||
| dates.js:12:31:12:73 | `Time i ... aint)}` | dates.js:9:36:9:50 | window.location | dates.js:12:31:12:73 | `Time i ... aint)}` | Cross-site scripting vulnerability due to $@. | dates.js:9:36:9:50 | window.location | user-provided value |
|
||||
| dates.js:13:31:13:72 | `Time i ... time)}` | dates.js:9:36:9:50 | window.location | dates.js:13:31:13:72 | `Time i ... time)}` | Cross-site scripting vulnerability due to $@. | dates.js:9:36:9:50 | window.location | user-provided value |
|
||||
| dates.js:16:31:16:69 | `Time i ... aint)}` | dates.js:9:36:9:50 | window.location | dates.js:16:31:16:69 | `Time i ... aint)}` | Cross-site scripting vulnerability due to $@. | dates.js:9:36:9:50 | window.location | user-provided value |
|
||||
| dates.js:18:31:18:66 | `Time i ... aint)}` | dates.js:9:36:9:50 | window.location | dates.js:18:31:18:66 | `Time i ... aint)}` | Cross-site scripting vulnerability due to $@. | dates.js:9:36:9:50 | window.location | user-provided value |
|
||||
| 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 |
|
||||
| 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 |
|
||||
| jquery.js:8:18:8:34 | "XSS: " + tainted | jquery.js:2:17:2:33 | document.location | jquery.js:8:18:8:34 | "XSS: " + tainted | Cross-site scripting vulnerability due to $@. | jquery.js:2:17:2:33 | document.location | user-provided value |
|
||||
|
||||
@@ -89,6 +89,32 @@ nodes
|
||||
| classnames.js:15:47:15:63 | clsx(window.name) |
|
||||
| classnames.js:15:52:15:62 | window.name |
|
||||
| classnames.js:15:52:15:62 | window.name |
|
||||
| dates.js:9:9:9:69 | taint |
|
||||
| dates.js:9:17:9:69 | decodeU ... ing(1)) |
|
||||
| dates.js:9:36:9:50 | window.location |
|
||||
| dates.js:9:36:9:50 | window.location |
|
||||
| dates.js:9:36:9:55 | window.location.hash |
|
||||
| dates.js:9:36:9:68 | window. ... ring(1) |
|
||||
| dates.js:11:31:11:70 | `Time i ... aint)}` |
|
||||
| dates.js:11:31:11:70 | `Time i ... aint)}` |
|
||||
| dates.js:11:42:11:68 | dateFns ... taint) |
|
||||
| dates.js:11:63:11:67 | taint |
|
||||
| dates.js:12:31:12:73 | `Time i ... aint)}` |
|
||||
| dates.js:12:31:12:73 | `Time i ... aint)}` |
|
||||
| dates.js:12:42:12:71 | dateFns ... taint) |
|
||||
| dates.js:12:66:12:70 | taint |
|
||||
| dates.js:13:31:13:72 | `Time i ... time)}` |
|
||||
| dates.js:13:31:13:72 | `Time i ... time)}` |
|
||||
| dates.js:13:42:13:70 | dateFns ... )(time) |
|
||||
| dates.js:13:59:13:63 | taint |
|
||||
| dates.js:16:31:16:69 | `Time i ... aint)}` |
|
||||
| dates.js:16:31:16:69 | `Time i ... aint)}` |
|
||||
| dates.js:16:42:16:67 | moment( ... (taint) |
|
||||
| dates.js:16:62:16:66 | taint |
|
||||
| dates.js:18:31:18:66 | `Time i ... aint)}` |
|
||||
| dates.js:18:31:18:66 | `Time i ... aint)}` |
|
||||
| dates.js:18:42:18:64 | datefor ... taint) |
|
||||
| dates.js:18:59:18:63 | taint |
|
||||
| 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") |
|
||||
@@ -692,6 +718,31 @@ edges
|
||||
| classnames.js:15:47:15:63 | clsx(window.name) | classnames.js:15:31:15:78 | `<span ... <span>` |
|
||||
| classnames.js:15:52:15:62 | window.name | classnames.js:15:47:15:63 | clsx(window.name) |
|
||||
| classnames.js:15:52:15:62 | window.name | classnames.js:15:47:15:63 | clsx(window.name) |
|
||||
| dates.js:9:9:9:69 | taint | dates.js:11:63:11:67 | taint |
|
||||
| dates.js:9:9:9:69 | taint | dates.js:12:66:12:70 | taint |
|
||||
| dates.js:9:9:9:69 | taint | dates.js:13:59:13:63 | taint |
|
||||
| dates.js:9:9:9:69 | taint | dates.js:16:62:16:66 | taint |
|
||||
| dates.js:9:9:9:69 | taint | dates.js:18:59:18:63 | taint |
|
||||
| dates.js:9:17:9:69 | decodeU ... ing(1)) | dates.js:9:9:9:69 | taint |
|
||||
| dates.js:9:36:9:50 | window.location | dates.js:9:36:9:55 | window.location.hash |
|
||||
| dates.js:9:36:9:50 | window.location | dates.js:9:36:9:55 | window.location.hash |
|
||||
| dates.js:9:36:9:55 | window.location.hash | dates.js:9:36:9:68 | window. ... ring(1) |
|
||||
| dates.js:9:36:9:68 | window. ... ring(1) | dates.js:9:17:9:69 | decodeU ... ing(1)) |
|
||||
| dates.js:11:42:11:68 | dateFns ... taint) | dates.js:11:31:11:70 | `Time i ... aint)}` |
|
||||
| dates.js:11:42:11:68 | dateFns ... taint) | dates.js:11:31:11:70 | `Time i ... aint)}` |
|
||||
| dates.js:11:63:11:67 | taint | dates.js:11:42:11:68 | dateFns ... taint) |
|
||||
| dates.js:12:42:12:71 | dateFns ... taint) | dates.js:12:31:12:73 | `Time i ... aint)}` |
|
||||
| dates.js:12:42:12:71 | dateFns ... taint) | dates.js:12:31:12:73 | `Time i ... aint)}` |
|
||||
| dates.js:12:66:12:70 | taint | dates.js:12:42:12:71 | dateFns ... taint) |
|
||||
| dates.js:13:42:13:70 | dateFns ... )(time) | dates.js:13:31:13:72 | `Time i ... time)}` |
|
||||
| dates.js:13:42:13:70 | dateFns ... )(time) | dates.js:13:31:13:72 | `Time i ... time)}` |
|
||||
| dates.js:13:59:13:63 | taint | dates.js:13:42:13:70 | dateFns ... )(time) |
|
||||
| dates.js:16:42:16:67 | moment( ... (taint) | dates.js:16:31:16:69 | `Time i ... aint)}` |
|
||||
| dates.js:16:42:16:67 | moment( ... (taint) | dates.js:16:31:16:69 | `Time i ... aint)}` |
|
||||
| dates.js:16:62:16:66 | taint | dates.js:16:42:16:67 | moment( ... (taint) |
|
||||
| dates.js:18:42:18:64 | datefor ... taint) | dates.js:18:31:18:66 | `Time i ... aint)}` |
|
||||
| dates.js:18:42:18:64 | datefor ... taint) | dates.js:18:31:18:66 | `Time i ... aint)}` |
|
||||
| dates.js:18:59:18:63 | taint | dates.js:18:42:18:64 | datefor ... taint) |
|
||||
| express.js:7:15:7:33 | req.param("wobble") | express.js:7:15:7:33 | req.param("wobble") |
|
||||
| jquery.js:2:7:2:40 | tainted | jquery.js:7:20:7:26 | tainted |
|
||||
| jquery.js:2:7:2:40 | tainted | jquery.js:8:28:8:34 | tainted |
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import dateFns from 'date-fns';
|
||||
import dateFnsFp from 'date-fns/fp';
|
||||
import dateFnsEsm from 'date-fns/esm';
|
||||
import moment from 'moment';
|
||||
import dateformat from 'dateformat';
|
||||
|
||||
function main() {
|
||||
let time = new Date();
|
||||
let taint = decodeURIComponent(window.location.hash.substring(1));
|
||||
|
||||
document.body.innerHTML = `Time is ${dateFns.format(time, taint)}`; // NOT OK
|
||||
document.body.innerHTML = `Time is ${dateFnsEsm.format(time, taint)}`; // NOT OK
|
||||
document.body.innerHTML = `Time is ${dateFnsFp.format(taint)(time)}`; // NOT OK
|
||||
document.body.innerHTML = `Time is ${dateFns.format(taint, time)}`; // OK - time arg is safe
|
||||
document.body.innerHTML = `Time is ${dateFnsFp.format(time)(taint)}`; // OK - time arg is safe
|
||||
document.body.innerHTML = `Time is ${moment(time).format(taint)}`; // NOT OK
|
||||
document.body.innerHTML = `Time is ${moment(taint).format()}`; // OK
|
||||
document.body.innerHTML = `Time is ${dateformat(time, taint)}`; // NOT OK
|
||||
}
|
||||
Reference in New Issue
Block a user