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: insecure iframe messaging #297

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

chaitanyapotti
Copy link

Fixes #296

@chaitanyapotti chaitanyapotti changed the title Fix insecure iframe messaging fix: insecure iframe messaging Sep 1, 2021
@@ -46,7 +47,7 @@ class PostMessageIframeTransport extends Transport {
const prom = this.transportRequestManager.addRequest(data, null);
const notifications = getNotifications(data);
if (this.frame) {
this.frame.postMessage((data as IJSONRPCData).request, "*");
this.frame.postMessage((data as IJSONRPCData).request, this.uri);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
this.frame.postMessage((data as IJSONRPCData).request, this.uri);
this.frame.postMessage((data as IJSONRPCData).request, this.origin);

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the origin can easily be derived as new URL(this.uri).origin
We don't need another parameter from ctor

@@ -28,7 +28,8 @@ class PostMessageIframeTransport extends Transport {
});
}
private messageHandler = (ev: MessageEvent) => {
this.transportRequestManager.resolveResponse(JSON.stringify(ev.data));
if (ev.origin === this.uri)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (ev.origin === this.uri)
if (ev.origin === this.origin)

@@ -36,7 +36,8 @@ class PostMessageTransport extends Transport {
}

private messageHandler = (ev: MessageEvent) => {
this.transportRequestManager.resolveResponse(JSON.stringify(ev.data));
if (ev.origin === this.uri)
Copy link
Member

@zcstarr zcstarr Sep 3, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (ev.origin === this.uri)
if (ev.origin === this.origin || ev.orgin === "*")

Copy link
Member

@zcstarr zcstarr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes look good, there is an issue, I added some suggestions for adding origin
so the constructor should be

  constructor(uri: string, origin: string) {
  this.orgin = origin
  ...

We're debating a little if this should be a breaking change, because it's probably better to take this away, vs let it persist. You can still do star this way, but you have to set it explicitly.

This was awesome patch it up and I'll be excited to merge this in, nice find!

Copy link
Member

@zcstarr zcstarr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

accidental approval in this state just requesting changes that were listed before

@chaitanyapotti
Copy link
Author

Pls check my changes.
We should derive origin from uri instead of relying on user input.

@zcstarr
Copy link
Member

zcstarr commented Sep 4, 2021

Pls check my changes.
We should derive origin from uri instead of relying on user input.

The suggestion for a parameter is so users can define what urls they want to accept request from. Locking people into request coming from the same url origin, makes the api not flexible enough.

We can't universally make that assumption about the context in which client-js is operating in.

@@ -5,10 +5,12 @@ class PostMessageIframeTransport extends Transport {
public uri: string;
public frame: undefined | null | Window;
public postMessageID: string;
public origin: string;

constructor(uri: string) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we'll still need the origin to come from the constructor here. We have to leave the origin to be specified by the consumers here, by passing it into the constructor. This is because we can't make an assumption about where they'd like the post message communication to come from.

In a dev case for instance they may want *, in a cross domain case they may want the origin to come from a window they launched that has a separate domain they know. If we lock them in it takes away the choice.

The default to * after speaking with @shanejonas we both feel like the security change warrants a version that makes people explicitly state *, so they know what assumptions they're making about the transport.

The pr looks great, and thanks for the questions and comments and getting this done!

@chaitanyapotti
Copy link
Author

I've made the necessary changes

@@ -28,7 +30,8 @@ class PostMessageIframeTransport extends Transport {
});
}
private messageHandler = (ev: MessageEvent) => {
this.transportRequestManager.resolveResponse(JSON.stringify(ev.data));
if (ev.origin === this.origin)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (ev.origin === this.origin)
if (ev.orgin === this.origin || ev.origin === "*")

super();
this.uri = uri;
this.origin = origin || new URL(uri).origin;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is awesome thanks for doing this. The only thing here is that we're going to opt for a breaking change here.

We're going to rm the default, because defaulting to origin can be a hidden breaking change to people using this in prod.

We'll do a maj. verson bump which will force people to explicitly update their clients to set what domain they'd like to use this against, when using postmessage transport.

Once this lands the team will bump the versions of generator and any other ecosystem consumers.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
this.origin = origin || new URL(uri).origin;
this.origin = origin;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commit message for these changes should be in the following format for semantic release

fix: patch security hole for post message iframe transport. this change forces consumers to
explicitly set the transport's acceptable origins. Improving the security using the transport.

BREAKING CHANGE: transport now takes second argument and requires origin be set for filtering
post message request.


constructor(uri: string) {
constructor(uri: string, origin?: string) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
constructor(uri: string, origin?: string) {
constructor(uri: string, origin: string) {

@@ -36,7 +38,8 @@ class PostMessageTransport extends Transport {
}

private messageHandler = (ev: MessageEvent) => {
this.transportRequestManager.resolveResponse(JSON.stringify(ev.data));
if (ev.origin === this.origin)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (ev.origin === this.origin)
if (ev.origin === this.origin || ev.origin === "*")

@BelfordZ
Copy link
Member

BelfordZ commented Jan 5, 2023

@chaitanyapotti Thank you for the PR and issue! nice work!

Are you able to finish this one off? Happy to help get it through.

@BelfordZ
Copy link
Member

BelfordZ commented Jan 5, 2023

@zcstarr perhaps you have some time to cherrypick his commits and make the required changes?

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.

Insecure postMessage window handlers
3 participants