import pytest from fastapi.testclient import TestClient @pytest.fixture def frontend(tmp_path, monkeypatch): from backend.app import main root = tmp_path / 'dist' root.mkdir() (root / 'index.html').write_text('Public AppOps frontend') (root / 'icon.svg').write_text('public-icon') (tmp_path / 'outside.txt').write_text('private-test-marker') monkeypatch.setattr(main, 'static_root', root) return TestClient(main.app), root @pytest.mark.parametrize('path', ['/%2e%2e/outside.txt', '/%2e%2e%2foutside.txt', '/%2fetc/passwd']) def test_public_frontend_rejects_encoded_path_escapes(frontend, path): client, _ = frontend response = client.get(path) assert response.status_code == 404 assert 'private-test-marker' not in response.text def test_public_frontend_serves_assets_and_spa_routes(frontend): client, _ = frontend assert client.get('/icon.svg').text == 'public-icon' assert 'Public AppOps frontend' in client.get('/settings').text assert client.get('/api/nonexistent').status_code in {401, 404} def test_public_frontend_rejects_symlink_escape(frontend): client, root = frontend try: (root / 'escaped.txt').symlink_to(root.parent / 'outside.txt') except OSError: pytest.skip('Symlinks unavailable on this host') assert client.get('/escaped.txt').status_code == 404