Merge pull request #4567 from asgerf/js/date-functions

Approved by erik-krogh
This commit is contained in:
CodeQL CI
2020-11-11 11:17:30 +00:00
committed by GitHub
6 changed files with 223 additions and 0 deletions

View File

@@ -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

View File

@@ -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
}
}
}

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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
}