e93507a09c
Lockfile supply-chain audit / lockfile supply-chain audit (push) Has been cancelled
Windows Studio GGUF CI / GPU prebuilt resolves without Visual Studio (push) Has been cancelled
Windows Studio GGUF CI / setup.ps1 unit tests (VS 2026 / CMake guard) (push) Has been cancelled
Windows Studio GGUF CI / real-VS detection (VS 2022) (push) Has been cancelled
Windows Studio GGUF CI / real-VS detection (VS 2026) (push) Has been cancelled
Windows Studio GGUF CI / VC++ runtime detect + install round-trip (windows-2025-vs2026) (push) Has been cancelled
Windows Studio GGUF CI / VC++ runtime detect + install round-trip (windows-latest) (push) Has been cancelled
Windows Studio Update CI / Studio Updating Tests (push) Has been cancelled
Wheel CI / Wheel build + content sanity + import smoke (push) Has been cancelled
Lint CI / Source lint (Python + shell + YAML + JSON + safety nets) (push) Has been cancelled
MLX CI on Mac M1 / dispatch (push) Has been cancelled
Security audit / advisory audit (pip + npm + cargo) (push) Has been cancelled
Security audit / pip scan-packages :: extras (push) Has been cancelled
Security audit / pip scan-packages :: studio (push) Has been cancelled
Security audit / pip scan-packages :: hf-stack (push) Has been cancelled
Security audit / npm scan-packages (Studio frontend tarballs) (push) Has been cancelled
Security audit / workflow-trigger lint (pull_request_target / cache-poisoning) (push) Has been cancelled
Security audit / pytest tests/security (push) Has been cancelled
Security audit / npm provenance + new install-script diff (push) Has been cancelled
Studio API CI / Studio API & Auth Tests (push) Has been cancelled
Backend CI / (Python 3.10) (push) Has been cancelled
Backend CI / (Python 3.11) (push) Has been cancelled
Backend CI / (Python 3.12) (push) Has been cancelled
Backend CI / (Python 3.13) (push) Has been cancelled
Backend CI / Repo tests (CPU) (push) Has been cancelled
Frontend CI / Frontend build + bundle sanity (push) Has been cancelled
Studio GGUF CI / OpenAI, Anthropic API tests (push) Has been cancelled
Studio GGUF CI / Tool calling Tests (push) Has been cancelled
Studio GGUF CI / JSON, images (push) Has been cancelled
Mac Studio GGUF CI / OpenAI, Anthropic API tests (push) Has been cancelled
Mac Studio GGUF CI / Tool calling Tests (push) Has been cancelled
Mac Studio GGUF CI / JSON, images (push) Has been cancelled
Mac Studio Install Matrix CI / Install + load (macos-14) (push) Has been cancelled
Mac Studio Install Matrix CI / Install + load (macos-15) (push) Has been cancelled
Mac Studio Install Matrix CI / Install + load (macos-26) (push) Has been cancelled
Mac Studio Install Matrix CI / Install + load (macos-15-intel) (push) Has been cancelled
Mac Studio API CI / Studio API & Auth Tests (push) Has been cancelled
Mac Studio Install Matrix CI / Install + load (macos-26-intel) (push) Has been cancelled
Mac Studio UI CI / Chat UI Tests (push) Has been cancelled
Studio Tauri CI / Tauri Linux debug build (no codesign) (push) Has been cancelled
Mac Studio Update CI / Studio Updating Tests (push) Has been cancelled
Studio UI CI / Chat UI Tests (push) Has been cancelled
Windows Studio API CI / Studio API & Auth Tests (push) Has been cancelled
Windows Studio UI CI / Chat UI Tests (push) Has been cancelled
Studio Update CI / Studio Updating Tests (push) Has been cancelled
Core / Core (HF=default + TRL=default) (push) Has been cancelled
Core / Core (HF=4.57.6 + TRL<1) (push) Has been cancelled
Core / Core (HF=latest + TRL=latest) (push) Has been cancelled
Core / llama.cpp build + smoke (push) Has been cancelled
Windows Studio GGUF CI / OpenAI, Anthropic API tests (push) Has been cancelled
Windows Studio GGUF CI / Tool calling Tests (push) Has been cancelled
Windows Studio GGUF CI / JSON, images (push) Has been cancelled
Windows Studio GGUF CI / Studio install + inference without Visual Studio (push) Has been cancelled
Studio export capability / capability (macos-latest) (push) Has been cancelled
Studio export capability / capability (ubuntu-latest) (push) Has been cancelled
Studio export capability / capability (windows-latest) (push) Has been cancelled
Cross-platform parity / parity (macos-latest) (push) Has been cancelled
Cross-platform parity / parity (windows-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
Studio load-orchestrator CI / test (push) Has been cancelled
190 lines
7.0 KiB
Python
190 lines
7.0 KiB
Python
# SPDX-License-Identifier: AGPL-3.0-only
|
|
# Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0
|
|
|
|
"""Extra edge-case coverage for the bootstrap-pw cross-origin gate.
|
|
Companion to ``test_index_bootstrap_origin.py``: IPv6 netlocs, opaque origins
|
|
(``data:``, ``blob:``), comma-joined multi-Origin headers, and the
|
|
``localhost`` vs ``127.0.0.1`` distinct-origin rule.
|
|
"""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
|
|
def _build_request(
|
|
host: str,
|
|
origin,
|
|
scheme: str = "http",
|
|
) -> MagicMock:
|
|
request = MagicMock()
|
|
request.url.scheme = scheme
|
|
request.url.netloc = host
|
|
request.headers = {"origin": origin} if origin is not None else {}
|
|
return request
|
|
|
|
|
|
# ── IPv6 ────────────────────────────────────────────────────────────
|
|
|
|
|
|
def test_is_same_origin_request_ipv6_loopback_same_origin():
|
|
"""Studio supports ``-H ::1`` binds; netloc is ``[::1]:8902``. Bare
|
|
``partition(":")`` mis-parses the bracketed form and would refuse the
|
|
bootstrap on legitimate same-origin navigation.
|
|
"""
|
|
from main import _is_same_origin_request
|
|
|
|
req = _build_request("[::1]:8902", origin = "http://[::1]:8902")
|
|
assert _is_same_origin_request(req) is True
|
|
|
|
|
|
def test_is_same_origin_request_ipv6_full_address_same_origin():
|
|
from main import _is_same_origin_request
|
|
req = _build_request(
|
|
"[2001:db8::1]:8443",
|
|
origin = "https://[2001:db8::1]:8443",
|
|
scheme = "https",
|
|
)
|
|
assert _is_same_origin_request(req) is True
|
|
|
|
|
|
def test_is_same_origin_request_ipv6_default_port_stripped():
|
|
"""Browser drops :80 on ``http://[::1]``."""
|
|
from main import _is_same_origin_request
|
|
|
|
req = _build_request("[::1]:80", origin = "http://[::1]")
|
|
assert _is_same_origin_request(req) is True
|
|
|
|
|
|
def test_is_same_origin_request_ipv6_case_insensitive():
|
|
"""Hex digits in IPv6 are case-insensitive per RFC 5952."""
|
|
from main import _is_same_origin_request
|
|
|
|
req = _build_request(
|
|
"[2001:DB8::1]:8443",
|
|
origin = "https://[2001:db8::1]:8443",
|
|
scheme = "https",
|
|
)
|
|
assert _is_same_origin_request(req) is True
|
|
|
|
|
|
def test_is_same_origin_request_ipv6_different_host_cross_origin():
|
|
from main import _is_same_origin_request
|
|
req = _build_request("[::1]:8902", origin = "http://[2001:db8::1]:8902")
|
|
assert _is_same_origin_request(req) is False
|
|
|
|
|
|
def test_is_same_origin_request_ipv6_port_mismatch_cross_origin():
|
|
from main import _is_same_origin_request
|
|
req = _build_request("[::1]:8902", origin = "http://[::1]:9999")
|
|
assert _is_same_origin_request(req) is False
|
|
|
|
|
|
def test_is_same_origin_request_ipv6_userinfo_stripped():
|
|
from main import _is_same_origin_request
|
|
req = _build_request("user:pass@[::1]:8902", origin = "http://[::1]:8902")
|
|
assert _is_same_origin_request(req) is True
|
|
|
|
|
|
# ── Opaque origins (data:, blob:) ───────────────────────────────────
|
|
|
|
|
|
def test_is_same_origin_request_data_url_origin_is_cross_origin():
|
|
"""``data:`` URLs are opaque origins (HTML living standard); no host, never same-origin."""
|
|
from main import _is_same_origin_request
|
|
|
|
req = _build_request("127.0.0.1:8902", origin = "data:text/html,<script>alert(1)</script>")
|
|
assert _is_same_origin_request(req) is False
|
|
|
|
|
|
def test_is_same_origin_request_blob_url_origin_is_cross_origin():
|
|
"""``blob:`` URLs carry the inner origin only in non-canonical form; the canonical comparison rejects them."""
|
|
from main import _is_same_origin_request
|
|
|
|
req = _build_request("127.0.0.1:8902", origin = "blob:http://127.0.0.1:8902/uuid")
|
|
assert _is_same_origin_request(req) is False
|
|
|
|
|
|
def test_is_same_origin_request_file_url_origin_is_cross_origin():
|
|
"""``file://`` pages usually send ``Origin: null``; older engines sent
|
|
``Origin: file://``. Neither is same-origin vs an http listener.
|
|
"""
|
|
from main import _is_same_origin_request
|
|
|
|
req = _build_request("127.0.0.1:8902", origin = "file://")
|
|
assert _is_same_origin_request(req) is False
|
|
|
|
|
|
# ── Multi-Origin header (comma-joined by Starlette) ────────────────
|
|
|
|
|
|
def test_is_same_origin_request_comma_joined_origins_cross_origin():
|
|
"""Starlette joins repeated headers with ``, ``; the canonical parser can't
|
|
safely split this, so it falls to cross-origin.
|
|
"""
|
|
from main import _is_same_origin_request
|
|
|
|
req = _build_request(
|
|
"127.0.0.1:8902",
|
|
origin = "http://127.0.0.1:8902, http://evil.example",
|
|
)
|
|
assert _is_same_origin_request(req) is False
|
|
|
|
|
|
# ── localhost vs 127.0.0.1 (distinct origins per web platform) ──────
|
|
|
|
|
|
def test_is_same_origin_request_localhost_vs_127_is_cross_origin():
|
|
"""Browsers treat ``localhost`` and ``127.0.0.1`` as distinct origins; the
|
|
canonical comparison must not DNS-collapse them.
|
|
"""
|
|
from main import _is_same_origin_request
|
|
|
|
req = _build_request("127.0.0.1:8902", origin = "http://localhost:8902")
|
|
assert _is_same_origin_request(req) is False
|
|
|
|
|
|
def test_is_same_origin_request_127_vs_localhost_is_cross_origin():
|
|
from main import _is_same_origin_request
|
|
req = _build_request("localhost:8902", origin = "http://127.0.0.1:8902")
|
|
assert _is_same_origin_request(req) is False
|
|
|
|
|
|
# ── urlparse ValueError robustness ─────────────────────────────────
|
|
|
|
|
|
def test_is_same_origin_request_malformed_ipv6_bracket_is_cross_origin():
|
|
"""``urlparse`` raises ``ValueError('Invalid IPv6 URL')`` on unclosed
|
|
brackets (CVE-2024-11168 hardening). The gate must swallow it and fall to
|
|
cross-origin rather than 500 the SPA handler.
|
|
"""
|
|
from main import _is_same_origin_request
|
|
|
|
req = _build_request("127.0.0.1:8902", origin = "http://[malformed")
|
|
assert _is_same_origin_request(req) is False
|
|
|
|
|
|
def test_is_same_origin_request_invalid_ipv6_address_is_cross_origin():
|
|
"""Bracketed but invalid IPv6 (e.g. ``[::g]``) also raises
|
|
``ValueError`` inside ``urlparse``."""
|
|
from main import _is_same_origin_request
|
|
|
|
req = _build_request("127.0.0.1:8902", origin = "http://[::g]:8902")
|
|
assert _is_same_origin_request(req) is False
|
|
|
|
|
|
def test_is_same_origin_request_bracket_with_trailing_garbage_is_cross_origin():
|
|
"""Text after the closing bracket also raises inside ``urlparse``."""
|
|
from main import _is_same_origin_request
|
|
|
|
req = _build_request("127.0.0.1:8902", origin = "http://[2001:db8::1]extra:8902")
|
|
assert _is_same_origin_request(req) is False
|
|
|
|
|
|
def test_is_same_origin_request_empty_origin_header_is_cross_origin():
|
|
"""Explicit empty ``Origin:`` is not a valid serialised origin and must not
|
|
be conflated with a missing header; cross-origin, bootstrap withheld.
|
|
"""
|
|
from main import _is_same_origin_request
|
|
|
|
req = _build_request("127.0.0.1:8902", origin = "")
|
|
assert _is_same_origin_request(req) is False
|