This is an alternative presentation of the query from the blog post about [Detecting Reflected File Download vulnerabilities using QL](https://securitylab.github.com/research/etherpad-reflected-file-download/), phrasing it as a customization of Semmle's standard Reflected XSS query. Use [this snapshot](https://github.com/github/securitylab/releases/download/etherpad-vulnerable-codeql-database/Etherpad_1.6.2.zip) (etherpad-lite v1.6.2) for the initial stages of the development. All snapshots were built using version 1.9.3 of the Semmle toolchain; if you are using 1.20 or newer you will need to upgrade them. - [01_ReflectedXss.ql](01_ReflectedXss.ql): The standard query; finds nothing. The reason is that etherpad-lite uses [Swagger](https://www.npmjs.com/package/swagger-node-express) for implementing its REST API, which is not supported out of the box. The next few queries build up a basic model of Swagger that is rich enough to find the vulnerability. - [02_SwaggerRouteHandler.ql](02_SwaggerRouteHandler.ql): A query for finding places where Swagger is used to install an Express HTTP route handler. Note that the newly introduced class extends `Express::RouteHandler` from the standard library, so the standard HTTP server model can now be used to reason about Swagger-based APIs. - [03_ResponseSendArgument.ql](03_ResponseSendArgument.ql): A query for finding HTTP responses using the standard HTTP server model plus the extension developed in the previous query. Results are disappointing. - [04_ResponseSendAccess.ql](04_ResponseSendAccess.ql): To figure out what's going on, we instead just look for all references to the HTTP `send` method. The results show that etherpad-lite wraps that method and replaces it with a custom send method that ultimately delegates to the standard method. - [05_ResponseSendArgumentWithAliasing.ql](05_ResponseSendArgumentWithAliasing.ql): We can model this wrapping process, yielding an improved version of `03_ResponseSendArgument.ql`. - [06_ReflectedXss.ql](06_ReflectedXss.ql): Including all of the above extensions in the standard XSS query finds a true-positive result. This is the one we reported. The developers [fixed](https://github.com/ether/etherpad-lite/commit/a2992b3) the vulnerability by introducing a sanitizer using the [is-var-name](https://www.npmjs.com/package/is-var-name) npm package. [This snapshot](https://github.com/github/securitylab/releases/tag/etherpad-patched-codeql-database) corresponds to the fix commit. The standard library does not include a model for `is-var-name` (it is not a very widely used package), but [07_ReflectedXssWithSanitizer.ql](07_ReflectedXssWithSanitizer.ql) shows that it is very easy to add, making the result go away. Later on, this sanitizer was [replaced](https://github.com/ether/etherpad-lite/commit/dd7894d) with a custom sanitizer, which is, unfortunately, ineffective. ([This snapshot](https://github.com/github/securitylab/releases/download/etherpad-1.6.4-patched-codeql-database/Etherpad_1.6.4.zip) of etherpad-lite v1.6.4 contains the new sanitizer.) However, all browsers mitigate against reflected file download vulnerabilities these days, so while the vulnerability still exists, it is no longer exploitable.