File size: 3,413 Bytes
98e4465
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15d6506
98e4465
 
 
 
 
 
 
 
15d6506
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98e4465
 
 
 
15d6506
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98e4465
 
 
 
 
 
 
 
15d6506
98e4465
 
 
 
 
 
 
 
 
 
 
 
 
 
15d6506
98e4465
 
15d6506
 
98e4465
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
from fastapi.testclient import TestClient

from agent.tools.sandbox_client import _SANDBOX_SERVER, Sandbox


def _sandbox_app(
    monkeypatch,
    token: str | None = "sandbox-secret",
    *,
    hf_token: str | None = None,
):
    monkeypatch.delenv("SANDBOX_API_TOKEN", raising=False)
    monkeypatch.delenv("HF_TOKEN", raising=False)
    if token is not None:
        monkeypatch.setenv("SANDBOX_API_TOKEN", token)
    if hf_token is not None:
        monkeypatch.setenv("HF_TOKEN", hf_token)
    namespace = {}
    exec(_SANDBOX_SERVER, namespace)
    return namespace["app"]


def test_health_is_public(monkeypatch):
    client = TestClient(_sandbox_app(monkeypatch))

    response = client.get("/api/health")

    assert response.status_code == 200
    assert response.json() == {"status": "ok"}


def test_file_and_command_routes_require_bearer_token(monkeypatch):
    client = TestClient(_sandbox_app(monkeypatch, "sandbox-secret"))

    response = client.post("/api/exists", json={"path": "/tmp"})

    assert response.status_code == 401


def test_file_and_command_routes_reject_authorization_bearer_token(monkeypatch):
    client = TestClient(_sandbox_app(monkeypatch, "sandbox-secret"))

    response = client.post(
        "/api/exists",
        json={"path": "/tmp"},
        headers={"Authorization": "Bearer sandbox-secret"},
    )

    assert response.status_code == 401


def test_file_and_command_routes_accept_sandbox_header_with_hf_bearer(monkeypatch):
    client = TestClient(
        _sandbox_app(monkeypatch, "sandbox-secret", hf_token="hf-secret")
    )

    response = client.post(
        "/api/exists",
        json={"path": "/tmp"},
        headers={
            "Authorization": "Bearer hf-secret",
            "X-Sandbox-Authorization": "Bearer sandbox-secret",
        },
    )

    assert response.status_code == 200
    assert response.json()["success"] is True


def test_hf_bearer_alone_is_rejected_when_sandbox_token_is_configured(monkeypatch):
    client = TestClient(
        _sandbox_app(monkeypatch, "sandbox-secret", hf_token="hf-secret")
    )

    response = client.post(
        "/api/exists",
        json={"path": "/tmp"},
        headers={"Authorization": "Bearer hf-secret"},
    )

    assert response.status_code == 401


def test_legacy_hf_token_fallback_is_rejected(monkeypatch):
    client = TestClient(_sandbox_app(monkeypatch, token=None, hf_token="hf-secret"))

    response = client.post(
        "/api/exists",
        json={"path": "/tmp"},
        headers={"Authorization": "Bearer hf-secret"},
    )

    assert response.status_code == 503


def test_protected_routes_fail_closed_without_configured_token(monkeypatch):
    client = TestClient(_sandbox_app(monkeypatch, None))

    response = client.post(
        "/api/exists",
        json={"path": "/tmp"},
        headers={"Authorization": "Bearer anything"},
    )

    assert response.status_code == 503


def test_sandbox_sends_hub_auth_and_control_plane_header():
    sandbox = Sandbox("owner/name", token="hf-token", api_token="sandbox-secret")

    assert sandbox._client.headers["authorization"] == "Bearer hf-token"
    assert sandbox._client.headers["x-sandbox-authorization"] == "Bearer sandbox-secret"


def test_sandbox_api_token_is_hidden_from_repr():
    sandbox = Sandbox("owner/name", token="hf-token", api_token="sandbox-secret")

    assert "sandbox-secret" not in repr(sandbox)