Skip to content

crypto.randomUUID is not a function when running locally #2326

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
antocuni opened this issue Apr 4, 2025 · 11 comments · Fixed by #2328
Closed

crypto.randomUUID is not a function when running locally #2326

antocuni opened this issue Apr 4, 2025 · 11 comments · Fixed by #2328

Comments

@antocuni
Copy link
Contributor

antocuni commented Apr 4, 2025

This is the content of my directory:
index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Proud Sunset</title>

    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">

    <link rel="stylesheet" href="https://pyscript.net/releases/2025.3.1/core.css">
    <script type="module" src="https://pyscript.net/releases/2025.3.1/core.js"></script>
</head>

<body>
    <script type="py" src="./main.py" config="./pyscript.toml" terminal></script>
</body>
</html>

pyscript.toml:

name = "Bug"

main.py:

print("hello world")

I tried to start a local web server:

❯ python -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

When opening the browser, the page is completely blank, and devtools shows this:

Uncaught TypeError: crypto.randomUUID is not a function
  at main.js:43:26

The same code works fine on pyscript.com:
https://pyscript.com/@antocuni/lingering-sound/latest

@WebReflection
Copy link
Contributor

WebReflection commented Apr 4, 2025

it's either https or http://localhost:$PORT/ 80% of the modern Web features won't work in non secured environments (or localhost) and we can't put try/catch around static import dependencies so this feels like a good section for our F.A.Q. section in the docs.

expanding even if we did a try catch, our static dependencies are resolved and run before ... we can't intercept errors in there before our code gets even a chance to run

P.S. by localhost I literally mean it ... it's not 127.0.0.1 or 0.0.0.0 it's gotta be localhost which gives browsers "special powers", it's not our choice, it's how browsers, or the Web, work these days. Dare I say http.server should actually hint to reach localhost instead of 0.0.0.0 as that has a special meaning for the IP, internally, but it breaks everything in a browser.

P.S.2 MDN seems to disagree around 127.0.0.1 which is a loopback hole thing that might be treated differently but for sure localhost enables https features, except those that need special headers (and I am sure that'll be your next issue with http.server, have a look at our docs or about workers) so I suggest always to test stuff in localhost, no IP based addresses.

@WebReflection
Copy link
Contributor

@antocuni
Copy link
Contributor Author

antocuni commented Apr 4, 2025

thank you! I confirm that with http://localhost it works.

I don't know how hard it is (and if it's even possible), but from the "naive user" point of view, I think it would be nice to detect the "non secure environment" case and display a nice error in the DOM, possibly with a link to the FAQ.

@WebReflection
Copy link
Contributor

and if it's even possible

that's the issue ... as soon as any dependency uses features that require https or localhost, which is the norm for modern Web development, we can't intercept those calls so we put a copy and paste error in our docs that explains what's going on but a search in any search engine would reveal the exact same issue (and solution) all over the Web ... in this case crypto.randomUUUID() is just the tip of the iceberg, pretty much everything else we do in here would fail out of http so it's actually good that error happens when the env is potentially poisoned because users should not ignore that error and the page can't (or shouldn't) work if not properly served in a secure way.

In short, static import happens before our code runs, if those throws already, our code won't run.

I would close this and maybe think about a way, at least in our stack, to mitigate the issue but I feel like it'd be quite a rewrite and for little gain ... I believe WASM features can be also half/broken in non secured/localhost env 🥲

@antocuni
Copy link
Contributor Author

antocuni commented Apr 4, 2025

What I was thinking is something like:

// at the very beginning of core.js
if (not_a_secure_environment()) {
    document.appendChild("<div class="error">Pyscript cannot work on a non secure env, see the FAQ</div>");
}

@WebReflection
Copy link
Contributor

WebReflection commented Apr 4, 2025

that cannot work because there are static imports which have absolute priority over the code that is importing ... it doesn't matter if you import after that line, static imports (needed to bundle) are always before anything happening in your module.

// a.js
console.log('a');

import './b.js';
// b.js
console.log('b');

when you run a.js you'll read b then a.

if b.js throws you'll never see that logged a.

@antocuni
Copy link
Contributor Author

antocuni commented Apr 4, 2025

sorry if I say nonsense, as you know my JS knowledge is very limited 😅.
Maybe what I'm about to propose doesn't make any sense but...
Can't we bundle a detect-insecure-env.js and write the code in such a way that it's the first to be statically imported (and thus has the chance to write a nice error message before anything else fails)?

@WebReflection
Copy link
Contributor

We could have a top module import in core but even the error logic is in another module that could have 3rd party dependencies but I’ll give it a shot and see if that works

@WebReflection WebReflection reopened this Apr 5, 2025
@antocuni
Copy link
Contributor Author

antocuni commented Apr 5, 2025

Sounds good to me. Note that these are just my 2 cents, feel free to ignore my suggestions if you think it's low priority.
That said, I suppose that it's a mistake that other people might do (simply because it's very easy to just click on the link printed by python -m http.server), so would be nice to save them from it.

Thanks!

@WebReflection
Copy link
Contributor

We could go further and just redirect from 0.0.0.0 to localhost out of the box … even less to do for users, no issues in importing modules that might use trusted APIs … less to learn though, yet convenient?

@antocuni
Copy link
Contributor Author

antocuni commented Apr 6, 2025

I like it :)

WebReflection added a commit to WebReflection/pyscript that referenced this issue Apr 7, 2025
WebReflection added a commit to WebReflection/pyscript that referenced this issue Apr 7, 2025
WebReflection added a commit to WebReflection/pyscript that referenced this issue Apr 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants