d9f1c8325a
ci / lint-prettier (push) Failing after 8s
ci / lint-ruff (push) Successful in 4s
ci / lint-yaml (push) Failing after 7s
ci / lint-dockerfiles (push) Successful in 4s
ci / validate (push) Successful in 5s
deploy / redeploy (push) Failing after 0s
ci / build (push) Has been skipped
ci / deploy-userbot-panel (push) Has been skipped
- ensure_prerequisites runs on startup, not per-request; kube config errors surface as 503 PanelError - serialize provisioning with a lock; drop per-endpoint prereq checks - guard SPA fallback against path traversal (relative_to) - add backend tests for auth flow, k8s service, spa routing; ci comment for legacy userbot deployments
49 lines
1.5 KiB
Python
49 lines
1.5 KiB
Python
from pathlib import Path
|
|
|
|
import pytest
|
|
from app.main import spa_fallback
|
|
|
|
|
|
@pytest.fixture
|
|
def static_dir(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Path:
|
|
static = tmp_path / "static"
|
|
static.mkdir()
|
|
(static / "index.html").write_text("<html>index</html>", encoding="utf-8")
|
|
(static / "app.js").write_text("console.log('app')", encoding="utf-8")
|
|
secret = tmp_path / "secret.txt"
|
|
secret.write_text("TOP SECRET", encoding="utf-8")
|
|
monkeypatch.setattr("app.main.static_dir", static)
|
|
return static
|
|
|
|
|
|
def static_index(static_dir: Path) -> Path:
|
|
return static_dir / "index.html"
|
|
|
|
|
|
def test_returns_existing_file(static_dir: Path) -> None:
|
|
response = spa_fallback("app.js")
|
|
assert response.path == static_dir / "app.js"
|
|
|
|
|
|
def test_unknown_path_falls_back_to_index(static_dir: Path) -> None:
|
|
response = spa_fallback("does/not/exist.js")
|
|
assert response.path == static_index(static_dir)
|
|
|
|
|
|
def test_traversal_does_not_leak_outside_static(static_dir: Path) -> None:
|
|
response = spa_fallback("../secret.txt")
|
|
assert response.path == static_index(static_dir)
|
|
|
|
response = spa_fallback("%2e%2e/secret.txt")
|
|
assert response.path == static_index(static_dir)
|
|
|
|
|
|
def test_symlink_outside_static_is_blocked(static_dir: Path, tmp_path: Path) -> None:
|
|
target = tmp_path / "outside.txt"
|
|
target.write_text("secret", encoding="utf-8")
|
|
link = static_dir / "leak.txt"
|
|
link.symlink_to(target)
|
|
|
|
response = spa_fallback("leak.txt")
|
|
assert response.path == static_index(static_dir)
|