CSP Issue attempting to access an iframe from a different origin: "Blocked a frame with origin from accessing a cross-origin frame"

Hi,
I spotted this other thread explaining how to set bypassCSP: true to be able to work with iframes from a different origin

However, am I correct in assuming that this code no longer works since k6 v0.46?

const context = browser.newContext({
  bypassCSP: true
});

From:

" * Browser options can now only be set using environment variables."

I searched for a relevant env variable but couldn’t fine one in the docs

Currently I get the following error

Blocked a frame with origin "https://mydomain.com" from accessing a cross-origin frame.

The code I’m attempting to execute is identical to the previous thread:

  console.log(page.evaluate(() => {
    return document.querySelector('iframe').contentWindow.document.getElementsByTagName('span')[0].innerText
  }));

Hello @colm3,

The code you provided remains functional in k6 v0.46. The bypassCSP setting belongs to the browserContext options, as outlined in the browserContext documentation, rather than being a browser module option. You can continue configuring it as you have before without necessitating the use of environment variables.

Kindly produce a test script that reproduces the issue, letting us offer assistance.

Thanks.

The “Blocked a frame with origin from accessing a cross-origin frame” error is triggered by the Same-Origin Policy in web browsers, which prevents scripts in one frame from directly accessing content in a frame from a different origin due to security concerns. To address this issue, you should employ cross-origin communication techniques such as postMessage() for controlled messaging between frames, configure Cross-Origin Resource Sharing (CORS) headers when controlling both source and destination servers, or use JSONP for data retrieval. Verify proper URL configuration, consider server-side solutions, and adhere to browser extension policies. These measures ensure secure and legitimate interactions between frames without violating the security constraints imposed by the Same-Origin Policy.

Hi @inancgumus

Here’s an example to reproduce the problem:
I’ve setup a tmp instance of a Braintree credit card form here:
https://k6csp.guruslabs.com/btree/

Here’s the sample k6 browser test I created

I tried executing this with:

K6_BROWSER_HEADLESS=false k6 run k6b-iframe.js

In desperation I also tried it with:
K6_BROWSER_HEADLESS=false K6_BROWSER_ARGS='disable-web-security,user-data-dir=datadir' k6 run k6b-iframe-sample.js

In all scenarios I get the following error:

ERRO[0005] Uncaught (in promise) GoError: evaluating JS: DOMException: Blocked a frame with origin "https://k6csp.guruslabs.com" from accessing a cross-origin frame.
    at __xk6_browser_evaluation_script__:3:89
	at github.com/grafana/xk6-browser/api.Page.Evaluate-fm (native)
	at file:///<<snip>>/k6b-iframe-sample.js:42:24(39)  executor=shared-iterations scenario=browser

Let me know if you need anything else

1 Like

Hi @colm3,

Thanks for the example :bowing_man:

Can you try the following script:

export default async function () {
  const context = browser.newContext({
    bypassCSP: true,
    colorScheme: 'dark',
  });

  const page = context.newPage();

  try {
    await page.goto(
      'https://k6csp.guruslabs.com/btree/index.php',
      { waitUntil: 'networkidle' },
    )  
    
    // complete test payment.
    await page.locator('div.braintree-option__card').click();

    const iframeHandle = page.$('iframe[name=braintree-hosted-field-number]');
    const frame = iframeHandle.contentFrame();
    frame.waitForSelector('input[name="credit-card-number"]');
    await frame.click('input[name="credit-card-number"]');
    await frame.type('input[name="credit-card-number"]', '4111111111111111');

    await page.locator('button').click();
  } finally {
    page.close();
  }
}

Please make sure also enable CORS on this server. Something like the following:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://your-domain.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Credentials: true

Let me know how it goes.

Thanks.

1 Like

Hi @inancgumus

unfortunately that didn’t work :confused:

At the moment the script is just running indefinitely - I’m guessing it’s stuck at:

frame.waitForSelector('input[name="credit-card-number"]');

Re: CORS settings - those aren’t relevant here I think? Any CORS issues would pertain to Braintrees server settings, and the form in my demo is coming directly from Braintree and I can see their scripts/assets all load with the correct CORS headers in their responses:
e.g.

It seems like a local problem because it works on my localhost. Could you try running it from another machine/network to diagnose the problem? Another reason could be the element from the selector might not be appearing at the exact time.

Hi @inancgumus your answer here worked for me almost verbatim, as I have a similar CC processing service to test. I am using title= instead of name. My challenge is: there are multiple iframes, the CC number is in the first iframe and the CSC/CVV is in the second. Their titles are duplicated which I understand is suboptimal to do. The script will locate and type the CC number value in the first iframe but has cannot complete the location of the CSC/CVV; there is an error panic: GoError: dispose: canceled and the script stops. Are there alternate ways to refer to the iframe? I tried a counting approach but so far have not figured it out.

Update: this approach is working to target the correct iframe

    const iframeHandle1 = page.$('//*[@id=" ...CardNumber... "]/iframe');
    const iframeHandle2 = page.$('//*[@id=" ...SecurityCode... "]/iframe');

Hi @richmarshall,

It’s good to hear that it worked for you! Can you send us a small working example of your script and the HTML test page so we can reproduce the issue?

Thanks!

I’m not sure I can send the application page.

The script goes into both separate iframes and manipulates the fields for each. These complete all the requirements for the form that creates an order which activates the place order button outside of the iframes (back on the primary document). The place order button gets clicked but during the waitForNavigation (immediately) the browser closes and script stops with the panic: GoError: dispose: canceled error; the stack trace is very close to identical to issue 1089. I am using k6.exe v0.49.0.

panic: GoError: dispose: canceled
running (1m31.0s), 1/1 VUs, 0 complete and 0 interrupted iterations
goroutine 43 [running]:ceOrder   [============>-------------------------] 1/1 VUs  1m31.0s/4m10.0s
go.k6.io/k6/js/common.Throw(...)
        go.k6.io/k6/js/common/util.go:20
github.com/grafana/xk6-browser/k6ext.Panic.func1(0x16130c0?, {0xc0005f0230?, 0x16b0a01?, 0xc000dd0ec0?})
        github.com/grafana/xk6-browser@v1.3.0/k6ext/panic.go:35 +0x74
github.com/grafana/xk6-browser/k6ext.sharedPanic({0x1c138b8, 0xc000b0a820}, 0xc0009a1a68, {0xc0005f0230, 0x1, 0x1})
        github.com/grafana/xk6-browser@v1.3.0/k6ext/panic.go:64 +0x254
github.com/grafana/xk6-browser/k6ext.Panic({0x1c138b8?, 0xc000b0a820?}, {0x185ca64?, 0xc00004cf50?}, {0xc0005f0230?, 0xc00004cf60?, 0x158dd20?})
        github.com/grafana/xk6-browser@v1.3.0/k6ext/panic.go:37 +0x5a
github.com/grafana/xk6-browser/common.(*BaseJSHandle).Dispose(0xc004868050)
        github.com/grafana/xk6-browser@v1.3.0/common/js_handle.go:84 +0x9f
github.com/grafana/xk6-browser/common.(*Frame).detach(0xc0063fcfc0)
        github.com/grafana/xk6-browser@v1.3.0/common/frame.go:243 +0x14a
github.com/grafana/xk6-browser/common.(*FrameManager).removeFramesRecursively(0xc002fa5bc0, 0xc0046ea700?)
        github.com/grafana/xk6-browser@v1.3.0/common/frame_manager.go:419 +0x256
github.com/grafana/xk6-browser/common.(*FrameManager).frameDetached(0xc002fa5bc0, {0xc0046ea700, 0x20}, {0x1853de2, 0x6})
        github.com/grafana/xk6-browser@v1.3.0/common/frame_manager.go:185 +0x151
github.com/grafana/xk6-browser/common.(*FrameSession).onFrameDetached(0xc002fa5c80, {0xc0046ea700, 0x20}, {0x1853de2, 0x6})
        github.com/grafana/xk6-browser@v1.3.0/common/frame_session.go:739 +0x178
github.com/grafana/xk6-browser/common.(*FrameSession).initEvents.func1()
        github.com/grafana/xk6-browser@v1.3.0/common/frame_session.go:257 +0x507
created by github.com/grafana/xk6-browser/common.(*FrameSession).initEvents in goroutine 104
        github.com/grafana/xk6-browser@v1.3.0/common/frame_session.go:223 +0x19b

Hey! you didn’t then inform about it…

This looks like a csp issue is it? If so, update frame-ancestors or frame-src to allow the iframe’s origin, e.g, Content-Security-Policy: frame-ancestors 'self' https://trusted-origin.com;. When done, get to the use of pi for you maths.