mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-19 08:14:40 +00:00
fix: more mini connector hardening
This commit is contained in:
1 parent
08e8de7370
commit
e8305ef137
4 files changed
+134
-23
No files matched your search
@@ -29,12 +29,15 @@ def _encode_state(payload):
|
||||
return base64.urlsafe_b64encode(json.dumps(payload).encode()).decode()
|
||||
|
||||
|
||||
def _seed_session(pg_conn, user, token, provider="google_drive"):
|
||||
def _seed_session(pg_conn, user, token, provider="google_drive", token_info=None):
|
||||
from docsgpt.storage.db.repositories.connector_sessions import ConnectorSessionsRepository
|
||||
|
||||
repo = ConnectorSessionsRepository(pg_conn)
|
||||
row = repo.upsert(user, provider, status="authorized")
|
||||
repo.update(str(row["id"]), {"session_token": token})
|
||||
patch_fields = {"session_token": token}
|
||||
if token_info:
|
||||
patch_fields["token_info"] = token_info
|
||||
repo.update(str(row["id"]), patch_fields)
|
||||
return repo
|
||||
|
||||
|
||||
@@ -131,6 +134,17 @@ class TestCallbackStatusPage:
|
||||
r = ConnectorCallbackStatus().get()
|
||||
assert "const targetOrigins = [];" in r.get_data(as_text=True)
|
||||
|
||||
def test_request_provider_never_reaches_inline_script(self, app):
|
||||
from docsgpt.api.connector.routes import ConnectorCallbackStatus
|
||||
|
||||
with app.test_request_context(
|
||||
"/api/connectors/callback-status?status=error&provider=zz-injected-provider"
|
||||
):
|
||||
r = ConnectorCallbackStatus().get()
|
||||
body = r.get_data(as_text=True)
|
||||
script = body[body.index("<script>"):body.index("</script>")]
|
||||
assert "zz-injected-provider" not in script
|
||||
|
||||
|
||||
class TestCallbackDeliversTokenSafely:
|
||||
def test_success_renders_page_without_redirecting_token(self, app, pg_conn):
|
||||
@@ -166,6 +180,7 @@ class TestCallbackDeliversTokenSafely:
|
||||
assert r.status_code == 200
|
||||
assert "Location" not in r.headers
|
||||
assert token in body
|
||||
assert '"type": "google_drive_auth_success"' in body
|
||||
assert '"https://app.example.com"' in body
|
||||
assert "'*'" not in body
|
||||
assert r.headers["Cache-Control"] == "no-store"
|
||||
@@ -334,3 +349,88 @@ class TestRemoteUploadSessionOwnership:
|
||||
|
||||
assert r.status_code == 200
|
||||
apply_mock.assert_called_once()
|
||||
|
||||
def test_rejects_session_issued_for_another_provider(self, app, pg_conn):
|
||||
_seed_session(pg_conn, "u-prov-up", "st-prov-up", provider="share_point")
|
||||
apply_mock = MagicMock(return_value=MagicMock(id="t"))
|
||||
|
||||
r = self._post(app, pg_conn, "u-prov-up", "st-prov-up", apply_mock)
|
||||
|
||||
assert r.status_code == 401
|
||||
apply_mock.assert_not_called()
|
||||
|
||||
|
||||
class TestSessionProviderBinding:
|
||||
def _files(self, app, pg_conn, user, provider, token, create_connector):
|
||||
from docsgpt.api.connector.routes import ConnectorFiles
|
||||
|
||||
with _patch_db(pg_conn), patch(
|
||||
"docsgpt.api.connector.routes.ConnectorCreator.create_connector", create_connector,
|
||||
), app.test_request_context(
|
||||
"/api/connectors/files", method="POST", json={"provider": provider, "session_token": token},
|
||||
):
|
||||
from flask import request
|
||||
request.decoded_token = {"sub": user}
|
||||
return ConnectorFiles().post()
|
||||
|
||||
def test_files_rejects_session_issued_for_another_provider(self, app, pg_conn):
|
||||
_seed_session(pg_conn, "u-files-prov", "st-files-prov", provider="google_drive")
|
||||
create_connector = MagicMock()
|
||||
|
||||
r = self._files(app, pg_conn, "u-files-prov", "share_point", "st-files-prov", create_connector)
|
||||
|
||||
assert r.status_code == 401
|
||||
create_connector.assert_not_called()
|
||||
|
||||
def test_files_matches_provider_case_insensitively(self, app, pg_conn):
|
||||
_seed_session(pg_conn, "u-files-case", "st-files-case", provider="google_drive")
|
||||
create_connector = MagicMock(return_value=MagicMock(load_data=MagicMock(return_value=[]), next_page_token=None))
|
||||
|
||||
r = self._files(app, pg_conn, "u-files-case", "Google_Drive", "st-files-case", create_connector)
|
||||
|
||||
assert r.status_code == 200
|
||||
create_connector.assert_called_once()
|
||||
|
||||
def test_validate_session_rejects_session_issued_for_another_provider(self, app, pg_conn):
|
||||
from docsgpt.api.connector.routes import ConnectorValidateSession
|
||||
|
||||
_seed_session(
|
||||
pg_conn, "u-val-prov", "st-val-prov", provider="google_drive", token_info={"access_token": "at"},
|
||||
)
|
||||
create_auth = MagicMock()
|
||||
with _patch_db(pg_conn), patch(
|
||||
"docsgpt.api.connector.routes.ConnectorCreator.create_auth", create_auth,
|
||||
), app.test_request_context(
|
||||
"/api/connectors/validate-session", method="POST",
|
||||
json={"provider": "share_point", "session_token": "st-val-prov"},
|
||||
):
|
||||
from flask import request
|
||||
request.decoded_token = {"sub": "u-val-prov"}
|
||||
r = ConnectorValidateSession().post()
|
||||
|
||||
assert r.status_code == 401
|
||||
create_auth.assert_not_called()
|
||||
|
||||
def test_sync_rejects_session_issued_for_another_provider(self, app, pg_conn):
|
||||
from docsgpt.api.connector.routes import ConnectorSync
|
||||
from docsgpt.storage.db.repositories.sources import SourcesRepository
|
||||
|
||||
user = "u-sync-prov"
|
||||
_seed_session(pg_conn, user, "st-sync-prov", provider="share_point")
|
||||
src = SourcesRepository(pg_conn).create(
|
||||
"drive-src", user_id=user,
|
||||
remote_data={"provider": "google_drive", "file_ids": ["f"], "folder_ids": []},
|
||||
)
|
||||
delay = MagicMock()
|
||||
with _patch_db(pg_conn), patch(
|
||||
"docsgpt.api.connector.routes.ingest_connector_task.delay", delay,
|
||||
), app.test_request_context(
|
||||
"/api/connectors/sync", method="POST",
|
||||
json={"source_id": str(src["id"]), "session_token": "st-sync-prov"},
|
||||
):
|
||||
from flask import request
|
||||
request.decoded_token = {"sub": user}
|
||||
r = ConnectorSync().post()
|
||||
|
||||
assert r.status_code == 401
|
||||
delay.assert_not_called()
|
||||
Reference in new issue
Block a user