Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
413 changes: 407 additions & 6 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,14 @@
"csv": "~5.3.2",
"csv-stringify": "~5.6.5",
"d3": "~7.8.5",
"dompurify": "~3.2.6",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The update to dompurify and jsdom is not reflected in the package-lock.json file. Since OED does not automatically update package-lock.json on install, it must be done as part of the changes. When I tried to do docker compose up with this version it failed due to this. This had been done for the previous addition in this PR. Thus, can you carefully update package-lock.json where it only does what is needed for the two updated packages (not a general npm install). Please let me know if you have questions or need help with this.

"dotenv": "~16.4.5",
"escape-html": "~1.0.3",
"express": "~4.19.2",
"express-rate-limit": "~7.2.0",
"history": "~5.3.0",
"ini": "~4.1.3",
"jsdom": "~26.1.0",
"jsonschema": "~1.4.1",
"jsonwebtoken": "~9.0.0",
"lodash": "~4.17.21",
Expand Down
2 changes: 1 addition & 1 deletion pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ Fixes #[issue]

## Limitations

(Describe any issues that remain or work that should still be done.)
(Describe any issues that remain or work that should still be done.)
31 changes: 15 additions & 16 deletions src/server/routes/response.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,31 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// Functions to return a code and comment from an Express request.
// Functions to return a code and comment from an Express request.

const DOMPurify = require('../services/utils/sanitizer');

/**
* Inform the client of a success (200 OK).
*
* @param res The Express response object
* @param comment Any additional data to be returned to the client as a string
* Inform the client of a success (200 OK) with sanitized content.
*
* @param {express.Response} res The Express response object.
* @param {string} comment Any additional data to be returned to the client as a string.
*/
function success(res, comment = '') {
res.status(200) // 200 OK
.send(comment);
function success(res, comment = '') {
const safeComment = DOMPurify.sanitize(comment);
res.status(200).send(safeComment);
}

/**
* Inform the client of a failure with provided code or 500.
*
* @param res The Express response object
* @param code The code number to send back for request
* @param comment Any additional data to be returned to the client as a string
* Inform the client of a failure with provided code or 500, using sanitized content.
*
* @param {express.Response} res The Express response object.
* @param {number} code The code number to send back for the request.
* @param {string} comment Any additional data to be returned to the client as a string.
*/
function failure(res, code = 500, comment = '') {
res.status(code)
.send(comment);

const safeComment = DOMPurify.sanitize(comment);
res.status(code).send(safeComment);
}

module.exports = { success, failure };
34 changes: 16 additions & 18 deletions src/server/services/csvPipeline/success.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,33 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

const express = require('express') /* needed to resolve types in JSDoc comments */
const express = require('express');
const DOMPurify = require('../utils/sanitizer');

/**
* Inform the client of a success (200 OK).
* Inform the client of a success (200 OK) with sanitized HTML content.
*
* @param {express.Request} req The Express request object
* @param {express.Response} res The Express response object
* @param {express.Request} req The Express request object.
* @param {express.Response} res The Express response object.
* @param {string} comment Any additional data to be returned to the client.
*
*/
function success(req, res, comment = '') {
res.status(200) // 200 OK
.send(`<h1>SUCCESS</h1>${comment}`);
const safeComment = DOMPurify.sanitize(comment);
res.status(200).send(`<h1>SUCCESS</h1>${safeComment}`);
}


/**
* Inform the client of a failure (400 OK).
* Inform the client of a failure (400 OK) with sanitized HTML content.
*
* @param {express.Request} req The Express request object
* @param {express.Response} res The Express response object
* @param {express.Request} req The Express request object.
* @param {express.Response} res The Express response object.
* @param {string} comment Any additional data to be returned to the client.
*
*/
function failure(req, res, comment = '') {
// 400 is client error. There is a small chance the insert into the DB failed
// but overlooking that.
res.status(400)
.send(`<h1>FAILURE</h1>${comment}`);

const safeComment = DOMPurify.sanitize(comment);
// 400 is client error. There is a small chance the insert into the DB failed
// but overlooking that.
res.status(400).send(`<h1>FAILURE</h1>${safeComment}`);
}

module.exports = { success, failure };
module.exports = { success, failure };
8 changes: 8 additions & 0 deletions src/server/services/utils/sanitizer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const { JSDOM } = require('jsdom');
const createDOMPurify = require('dompurify');

// Create jsdom window application and initialize
const window = new JSDOM('').window;
const DOMPurify = createDOMPurify(window);

module.exports = DOMPurify;
28 changes: 28 additions & 0 deletions src/server/test/crossSite/crossSite.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/* This file tests the functionality of the DOMPurify library. It tests for XSS
vulnerabilities in HTML of user uploaded data.*/

/* Run in OED Docker web container terminal/shell:
npm run testsome src/server/test/crossSite/crossSite.js */
const { chai, mocha, expect, app, testUser } = require('../common');

mocha.describe('Cross site', () => {
mocha.it('test 1: tests for sanitization of HTML', async () => {
const filePath = 'src/server/test/crossSite/readings.csv';

const res = await chai.request(app).post('/api/csv/readings')
.field('email', testUser.username)
.field('password', testUser.password)
/* This next line should produce:
res.text: <h1>FAILURE</h1>CSVPipelineError:
User Error: Meter with name '<img src="x">' not found. */
.field('meterName','<img src=x onerror="alert(document.domain)">')
.field('gzip', "no")
.attach('csvfile', 'src/server/test/crossSite/something.csv');
expect(res.text).to.include('<img src="x">');
expect(res).to.have.status(400);
});
});
1 change: 1 addition & 0 deletions src/server/test/crossSite/something.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1,2,3
1 change: 1 addition & 0 deletions src/server/test/something.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1,2,3