Does express-validator sanitize.escape() the same as DOMPurify? - node.js

Want to take measures to protect myself against XSS.
Right now, I have:
sanitizeQuery('searchQuery').escape().trim()
Is that adequate protection? Or would you recommend adding something like DOM Purify (running on the node end) as well?

Short answer: No
Long answer: your approach will get you most part of the way but and I quote:
HTML entity encoding doesn't work if you're putting untrusted data inside a tag anywhere, or an event handler attribute like onmouseover, or inside CSS, or in a URL.
You should be using something like DOMPurify
Source XSS Prevention Cheat Sheet

You can use dompurify with express-validator.
const { param, validationResult } = require('express-validator')
const createDOMPurify = require('dompurify');
const { JSDOM } = require('jsdom');
const xssSenitize = (value) => {
const window = new JSDOM('').window;
const DOMPurify = createDOMPurify(window);
return DOMPurify.sanitize(value, { ALLOWED_TAGS: [] });
}
query(['id']).customSanitizer(xssSenitize)

Related

confused about node-localstorage

so I'm making a site with node js, and I need to use localstorage, so I'm using the node-localstorage library. So basically, in one file I add data to it, and in another file I want to retrieve it. I'm not 100% sure about how to retrieve it. I know I need to use localStorage.getItem to retrieve it, but do I need to include localStorage = new LocalStorage('./scratch');? So I was wondering what the localStorage = new LocalStorage('./scratch'); did. So here is my code for adding data:
const ls = require('node-localstorage');
const express = require("express");
const router = express.Router();
router.route("/").post((req, res, next) => {
var localStorage = new ls.LocalStorage('./scratch');
if(req.body.name != undefined){
localStorage.setItem("user", req.body.name);
res.redirect('/')
}
else{
console.log("undefind")
}
});
module.exports = router;
If my question is confusing, I just want to know what var localStorage = new ls.LocalStorage('./scratch'); does.
A drop-in substitute for the browser native localStorage API that runs on node.js.
It creates an instance of the "localStorage" class, which this library provides. The constructor expects the location of the file, the scripts stores the key, value elements in.
Opinion: This looks pointless to me - I guess it fits your use case.

Can a global variable set during a request leak across different requests?

If I set a global variable during processing of a request, can I leak that information into subsequent requests?
That is, the global variable is set on every request, and because nodejs is single-threaded I think I'm safe, but I'm asking here to increase confidence.
Here's my context:
I'm building a front-end service (Typescript + React) which does server side rendering, and I want to configure the application per-request.
To that end I'm using this technique:
conf.ts:
let CONFIG: any
export function setGlobal (state: any): void {
CONFIG = state
}
export function getGlobal(): any {
return CONFIG
}
server.tsx - where the Express app is configured:
const app = express()
app.get("/*", htmlEndpoint)
function htmlEndpoint (req: express.Request, res: express.Response): void {
const foo = req.headers["x-foo"] as string || ""
setGlobal({ foo })
const context = {}
const markup = renderToString(
<StaticRouter location={req.url}>
<App/>
</StaticRouter>,
)
<... respond with HTML, just boring boilerplate code ...>
}
And now somewhere deep in the React render-tree, a component can do this:
export function MyComponent() {
console.log(getGlobal().foo)
}
Technically my question is very narrow in scope: By calling setGlobal on every request, am I running a real risk of leaking the contents of that global into other requests?
But more broadly I also welcome any kind of feedback and thoughts on the design. I dislike globals but haven't found another solution, but I also recognize I'm not an expert in any of my chosen technologies so it may be you can help open my eyes to alternatives. Very happy to hear your thoughts.
You are right - since Node is single threaded only one request is processed at a time, meaning that it would most certainly not be possible for the value to leak over into another request.
I think your approach is fine, although the code might not be as readable as it could be. Would it not be simpler to pass the value as a prop instead?
To do that you could do like this:
const global = { value: null }
// To set:
global.value = 'foo'
// To read:
console.log(global.value)
To pass it as a prop, you would declare your App component like:
function App(props) {
// To access
console.log(props.global.value)
}
And in your request:
<App global={global} />
You would then need to pass the value down the react tree to whichever component needs it.

How to use i18next in serverless node js?

I am using Node JS Azure functions. I am trying to internationalize the error messages returned by the functions with i18next. I could find examples with express or plain node server. In these cases middleware pattern can be used.
But for functions, I need a way to call i18next.t('key') with probably a language parameter which I am not able to find. Calling i18next.changeLanguage() before every call to i18next.t('key') doesn't seem practical.
My skeleton code is as follows
const i18next = require("i18next");
const backend = require("i18next-node-fs-backend");
const options = {
// path where resources get loaded from
loadPath: '../locales/{{lng}}/{{ns}}.json',
// path to post missing resources
addPath: '../locales/{{lng}}/{{ns}}.missing.json',
// jsonIndent to use when storing json files
jsonIndent: 4
};
i18next.use(backend).init(options);
exports.getString = (key, lang) => {
//i18next.changeLanguage(lang,
return i18next.t(key);
}
It is possible to fetch translations without doing changeLanguage each time?
As pointed out in the comments you need to call the i18next.changeLanguage(lang) function whenever the language needs to be defined or changed.
You can take a look to the documentation here.
The code could look like this
const i18next = require('i18next')
const backend = require('i18next-node-fs-backend')
const options = {
// path where resources get loaded from
loadPath: '../locales/{{lng}}/{{ns}}.json',
// path to post missing resources
addPath: '../locales/{{lng}}/{{ns}}.missing.json',
// jsonIndent to use when storing json files
jsonIndent: 4
}
i18next.use(backend).init(options)
exports.getString = (key, lang) => {
return i18next
.changeLanguage(lang)
.then((t) => {
t(key) // -> same as i18next.t
})
}

Updating the prototype of ServerRequest in an express/node configuration

I'd like to augment the prototype of the request object in expressjs, but it isn't clear where this request is defined? I think it is http.ServerRequest, but I can't find that definition either.
What's the right way to do the following...
http.ServerRequest.prototype.redirect = function(path) { }
Express itself adds it's utility methods to http.IncomingMessage.prototype, using this pattern in 2.*:
var http = require('http'),
req = http.IncomingMessage.prototype;
req.foo = function(bar) {
// Do cool stuff
};
And this pattern in 3.*:
var http = require('http');
var req = exports = module.exports = {
__proto__: http.IncomingMessage.prototype
};
It's wise to be careful with monkey patching though, as Vadim Baryshev warns in his answer.
Look at Connect framework and his middleware libs. Every middleware extends request and response objects after their creation. Changing prototype of core objects not the best way because this can lead to unpredictable behavior in other modules.

URL Generation for Routes in Express

I'm considering using Express framework in my next node.js project. However, a stumbling block for me is non-existence of URL generation for routes like in most other non-Sinatra based frameworks, examples- Django, Flask, Rails etc.
I tried looking for some Connect middleware to serve my task and I did find Barista, Escort, Sherpa and the likes but looking at their GitHub pages, all seem dead and in-active. So, I don't want to go for something that's not maintained anymore for obvious reasons.
My main concern here is that the project may get really large and it WILL be a pain to update URLs in every page whenever business and/or aesthetic requirements change.
Is there something that I failed to see in the docs/tests? If not, then how do I extend the routing framework in Express to do URL generation and make this wrapper available in my views as well as controller functions?
UPDATE: (22/3/2012) I found this page: https://github.com/clyfe/tweet_express/wiki/TODO which specified some routers that do URL generation and stumbled upon the escort router which can also interface with express.
Or stick with express and use the package reversable-router.
Example from the readme:
app.get('/admin/user/:id', 'admin.user.edit', function(req, res, next){
//...
});
//.. and a helper in the view files:
url('admin.user.edit', {id: 2})
You might try Locomotive, which is built on Express.
It does much more than route generation. From the docs: "Locomotive brings additional MVC-based structure, for architecting larger applications, while leveraging the power of Express and Connect middleware."
Locomotive's router generates helpers that are automatically available to controllers and views.
From #freakish's answer:
There is no out of the box mechanism for that. However you can mimic Django's style like that: define urls.js file which will hold an array of URLs. First start with:
myviews.js
exports.Index = function( req, res, next ) {
res.send( "hello world!" );
};
urls.js
var MyViews = require( "mywviews.js" );
module.exports = [
{ name : "index", pattern : "/", view : MyViews.Index }
]
Now in app.js ( or whatever the main file is ) you need to bind urls to Express. For example like this:
app.js
var urls = require( "urls.js" );
for ( var i = 0, l = urls.length; i < l; i++ ) {
var url = urls[ i ];
app.all( url.pattern, url.view );
};
Now you can define custom helper ( Express 3.0 style ):
var urls = require( "urls.js" ), l = urls.length;
app.locals.url = function( name ) {
for ( var i = 0; i < l; i++ ) {
var url = urls[ i ];
if ( url.name === name ) {
return url.pattern;
}
};
};
and you can easily use it in your template. Now the problem is that it does not give you fancy URL creation mechanism like in Django ( where you can pass additional parameters to url ). On the other hand you can modify url function and extend it. I don't want to go into all details here, but here's an example how to use regular expressions ( you should be able to combine these to ideas together ):
Express JS reverse URL route (Django style)
Note that I posted the question, so I had the same problem some time ago. :D

Resources