Skip to content

[BUG]: Some JS characters aren't escaped when running the page-ready check #316

Description

@camdecoster

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

  • Run the following code:
import asyncio
import choreographer as choreo
from choreographer.protocol.devtools_async_helpers import create_and_wait

async def main():
    browser = await choreo.Browser(headless=True)
    try:
        # Correct: raises TimeoutError after 5s, because the address never loads
        await create_and_wait(browser, url="http://192.0.2.1:9999", timeout=5.0)
    except TimeoutError:
        print("plain URL: TimeoutError")
    # Wrong: returns after 0.02s, for the same unreachable address
    await create_and_wait(browser, url="http://192.0.2.1:9999/`", timeout=5.0)
    print("URL with a backtick: returned OK")
    await browser.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
  • This was found while working on fix: Update URL comparison check #295

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3not needed for current cyclebugsomething brokensize: 1

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions