捕获 iframe csp/沙盒错误

问题描述 投票:0回答:1

我正在编写 Cypress 测试来验证有关沙箱和 CSP 权限的 iframe 安全策略。我已禁用

allow-modals
,并且对警报和其他调用的调用按预期失败,并显示以下 Chrome 生成的错误消息:
VM271 about:srcdoc:1 Ignored call to 'alert()'. The document is sandboxed, and the 'allow-modals' keyword is not set.
太棒了,如预期。

现在我需要构建一个 Cypress 测试来证明 iframe 上的行为是正确的。我最初打算通过监视 iframe/window 的 console.error 并检查带有上述错误消息的调用来完成此操作。这不起作用。我已经用间谍包装了 window、iframe 和 cypress 环境错误处理程序和

console.error
函数,当 Chrome 记录上述“忽略警报”错误消息时,它们都不会被调用。我还将 iframe
window.alert()
包裹在间谍中,它仍然被调用(如预期),但浏览器的警报模式没有显示(如预期,因为它被 chrome 忽略)。

有没有办法在这里捕获浏览器的“特殊”错误日志?如果不是通过浏览器窗口或 iframe 窗口元素记录它,那么它是如何记录的?

内嵌框架:

<iframe><script>alert('test');</script></iframe>

柏树:

let iframeWindow;
let spyErrorIframe;
cy.get('iframe').then(($iframe) => {
  iframeWindow = $iframe[0].contentWindow;
  function errorHandler(...args) {
    console.log('~~~ iframe');
    return iframeWindow.console.error(...args);
  }
  spyErrorIframe = cy.spy(errorHandler);
  iframeWindow.addEventListener('error', spyErrorIframe);
  iframeWindow.onerror = spyErrorIframe;
  cy.spy(iframeWindow.console, 'log');
  cy.spy(iframeWindow.console, 'error');
  cy.spy(iframeWindow, 'alert');
});

let mainWindow;
let spyErrorWindow;
cy.window().then((win) => {
  mainWindow = win;
  function errorHandler(...args) {
    console.log('~~~ window');
    return iframeWindow.console.error(...args);
  }
  spyErrorWindow = cy.spy(errorHandler);
  mainWindow.addEventListener('error', spyErrorWindow);
  mainWindow.onerror = spyErrorWindow;
  cy.spy(win, 'alert');
  cy.spy(win.console, 'log');
  cy.spy(win.console, 'error');
});

cy.wait(GENERIC_TIMEOUT + 1000).then(() => {
  console.log('~~~ iframe console.error', iframeWindow.console.error.getCalls()); // no calls
  console.log('~~~ window console.error', mainWindow.console.error.getCalls()); // no calls
  console.log('~~~ cypress console.error', console.error.getCalls()); // no calls
  console.log('~~~ iframe error event', spyErrorIframe.getCalls()); // no calls
  console.log('~~~ window error event', spyErrorWindow.getCalls()); // no calls
  console.log('~~~ iframe alert', iframeWindow.alert.getCalls()); // one call as expected
  console.log('~~~ window alert', mainWindow.alert.getCalls()); // no calls
});
javascript security iframe error-handling cypress
1个回答
0
投票

我想我应该尝试稍微简化一下问题,这适用于只会引发控制台错误的简化网页。

页面来源

<body>
  <iframe
    id="inlineFrameExample"
    title="Inline Frame Example"
    width="300"
    height="200"
    src="./frame1.html"
  >
  </iframe>
</body>

内框源码

<h1>iframe</h1>
<script>
  setTimeout(() => {
    console.error('Catch me')
  }, 500)
</script>

测试代码

我添加了 cypress-iframe,以防加载框架内容时出现一些延迟。

本演示仅关注

console.error
,但应与其他房地产间谍合作来实现
console.log
window.alert

在现实世界的示例中,为间谍使用别名会更好,因为

cy.wait()
可能需要不同的时间,具体取决于外部条件(网络速度、CI 平台)。

import 'cypress-iframe';

it('tests the iframe console.error', () => {

...


let iframeWindow;
let spyErrorIframe;

cy.enter().then(getBody => {
  getBody()
  .its('0.ownerDocument.defaultView')
  .then(win => {
    iframeWindow = win 

    function errorHandler(...args) {
      console.log('~~~ iframe');                           // log appears in console
      return iframeWindow.console.error(...args);
    }

    spyErrorIframe = cy.spy(iframeWindow.console, 'error', errorHandler)
      .as('spyErrorIframe')   
 
  })
})

// Using alias should means you don't have to wait
cy.get('@spyErrorIframe')
  .should('have.been.calledOnceWith', 'Catch me')           // passes

cy.wait(1000).then(() => {
  // one call logged
  console.log('~~~ iframe error event', spyErrorIframe.getCalls());     
})
© www.soinside.com 2019 - 2024. All rights reserved.