remix
remix copied to clipboard
Need ability to disable stack in _data error response to limit attackers identifying and exploiting dependencies
What version of Remix are you using?
1.5.1
Steps to Reproduce
Pass an invalid parameter to the /?_data=routes%2Fsomething_invalid endpoint. Observe the results. Or pass an invalid POST body to delve deeper into the application stack.
Expected Behavior
Need a way to disable the stack return data in production and have a more generic error returned to the client.
Actual Behavior
During testing by our security analyst, a stack trace was returned that identified the logging system in use and the open-source libraries of the application code running. This could be used by an attacker to exploit dependencies in the application the most serious of which may have zero day implications.
This line unconditionally returns the stack:
https://github.com/remix-run/remix/blob/252ea6c5c55650675b771bf8dada10f68a3cabb4/packages/remix-server-runtime/errors.ts#L68
I'm happy to work on this bug, the question is, do we want to just remove the stack trace when in production mode, or do we want to filter out paths, etc?
This appears to be quite a big security issue if there is no way to suppress the stack trace in responses with uncaught errors relying on use of ErrorBoundary.
I need to solve this myself either through a change to the framework or by other means; perhaps adding a middleware in express to redact the stack traces.
I had a quick look and I think serializeError could possibly take a second parameter to optionally add the stack trace if serverMode is not set to ServerMode.Production in the handler functions?
Hey! If you want to quick fix the above error, this is a snippet from the express instance I use to strip stack from the response and return 400 on incorrect _data param:
app.all(
'*',
createRequestHandler({ build: require('../build'), mode: 'production' }),
(err, req, res, next) => {
if (
err.message === "Cannot read properties of undefined (reading 'params')"
) {
res.status(400).send({ error: 'bad request' });
} else {
res.status(500).send({ error: 'unexpected error occured' });
}
}
);
Hey! If you want to quick fix the above error, this is a snippet from the express instance I use to strip stack from the response and return 400 on incorrect
_dataparam:app.all( '*', createRequestHandler({ build: require('../build'), mode: 'production' }), (err, req, res, next) => { if ( err.message === "Cannot read properties of undefined (reading 'params')" ) { res.status(400).send({ error: 'bad request' }); } else { res.status(500).send({ error: 'unexpected error occured' }); } } );
Probably not going to work so well if you want to maintain use of CatchBoundary for things like 404 page.
It's probably possible to remove stack from data and page requests (it's in appState) with a middleware and a bit of hackery. I've not looked into it yet but imagine there will be some trade offs in being able to use server components/streams.
Converting this to a Proposal discussion, as per our Development Process.