add support for the prettier API

This commit is contained in:
Erik Krogh Kristensen
2021-06-02 15:33:08 +02:00
parent 348fab82fd
commit 788c5ba701
7 changed files with 131 additions and 0 deletions

View File

@@ -104,6 +104,7 @@ import semmle.javascript.frameworks.Nest
import semmle.javascript.frameworks.Next
import semmle.javascript.frameworks.NoSQL
import semmle.javascript.frameworks.PkgCloud
import semmle.javascript.frameworks.Prettier
import semmle.javascript.frameworks.PropertyProjection
import semmle.javascript.frameworks.Puppeteer
import semmle.javascript.frameworks.React

View File

@@ -0,0 +1,52 @@
/**
* Provides classes and predicates for working with the [prettier](https://www.npmjs.com/package/prettier) library.
*/
import javascript
/** Provides classes and predicates modelling aspects of the [prettier](https://www.npmjs.com/package/prettier) library. */
private module Prettier {
/**
* A taint step from the [prettier API](https://prettier.io/docs/en/api.html).
*/
private class PrettierTaintStep extends TaintTracking::SharedTaintStep {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
exists(API::CallNode call |
call = API::moduleImport("prettier").getMember("format").getACall()
|
pred = call.getArgument(0) and
succ = call
)
or
exists(API::CallNode call |
call = API::moduleImport("prettier").getMember("formatWithCursor").getACall()
|
pred = call.getArgument(0) and
succ = call.getReturn().getMember("formatted").getAnImmediateUse()
)
}
}
private import semmle.javascript.security.dataflow.TaintedPathCustomizations::TaintedPath as TaintedPath
/**
* An argument given to the `prettier` library specificing the location of a config file.
*/
private class PrettierFileSink extends TaintedPath::Sink {
PrettierFileSink() {
this =
API::moduleImport("prettier")
.getMember(["resolveConfig", "resolveConfigFile", "getFileInfo"])
.getACall()
.getArgument(0)
or
this =
API::moduleImport("prettier")
.getMember("resolveConfig")
.getACall()
.getParameter(1)
.getMember("config")
.getARhs()
}
}
}

View File

@@ -2271,6 +2271,25 @@ nodes
| other-fs-libraries.js:52:24:52:27 | path |
| other-fs-libraries.js:52:24:52:27 | path |
| other-fs-libraries.js:52:24:52:27 | path |
| prettier.js:6:11:6:28 | p |
| prettier.js:6:11:6:28 | p |
| prettier.js:6:11:6:28 | p |
| prettier.js:6:11:6:28 | p |
| prettier.js:6:13:6:13 | p |
| prettier.js:6:13:6:13 | p |
| prettier.js:6:13:6:13 | p |
| prettier.js:6:13:6:13 | p |
| prettier.js:6:13:6:13 | p |
| prettier.js:7:28:7:28 | p |
| prettier.js:7:28:7:28 | p |
| prettier.js:7:28:7:28 | p |
| prettier.js:7:28:7:28 | p |
| prettier.js:7:28:7:28 | p |
| prettier.js:11:44:11:44 | p |
| prettier.js:11:44:11:44 | p |
| prettier.js:11:44:11:44 | p |
| prettier.js:11:44:11:44 | p |
| prettier.js:11:44:11:44 | p |
| pupeteer.js:5:9:5:71 | tainted |
| pupeteer.js:5:9:5:71 | tainted |
| pupeteer.js:5:9:5:71 | tainted |
@@ -6668,6 +6687,30 @@ edges
| other-fs-libraries.js:49:24:49:30 | req.url | other-fs-libraries.js:49:14:49:37 | url.par ... , true) |
| other-fs-libraries.js:49:24:49:30 | req.url | other-fs-libraries.js:49:14:49:37 | url.par ... , true) |
| other-fs-libraries.js:49:24:49:30 | req.url | other-fs-libraries.js:49:14:49:37 | url.par ... , true) |
| prettier.js:6:11:6:28 | p | prettier.js:7:28:7:28 | p |
| prettier.js:6:11:6:28 | p | prettier.js:7:28:7:28 | p |
| prettier.js:6:11:6:28 | p | prettier.js:7:28:7:28 | p |
| prettier.js:6:11:6:28 | p | prettier.js:7:28:7:28 | p |
| prettier.js:6:11:6:28 | p | prettier.js:7:28:7:28 | p |
| prettier.js:6:11:6:28 | p | prettier.js:7:28:7:28 | p |
| prettier.js:6:11:6:28 | p | prettier.js:7:28:7:28 | p |
| prettier.js:6:11:6:28 | p | prettier.js:7:28:7:28 | p |
| prettier.js:6:11:6:28 | p | prettier.js:11:44:11:44 | p |
| prettier.js:6:11:6:28 | p | prettier.js:11:44:11:44 | p |
| prettier.js:6:11:6:28 | p | prettier.js:11:44:11:44 | p |
| prettier.js:6:11:6:28 | p | prettier.js:11:44:11:44 | p |
| prettier.js:6:11:6:28 | p | prettier.js:11:44:11:44 | p |
| prettier.js:6:11:6:28 | p | prettier.js:11:44:11:44 | p |
| prettier.js:6:11:6:28 | p | prettier.js:11:44:11:44 | p |
| prettier.js:6:11:6:28 | p | prettier.js:11:44:11:44 | p |
| prettier.js:6:13:6:13 | p | prettier.js:6:11:6:28 | p |
| prettier.js:6:13:6:13 | p | prettier.js:6:11:6:28 | p |
| prettier.js:6:13:6:13 | p | prettier.js:6:11:6:28 | p |
| prettier.js:6:13:6:13 | p | prettier.js:6:11:6:28 | p |
| prettier.js:6:13:6:13 | p | prettier.js:6:11:6:28 | p |
| prettier.js:6:13:6:13 | p | prettier.js:6:11:6:28 | p |
| prettier.js:6:13:6:13 | p | prettier.js:6:11:6:28 | p |
| prettier.js:6:13:6:13 | p | prettier.js:6:11:6:28 | p |
| pupeteer.js:5:9:5:71 | tainted | pupeteer.js:9:28:9:34 | tainted |
| pupeteer.js:5:9:5:71 | tainted | pupeteer.js:9:28:9:34 | tainted |
| pupeteer.js:5:9:5:71 | tainted | pupeteer.js:9:28:9:34 | tainted |
@@ -8295,6 +8338,8 @@ edges
| other-fs-libraries.js:42:53:42:56 | path | other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:42:53:42:56 | path | This path depends on $@. | other-fs-libraries.js:38:24:38:30 | req.url | a user-provided value |
| other-fs-libraries.js:51:19:51:22 | path | other-fs-libraries.js:49:24:49:30 | req.url | other-fs-libraries.js:51:19:51:22 | path | This path depends on $@. | other-fs-libraries.js:49:24:49:30 | req.url | a user-provided value |
| other-fs-libraries.js:52:24:52:27 | path | other-fs-libraries.js:49:24:49:30 | req.url | other-fs-libraries.js:52:24:52:27 | path | This path depends on $@. | other-fs-libraries.js:49:24:49:30 | req.url | a user-provided value |
| prettier.js:7:28:7:28 | p | prettier.js:6:13:6:13 | p | prettier.js:7:28:7:28 | p | This path depends on $@. | prettier.js:6:13:6:13 | p | a user-provided value |
| prettier.js:11:44:11:44 | p | prettier.js:6:13:6:13 | p | prettier.js:11:44:11:44 | p | This path depends on $@. | prettier.js:6:13:6:13 | p | a user-provided value |
| pupeteer.js:9:28:9:34 | tainted | pupeteer.js:5:28:5:53 | parseTo ... t).name | pupeteer.js:9:28:9:34 | tainted | This path depends on $@. | pupeteer.js:5:28:5:53 | parseTo ... t).name | a user-provided value |
| pupeteer.js:13:37:13:43 | tainted | pupeteer.js:5:28:5:53 | parseTo ... t).name | pupeteer.js:13:37:13:43 | tainted | This path depends on $@. | pupeteer.js:5:28:5:53 | parseTo ... t).name | a user-provided value |
| tainted-access-paths.js:8:19:8:22 | path | tainted-access-paths.js:6:24:6:30 | req.url | tainted-access-paths.js:8:19:8:22 | path | This path depends on $@. | tainted-access-paths.js:6:24:6:30 | req.url | a user-provided value |

View File

@@ -0,0 +1,14 @@
const express = require('express');
const prettier = require("prettier");
const app = express();
app.get('/some/path', function (req, res) {
const { p } = req.params;
prettier.resolveConfig(p).then((options) => { // NOT OK
const formatted = prettier.format("foo", options);
});
prettier.resolveConfig("foo", {config: p}).then((options) => { // NOT OK
const formatted = prettier.format("bar", options);
});
});

View File

@@ -187,6 +187,12 @@ nodes
| tst3.js:5:9:5:9 | p |
| tst3.js:6:12:6:12 | p |
| tst3.js:6:12:6:12 | p |
| tst3.js:11:9:11:74 | code |
| tst3.js:11:16:11:74 | prettie ... bel" }) |
| tst3.js:11:32:11:39 | reg.body |
| tst3.js:11:32:11:39 | reg.body |
| tst3.js:12:12:12:15 | code |
| tst3.js:12:12:12:15 | code |
edges
| ReflectedXss.js:8:33:8:45 | req.params.id | ReflectedXss.js:8:14:8:45 | "Unknow ... rams.id |
| ReflectedXss.js:8:33:8:45 | req.params.id | ReflectedXss.js:8:14:8:45 | "Unknow ... rams.id |
@@ -342,6 +348,11 @@ edges
| tst3.js:5:7:5:24 | p | tst3.js:6:12:6:12 | p |
| tst3.js:5:9:5:9 | p | tst3.js:5:7:5:24 | p |
| tst3.js:5:9:5:9 | p | tst3.js:5:7:5:24 | p |
| tst3.js:11:9:11:74 | code | tst3.js:12:12:12:15 | code |
| tst3.js:11:9:11:74 | code | tst3.js:12:12:12:15 | code |
| tst3.js:11:16:11:74 | prettie ... bel" }) | tst3.js:11:9:11:74 | code |
| tst3.js:11:32:11:39 | reg.body | tst3.js:11:16:11:74 | prettie ... bel" }) |
| tst3.js:11:32:11:39 | reg.body | tst3.js:11:16:11:74 | prettie ... bel" }) |
#select
| ReflectedXss.js:8:14:8:45 | "Unknow ... rams.id | ReflectedXss.js:8:33:8:45 | req.params.id | ReflectedXss.js:8:14:8:45 | "Unknow ... rams.id | Cross-site scripting vulnerability due to $@. | ReflectedXss.js:8:33:8:45 | req.params.id | user-provided value |
| ReflectedXss.js:17:12:17:39 | "Unknow ... rams.id | ReflectedXss.js:17:31:17:39 | params.id | ReflectedXss.js:17:12:17:39 | "Unknow ... rams.id | Cross-site scripting vulnerability due to $@. | ReflectedXss.js:17:31:17:39 | params.id | user-provided value |
@@ -386,3 +397,4 @@ edges
| tst2.js:36:12:36:12 | p | tst2.js:30:9:30:9 | p | tst2.js:36:12:36:12 | p | Cross-site scripting vulnerability due to $@. | tst2.js:30:9:30:9 | p | user-provided value |
| tst2.js:37:12:37:18 | other.p | tst2.js:30:9:30:9 | p | tst2.js:37:12:37:18 | other.p | Cross-site scripting vulnerability due to $@. | tst2.js:30:9:30:9 | p | user-provided value |
| tst3.js:6:12:6:12 | p | tst3.js:5:9:5:9 | p | tst3.js:6:12:6:12 | p | Cross-site scripting vulnerability due to $@. | tst3.js:5:9:5:9 | p | user-provided value |
| tst3.js:12:12:12:15 | code | tst3.js:11:32:11:39 | reg.body | tst3.js:12:12:12:15 | code | Cross-site scripting vulnerability due to $@. | tst3.js:11:32:11:39 | reg.body | user-provided value |

View File

@@ -40,3 +40,4 @@
| tst2.js:36:12:36:12 | p | Cross-site scripting vulnerability due to $@. | tst2.js:30:9:30:9 | p | user-provided value |
| tst2.js:37:12:37:18 | other.p | Cross-site scripting vulnerability due to $@. | tst2.js:30:9:30:9 | p | user-provided value |
| tst3.js:6:12:6:12 | p | Cross-site scripting vulnerability due to $@. | tst3.js:5:9:5:9 | p | user-provided value |
| tst3.js:12:12:12:15 | code | Cross-site scripting vulnerability due to $@. | tst3.js:11:32:11:39 | reg.body | user-provided value |

View File

@@ -5,3 +5,9 @@ app.enable('x-powered-by').disable('x-powered-by').get('/', function (req, res)
let { p } = req.params;
res.send(p); // NOT OK
});
const prettier = require("prettier");
app.post("foobar", function (reg, res) {
const code = prettier.format(reg.body, { semi: false, parser: "babel" });
res.send(code); // NOT OK
});