new file mode 100644
@@ -0,0 +1,125 @@
+From 7eb4a2aafe49a279c29b6d1f0ed0f42e9736194f Mon Sep 17 00:00:00 2001
+From: Illia Volochii <illia.volochii@gmail.com>
+Date: Wed, 18 Jun 2025 16:30:35 +0300
+Subject: [PATCH] Merge commit from fork
+
+CVE: CVE-2025-50182
+Upstream-Status: Backport [https://github.com/urllib3/urllib3/commit/7eb4a2aafe49a279c29b6d1f0ed0f42e9736194f]
+
+Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
+---
+ docs/reference/contrib/emscripten.rst | 2 +-
+ src/urllib3/contrib/emscripten/fetch.py | 20 ++++++++++
+ test/contrib/emscripten/test_emscripten.py | 46 ++++++++++++++++++++++
+ 3 files changed, 67 insertions(+), 1 deletion(-)
+
+diff --git a/docs/reference/contrib/emscripten.rst b/docs/reference/contrib/emscripten.rst
+index a8f1cda..4670757 100644
+--- a/docs/reference/contrib/emscripten.rst
++++ b/docs/reference/contrib/emscripten.rst
+@@ -65,7 +65,7 @@ Features which are usable with Emscripten support are:
+ * Timeouts
+ * Retries
+ * Streaming (with Web Workers and Cross-Origin Isolation)
+-* Redirects (determined by browser/runtime, not restrictable with urllib3)
++* Redirects (urllib3 controls redirects in Node.js but not in browsers where behavior is determined by runtime)
+ * Decompressing response bodies
+
+ Features which don't work with Emscripten:
+diff --git a/src/urllib3/contrib/emscripten/fetch.py b/src/urllib3/contrib/emscripten/fetch.py
+index a514306..6695821 100644
+--- a/src/urllib3/contrib/emscripten/fetch.py
++++ b/src/urllib3/contrib/emscripten/fetch.py
+@@ -573,6 +573,11 @@ def send_jspi_request(
+ "method": request.method,
+ "signal": js_abort_controller.signal,
+ }
++ # Node.js returns the whole response (unlike opaqueredirect in browsers),
++ # so urllib3 can set `redirect: manual` to control redirects itself.
++ # https://stackoverflow.com/a/78524615
++ if _is_node_js():
++ fetch_data["redirect"] = "manual"
+ # Call JavaScript fetch (async api, returns a promise)
+ fetcher_promise_js = js.fetch(request.url, _obj_from_dict(fetch_data))
+ # Now suspend WebAssembly until we resolve that promise
+@@ -693,6 +698,21 @@ def has_jspi() -> bool:
+ return False
+
+
++def _is_node_js() -> bool:
++ """
++ Check if we are in Node.js.
++
++ :return: True if we are in Node.js.
++ :rtype: bool
++ """
++ return (
++ hasattr(js, "process")
++ and hasattr(js.process, "release")
++ # According to the Node.js documentation, the release name is always "node".
++ and js.process.release.name == "node"
++ )
++
++
+ def streaming_ready() -> bool | None:
+ if _fetcher:
+ return _fetcher.streaming_ready
+diff --git a/test/contrib/emscripten/test_emscripten.py b/test/contrib/emscripten/test_emscripten.py
+index 5eaa674..fbf89fc 100644
+--- a/test/contrib/emscripten/test_emscripten.py
++++ b/test/contrib/emscripten/test_emscripten.py
+@@ -960,6 +960,52 @@ def test_redirects(
+ )
+
+
++@pytest.mark.with_jspi
++def test_disabled_redirects(
++ selenium_coverage: typing.Any, testserver_http: PyodideServerInfo
++) -> None:
++ """
++ Test that urllib3 can control redirects in Node.js.
++ """
++
++ @run_in_pyodide # type: ignore[misc]
++ def pyodide_test(selenium_coverage: typing.Any, host: str, port: int) -> None:
++ import pytest
++
++ from urllib3 import PoolManager, request
++ from urllib3.contrib.emscripten.fetch import _is_node_js
++ from urllib3.exceptions import MaxRetryError
++
++ if not _is_node_js():
++ pytest.skip("urllib3 does not control redirects in browsers.")
++
++ redirect_url = f"http://{host}:{port}/redirect"
++
++ with PoolManager(retries=0) as http:
++ with pytest.raises(MaxRetryError):
++ http.request("GET", redirect_url)
++
++ response = http.request("GET", redirect_url, redirect=False)
++ assert response.status == 303
++
++ with PoolManager(retries=False) as http:
++ response = http.request("GET", redirect_url)
++ assert response.status == 303
++
++ with pytest.raises(MaxRetryError):
++ request("GET", redirect_url, retries=0)
++
++ response = request("GET", redirect_url, redirect=False)
++ assert response.status == 303
++
++ response = request("GET", redirect_url, retries=0, redirect=False)
++ assert response.status == 303
++
++ pyodide_test(
++ selenium_coverage, testserver_http.http_host, testserver_http.http_port
++ )
++
++
+ def test_insecure_requests_warning(
+ selenium_coverage: typing.Any, testserver_http: PyodideServerInfo
+ ) -> None:
+--
+2.40.0
@@ -9,6 +9,7 @@ inherit pypi python_hatchling
SRC_URI += " \
file://CVE-2025-50181.patch \
+ file://CVE-2025-50182.patch \
"
DEPENDS += " \