While there is no issue loading / using stripe in my normal iframe environment, I have a client who has some security issues allowing the iframe sandbox attribute to have 'allow-same-origin' set to true. While I've worked around the issues with loading scripts into the DOM of my iframe, it would seem the issue lies with the iframe stripe loads into my iframe.
I have been unable to find any support in the documentation that would allow me to circumvent this. Is this possible? If so, how might one accomplish this?
@avcohen can you please share some more details: what is the full set of sandbox attributes on the iframe of your page? what does your code loading/using Stripe.js look like? what is breaking and when? what error message do you see?
Hi. @asolove-stripe. The full set of attributes on sandbox are allow-scripts allow-popups allow-forms. Below is a contrived example of how we're adding the stripe library to the DOM (promise based util is just adding it to the document with a callback) and mounting said components.
class _PaymentForm extends React.Component {
async handleSubmit(e) {
e.preventDefault();
const data = await this.props.stripe.createToken();
this.props.onSubmit(e, data.token.id);
}
render() {
return <PaymentForm {...this.props} onSubmit={this.handleSubmit.bind(this)} />;
}
}
const PaymentForm = injectStripe(_PaymentForm);
class StripeContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
stripe: null
};
}
componentDidMount() {
if (window.Stripe) {
this.onStripeLoaded();
} else {
this.stripeLoadReference = loadScript(
'https://js.stripe.com/v3/',
() => this.onStripeLoaded(),
false,
null
);
}
}
onStripeLoaded() {
const stripe = window.Stripe(config.STRIPE_KEY);
this.setState({ stripe: stripe });
}
render() {
return (
<StripeProvider stripe={this.state.stripe}>
<Elements>
<PaymentForm {...this.props} stripe={this.state.stripe} />
</Elements>
</StripeProvider>
);
}
}
To note, this works fine in all of our environments _except_ when 'allow-same-origin' is removed.
As for error messaging they're all the same error for various files in css and js subpaths - ('https://js.stripe.com/v3/fingerprinted/*):
Refused to load the script 'https://js.stripe.com/v3/fingerprinted/js/elements-inner-card-11de9108130c8bbb80768db9bca9e93b.js' because it violates the following Content Security Policy directive: "script-src 'self'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.
There is also a separate error loading https://m.stripe.com/4:
Access to XMLHttpRequest at 'https://m.stripe.com/4' from origin 'null' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value 'https://m.stripe.network' that is not equal to the supplied origin.
Thanks!
Interesting: is there a specific Content Security Policy served by your page (the one in the iframe)? It looks like some interaction of that CSP and the allow-same-origin is making the browser not load scripts from anywhere but the current origin (which, without allow-same-origin, is a fake origin that doesn't match anything).
So i'm actually not defining a specific CSP via a meta tag in the the head of the iframe that mounts and runs code from stripe.
To test, I did add one and while I was able to remove blocks from various source (local, mostly) whitelisting https://js.stripe.com/ as a script-src with both the 'unsafe-inline' and 'unsafe-eval' values did not seem to alleviate. Perhaps this is coming down to my misunderstanding of how CSP rules are defined?
Oh, I see. It's not blocking Stripe.js in your page, it's blocking the loading of one of the scripts inside our iframe. I don't believe this is fixable.
Here's what I think is happening: by not including allow-same-origin on the top-level iframe that includes your page, the browser also enforces that all child iframes inside that page are also sandboxed and also have allow-same-origin turned off. As a result, the Stripe iframe's CSP rule, which only allows loading JavaScript from the same origin, fails when it tries to load JavaScript, because the browser is treating the origin as not the same.
I do not think there is anything we can do to allow this. The browser is doing exactly what it is supposed to do, and Stripe.js' iframes definitely need to use CSP to only load JavaScript from our safe origin. I'm sorry, but I think you'll either need allow-same-origin or to use Stripe.js from the top-level page.
@asolove-stripe
I'm sorry, but I think you'll either need allow-same-origin or to use Stripe.js from the top-level page.
got the same issue. can you elaborate the solution in detail?
How can we allow-same-origin or use stripe.js from top-level page. Any information about how to do that if we are using plain html+css without react and other libraries or frameworks.
Most helpful comment
@asolove-stripe
got the same issue. can you elaborate the solution in detail?