-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
@uppy/companion: do not use unsafe call to JSON.stringify
#5422
Conversation
Diff output filesdiff --git a/packages/@uppy/companion/lib/server/emitter/redis-emitter.js b/packages/@uppy/companion/lib/server/emitter/redis-emitter.js
index aa4f768..62796bc 100644
--- a/packages/@uppy/companion/lib/server/emitter/redis-emitter.js
+++ b/packages/@uppy/companion/lib/server/emitter/redis-emitter.js
@@ -1,7 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const { EventEmitter } = require("node:events");
+const { default: safeStringify } = require("fast-safe-stringify");
const logger = require("../logger");
+function replacer(key, value) {
+ // Remove the circular structure and internal ones
+ return key[0] === "_" || value === "[Circular]" ? undefined : value;
+}
/**
* This module simulates the builtin events.EventEmitter but with the use of redis.
* This is useful for when companion is running on multiple instances and events need
@@ -134,7 +139,7 @@ module.exports = (redisClient, redisPubSubScope) => {
* @param {string} eventName name of the event
*/
function emit(eventName, ...args) {
- runWhenConnected(() => publisher.publish(getPrefixedEventName(eventName), JSON.stringify(args)));
+ runWhenConnected(() => publisher.publish(getPrefixedEventName(eventName), safeStringify(args, replacer)));
}
/**
* Remove all listeners of an event The following build files have been modified and might affect the actual diff:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a bit inefficient but should we temporarily add try
/catch
with JSON.stringify
to this change as well so we can log the eventName and object?
I'd rather work towards not sending massive circular objects over redis than to silence the problem.
Isn’t this a breaking change if the output from util.inspect is not the same as that from JSON.stringify? Wouldn’t using JSON.parse on an string that has been util.inspect’ed possibly fail? (I assume that JSON.stringify was not added here in order to make it human readable). |
I don't think it's breaking, in fact it's less breaking as the current code crashed in production and this won't. |
I mean breaking as in api breaking: if util.inspect changes the api and someone is consuming the event on redis, then it could break their implementation |
New and removed dependencies detected. Learn more about Socket for GitHub ↗︎
🚮 Removed packages: npm/dedent@1.5.3), npm/he@1.2.0), npm/lodash@4.17.21), npm/process@0.11.10), npm/tslib@2.7.0) |
|
||
const logger = require('../logger') | ||
|
||
function replacer(key, value) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
better to put replacer inside the function call so typescript can automatically infer the types for key and value, but we can also do that later when refactoring to typescript
|
||
const logger = require('../logger') | ||
|
||
function replacer(key, value) { | ||
// Remove the circular structure and internal ones |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Remove the circular structure and internal ones | |
// Remove the circular references and internal properties | |
// so that they don't get exposed to the browser (uppy client) |
Shall we also stop sending the entire req object in emits in this PR? Over Slack we concluded that it wouldn't be a breaking change. |
You mean stop sending the whole Error object and instead just send
|
Discussed just now. Let's keep things for now and not block this PR any further. |
| Package | Version | Package | Version | | ---------------------- | ------- | ---------------------- | ------- | | @uppy/aws-s3 | 4.1.0 | @uppy/informer | 4.1.0 | | @uppy/box | 3.1.0 | @uppy/instagram | 4.1.0 | | @uppy/companion | 5.1.0 | @uppy/locales | 4.1.0 | | @uppy/companion-client | 4.1.0 | @uppy/onedrive | 4.1.0 | | @uppy/compressor | 2.1.0 | @uppy/remote-sources | 2.2.0 | | @uppy/core | 4.2.0 | @uppy/screen-capture | 4.1.0 | | @uppy/dashboard | 4.1.0 | @uppy/tus | 4.1.0 | | @uppy/dropbox | 4.1.0 | @uppy/unsplash | 4.1.0 | | @uppy/facebook | 4.1.0 | @uppy/url | 4.1.0 | | @uppy/google-drive | 4.1.0 | @uppy/xhr-upload | 4.1.0 | | @uppy/google-photos | 0.3.0 | @uppy/zoom | 3.1.0 | | @uppy/image-editor | 3.1.0 | uppy | 4.3.0 | - @uppy/core,@uppy/dashboard: Pass container to `UIPlugin.render` for non-Preact integration (Merlijn Vos / #5437) - @uppy/companion: do not use unsafe call to `JSON.stringify` (Antoine du Hamel / #5422) - meta: Fix yarn.lock (Murderlon) - @uppy/locales: Fix locale-pack for en_US (Merlijn Vos / #5431) - meta: Add tsconfig to packages in private/ (Merlijn Vos / #5432) - @uppy/remote-sources: support companionKeysParams (Merlijn Vos / #5434) - @uppy/aws-s3,@uppy/box,@uppy/compressor,@uppy/dropbox,@uppy/facebook,@uppy/google-drive,@uppy/google-photos,@uppy/image-editor,@uppy/informer,@uppy/instagram,@uppy/onedrive,@uppy/screen-capture,@uppy/tus,@uppy/unsplash,@uppy/url,@uppy/xhr-upload,@uppy/zoom: export plugin options (Antoine du Hamel / #5433) - docs: correctly list exported components (Merlijn Vos / #5417)
Calling
JSON.stringify
on some objects (e.g. self-referencing objects) can lead to aTypeError
; instead we can useutil.inspect
that is able to deal with those, and is basically guaranteed to never throw. It also means the output will be more readable by humans – but no as readable for machines.