Skip to content
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

Merged
merged 3 commits into from
Dec 4, 2024
Merged

Fix allowed origins #5536

merged 3 commits into from
Dec 4, 2024

Conversation

mifi
Copy link
Contributor

@mifi mifi commented Dec 4, 2024

  • escape regex in default companionAllowedHosts
  • also fail early if invalid regex supplied
  • and add unit tests

mifi added 2 commits December 4, 2024 15:32
- also fail early if invalid regex supplied
- and add unit tests
Copy link
Contributor

github-actions bot commented Dec 4, 2024

Diff output files
diff --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}/`))
+  );
 }

Copy link
Member

@Murderlon Murderlon left a 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 ?
Copy link
Member

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?

Copy link
Contributor Author

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

@mifi
Copy link
Contributor Author

mifi commented Dec 4, 2024

I have now idea why it fails with this error. i haven't even touched any of those files

@parcel/core: Failed to resolve '@uppy/core' from 
'./e2e/clients/dashboard-aws-multipart/app.js'
  /home/runner/work/uppy/uppy/e2e/clients/dashboard-aws-multipart/app.js:1:22
  > 1 | import { Uppy } from '@uppy/core'
  >   |                      ^^^^^^^^^^^^
    2 | import Dashboard from '@uppy/dashboard'
    3 | import AwsS3Multipart from '@uppy/aws-s3-multipart'

@mifi
Copy link
Contributor Author

mifi commented Dec 4, 2024

All good things are 3 as we say in norway. 3rd run’s a success

Co-authored-by: Mikael Finstad <finstaden@gmail.com>
@mifi mifi merged commit 8ebdf73 into main Dec 4, 2024
16 checks passed
@mifi mifi deleted the fix-allowed-origins branch December 4, 2024 15:04
@github-actions github-actions bot mentioned this pull request Dec 5, 2024
github-actions bot added a commit that referenced this pull request Dec 5, 2024
| 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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants