-
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
Fix allowed origins #5536
Fix allowed origins #5536
Conversation
mifi
commented
Dec 4, 2024
- escape regex in default companionAllowedHosts
- also fail early if invalid regex supplied
- and add unit tests
- also fail early if invalid regex supplied - and add unit tests
Diff output filesdiff --git a/packages/@uppy/companion-client/lib/Provider.js b/packages/@uppy/companion-client/lib/Provider.js
index 8be290a..8b5780b 100644
--- a/packages/@uppy/companion-client/lib/Provider.js
+++ b/packages/@uppy/companion-client/lib/Provider.js
@@ -6,6 +6,7 @@ var id = 0;
function _classPrivateFieldLooseKey(e) {
return "__private_" + id++ + "_" + e;
}
+import { isOriginAllowed } from "./getAllowedHosts.js";
import RequestClient, { authErrorStatusCode } from "./RequestClient.js";
const getName = id => {
return id.split("-").map(s => s.charAt(0).toUpperCase() + s.slice(1)).join(" ");
@@ -13,21 +14,6 @@ const getName = id => {
function getOrigin() {
return location.origin;
}
-function getRegex(value) {
- if (typeof value === "string") {
- return new RegExp(`^${value}$`);
- }
- if (value instanceof RegExp) {
- return value;
- }
- return undefined;
-}
-function isOriginAllowed(origin, allowedOrigin) {
- const patterns = Array.isArray(allowedOrigin) ? allowedOrigin.map(getRegex) : [getRegex(allowedOrigin)];
- return patterns.some(pattern =>
- (pattern == null ? void 0 : pattern.test(origin)) || (pattern == null ? void 0 : pattern.test(`${origin}/`))
- );
-}
var _refreshingTokenPromise = _classPrivateFieldLooseKey("refreshingTokenPromise");
var _getAuthToken = _classPrivateFieldLooseKey("getAuthToken");
var _getPlugin = _classPrivateFieldLooseKey("getPlugin");
diff --git a/packages/@uppy/companion-client/lib/getAllowedHosts.js b/packages/@uppy/companion-client/lib/getAllowedHosts.js
index 9912fbf..45d2f1c 100644
--- a/packages/@uppy/companion-client/lib/getAllowedHosts.js
+++ b/packages/@uppy/companion-client/lib/getAllowedHosts.js
@@ -1,12 +1,40 @@
-export default function getAllowedHosts(hosts, url) {
- if (hosts) {
- if (typeof hosts !== "string" && !Array.isArray(hosts) && !(hosts instanceof RegExp)) {
- throw new TypeError(`The option "companionAllowedHosts" must be one of string, Array, RegExp`);
+function escapeRegex(string) {
+ return string.replace(/[/\-\\^$*+?.()|[\]{}]/g, "\\$&");
+}
+function wrapInRegex(value) {
+ if (typeof value === "string") {
+ return new RegExp(`^${value}$`);
+ }
+ if (value instanceof RegExp) {
+ return value;
+ }
+ return undefined;
+}
+export default function getAllowedHosts(companionAllowedHosts, companionUrl) {
+ if (companionAllowedHosts) {
+ const validate = value => {
+ if (!(typeof value === "string" && wrapInRegex(value)) && !(value instanceof RegExp)) {
+ throw new TypeError(`The option "companionAllowedHosts" must be one of string, Array, RegExp`);
+ }
+ };
+ if (Array.isArray(companionAllowedHosts)) {
+ companionAllowedHosts.every(validate);
+ } else {
+ validate(companionAllowedHosts);
}
- return hosts;
+ return companionAllowedHosts;
}
- if (/^(?!https?:\/\/).*$/i.test(url)) {
- return `https://${url.replace(/^\/\//, "")}`;
+ let ret = companionUrl;
+ if (/^(?!https?:\/\/).*$/i.test(ret)) {
+ ret = `https://${companionUrl.replace(/^\/\//, "")}`;
}
- return new URL(url).origin;
+ ret = new URL(ret).origin;
+ ret = escapeRegex(ret);
+ return ret;
+}
+export function isOriginAllowed(origin, allowedOrigin) {
+ const patterns = Array.isArray(allowedOrigin) ? allowedOrigin.map(wrapInRegex) : [wrapInRegex(allowedOrigin)];
+ return patterns.some(pattern =>
+ (pattern == null ? void 0 : pattern.test(origin)) || (pattern == null ? void 0 : pattern.test(`${origin}/`))
+ );
} |
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.
e2e is failing and one comment. Otherwise LGTM
// if it does not start with https://, prefix it (and remove any leading slashes) | ||
let ret = companionUrl | ||
if (/^(?!https?:\/\/).*$/i.test(ret)) { | ||
// todo shouldn't this also be wrapped in new URL(companionUrl).origin ? |
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.
you override ret below with new URL(ret).origin
as this todo comment wants so can we remove this?
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.
right, good catch. i was afraid of doing it in case it was be a breaking change, but then i accidentally did it after all 🤦♂️ if you agree it's probably not a breaking change, i'll just keep it as it is now
I have now idea why it fails with this error. i haven't even touched any of those files
|
All good things are 3 as we say in norway. 3rd run’s a success |
Co-authored-by: Mikael Finstad <finstaden@gmail.com>
| Package | Version | Package | Version | | -------------------------- | ------- | -------------------------- | ------- | | @uppy/audio | 2.0.2 | @uppy/instagram | 4.1.2 | | @uppy/aws-s3 | 4.1.3 | @uppy/locales | 4.3.1 | | @uppy/box | 3.1.2 | @uppy/onedrive | 4.1.2 | | @uppy/companion | 5.2.0 | @uppy/progress-bar | 4.0.2 | | @uppy/companion-client | 4.2.0 | @uppy/provider-views | 4.1.0 | | @uppy/compressor | 2.1.1 | @uppy/react | 4.0.4 | | @uppy/core | 4.3.0 | @uppy/remote-sources | 2.2.1 | | @uppy/dashboard | 4.1.3 | @uppy/screen-capture | 4.1.2 | | @uppy/drag-drop | 4.0.5 | @uppy/status-bar | 4.0.5 | | @uppy/drop-target | 3.0.2 | @uppy/store-default | 4.1.2 | | @uppy/dropbox | 4.1.2 | @uppy/thumbnail-generator | 4.0.2 | | @uppy/facebook | 4.1.2 | @uppy/transloadit | 4.1.4 | | @uppy/file-input | 4.0.4 | @uppy/tus | 4.1.5 | | @uppy/form | 4.0.2 | @uppy/unsplash | 4.1.2 | | @uppy/golden-retriever | 4.0.2 | @uppy/url | 4.1.2 | | @uppy/google-drive | 4.2.0 | @uppy/utils | 6.0.5 | | @uppy/google-drive-picker | 0.2.0 | @uppy/vue | 2.0.3 | | @uppy/google-photos | 0.4.0 | @uppy/webcam | 4.0.3 | | @uppy/google-photos-picker | 0.2.0 | @uppy/xhr-upload | 4.2.3 | | @uppy/image-editor | 3.2.1 | @uppy/zoom | 3.1.2 | | @uppy/informer | 4.1.2 | uppy | 4.8.0 | - @uppy/companion-client: Fix allowed origins (Mikael Finstad / #5536) - meta: Build lib refactor to esm (Mikael Finstad / #5537) - @uppy/provider-views: Google picker scope (Mikael Finstad / #5535) - @uppy/core,@uppy/provider-views: move useStore out of core (Mikael Finstad / #5533) - @uppy/companion,@uppy/google-drive-picker,@uppy/google-photos-picker: Google Picker (Mikael Finstad / #5443) - @uppy/aws-s3: console.error instead of throw for missing etag (Merlijn Vos / #5521) - docs: Put docs back in uppy.io repository where they belong (Merlijn Vos / #5527) - docs: typo (Azhar Rizqullah / #5523) - @uppy/audio,@uppy/aws-s3,@uppy/box,@uppy/companion-client,@uppy/compressor,@uppy/core,@uppy/dashboard,@uppy/drag-drop,@uppy/drop-target,@uppy/dropbox,@uppy/facebook,@uppy/file-input,@uppy/form,@uppy/golden-retriever,@uppy/google-drive,@uppy/google-photos,@uppy/image-editor,@uppy/informer,@uppy/instagram,@uppy/locales,@uppy/onedrive,@uppy/progress-bar,@uppy/provider-views,@uppy/react,@uppy/remote-sources,@uppy/screen-capture,@uppy/status-bar,@uppy/store-default,@uppy/thumbnail-generator,@uppy/transloadit,@uppy/tus,@uppy/unsplash,@uppy/url,@uppy/utils,@uppy/vue,@uppy/webcam,@uppy/xhr-upload,@uppy/zoom: cleanup tsconfig (Mikael Finstad / #5520) - meta: fix missing lint (Mikael Finstad / #5519) - docs: Add Next.js docs (Merlijn Vos / #5502) - e2e: try to fix flaky test (Mikael Finstad / #5512) - meta: Fix broken lint on CI (Mikael Finstad / #5507)