You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The page-ready check inserts the URL into a JavaScript template literal without escaping it, at src/choreographer/protocol/devtools_async_helpers.py:37. A backtick in the URL ends the literal, and a ${...} sequence in the URL runs as JavaScript.
Steps to reproduce
Run the following code:
importasyncioimportchoreographeraschoreofromchoreographer.protocol.devtools_async_helpersimportcreate_and_waitasyncdefmain():
browser=awaitchoreo.Browser(headless=True)
try:
# Correct: raises TimeoutError after 5s, because the address never loadsawaitcreate_and_wait(browser, url="http://192.0.2.1:9999", timeout=5.0)
exceptTimeoutError:
print("plain URL: TimeoutError")
# Wrong: returns after 0.02s, for the same unreachable addressawaitcreate_and_wait(browser, url="http://192.0.2.1:9999/`", timeout=5.0)
print("URL with a backtick: returned OK")
awaitbrowser.close()
asyncio.run(main())
For the second problem, pass https://www.example.com/${(window.__injected = 42, "")} to create_and_wait, then read window.__injected back from the page. The value is 42.
Notes
With this bug:
A backtick makes the script raise a SyntaxError. Runtime.evaluate returns that as a normal response, and the race in create_and_wait counts any finished task as a load. So create_and_wait returns a tab for a page that never loaded.
A ${...} sequence runs arbitrary JavaScript in the page.
A fix is to build the JavaScript string with json.dumps(url) and drop the backticks from the template. json.dumps supplies its own quotes and escapes the contents, so a backtick and a ${ are both inert.
create_and_wait should also inspect the response for exceptionDetails instead of counting every finished task as a successful load
Description
The page-ready check inserts the URL into a JavaScript template literal without escaping it, at
src/choreographer/protocol/devtools_async_helpers.py:37. A backtick in the URL ends the literal, and a${...}sequence in the URL runs as JavaScript.Steps to reproduce
For the second problem, pass
https://www.example.com/${(window.__injected = 42, "")}tocreate_and_wait, then readwindow.__injectedback from the page. The value is42.Notes
SyntaxError.Runtime.evaluatereturns that as a normal response, and the race increate_and_waitcounts any finished task as a load. Socreate_and_waitreturns a tab for a page that never loaded.${...}sequence runs arbitrary JavaScript in the page.json.dumps(url)and drop the backticks from the template.json.dumpssupplies its own quotes and escapes the contents, so a backtick and a${are both inert.create_and_waitshould also inspect the response forexceptionDetailsinstead of counting every finished task as a successful load