From 35e7e005929fd91ddbc427cb246775c80daae2ae Mon Sep 17 00:00:00 2001 From: junjun Date: Thu, 17 Sep 2026 15:23:43 +0800 Subject: [PATCH] fix: Cross-Workspace Data-Source Schema Disclosure and Modification (Incomplete IDOR Remediation) --- backend/apps/datasource/api/datasource.py | 7 ++++--- backend/apps/datasource/crud/datasource.py | 18 +++++++++++++++--- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/backend/apps/datasource/api/datasource.py b/backend/apps/datasource/api/datasource.py index bc7115db..f1ca6a29 100644 --- a/backend/apps/datasource/api/datasource.py +++ b/backend/apps/datasource/api/datasource.py @@ -166,8 +166,9 @@ async def get_fields(session: SessionDep, @router.post("/syncFields/{ds_id}/{id}", response_model=None, summary=f"{PLACEHOLDER_PREFIX}ds_sync_fields") @require_permissions(permission=SqlbotPermission(role=['ws_admin'], type='ds', keyExpression="ds_id")) async def sync_fields(session: SessionDep, trans: Trans, + ds_id: int = Path(..., description=f"{PLACEHOLDER_PREFIX}ds_id"), id: int = Path(..., description=f"{PLACEHOLDER_PREFIX}ds_table_id")): - return sync_single_fields(session, trans, id) + return sync_single_fields(session, trans, ds_id, id) from pydantic import BaseModel @@ -215,13 +216,13 @@ async def field_list(session: SessionDep, field: FieldObj, @router.post("/editTable", response_model=None, summary=f"{PLACEHOLDER_PREFIX}ds_edit_table") -@require_permissions(permission=SqlbotPermission(role=['ws_admin'], type='ds', keyExpression="ds_id")) +@require_permissions(permission=SqlbotPermission(role=['ws_admin'], type='ds', keyExpression="table.ds_id")) async def edit_table(session: SessionDep, table: CoreTable): updateTable(session, table) @router.post("/editField", response_model=None, summary=f"{PLACEHOLDER_PREFIX}ds_edit_field") -@require_permissions(permission=SqlbotPermission(role=['ws_admin'], type='ds', keyExpression="ds_id")) +@require_permissions(permission=SqlbotPermission(role=['ws_admin'], type='ds', keyExpression="field.ds_id")) async def edit_field(session: SessionDep, field: CoreField): updateField(session, field) diff --git a/backend/apps/datasource/crud/datasource.py b/backend/apps/datasource/crud/datasource.py index 9e727a3b..67bb9759 100644 --- a/backend/apps/datasource/crud/datasource.py +++ b/backend/apps/datasource/crud/datasource.py @@ -121,7 +121,8 @@ def update_ds(session: SessionDep, trans: Trans, user: CurrentUser, ds: CoreData def update_ds_recommended_config(session: SessionDep, datasource_id: int, recommended_config: int): # 使用 update 语句直接更新,避免 ORM 追踪问题 from sqlalchemy import update - stmt = update(CoreDatasource).where(CoreDatasource.id == datasource_id).values(recommended_config=recommended_config) + stmt = update(CoreDatasource).where(CoreDatasource.id == datasource_id).values( + recommended_config=recommended_config) session.execute(stmt) session.commit() @@ -181,8 +182,10 @@ def execSql(session: SessionDep, id: int, sql: str): return exec_sql(ds, sql, True) -def sync_single_fields(session: SessionDep, trans: Trans, id: int): - table = session.query(CoreTable).filter(CoreTable.id == id).first() +def sync_single_fields(session: SessionDep, trans: Trans, ds_id: int, id: int): + table = session.query(CoreTable).filter(and_(CoreTable.id == id, CoreTable.ds_id == ds_id)).first() + if not table: + raise HTTPException(status_code=500, detail='The data source ID does not match the table ID') ds = session.query(CoreDatasource).filter(CoreDatasource.id == table.ds_id).first() tables = getTablesByDs(session, ds) @@ -289,6 +292,10 @@ def update_table_and_fields(session: SessionDep, data: TableObj): def updateTable(session: SessionDep, table: CoreTable): + obj = session.query(CoreTable).filter(and_(CoreTable.id == table.id, CoreTable.ds_id == table.ds_id)).first() + if not obj: + raise HTTPException(status_code=500, detail='The data source ID does not match the table ID') + update_table(session, table) # do table embedding @@ -297,6 +304,11 @@ def updateTable(session: SessionDep, table: CoreTable): def updateField(session: SessionDep, field: CoreField): + obj = session.query(CoreField).filter( + and_(CoreField.id == field.id, CoreField.table_id == field.table_id, CoreField.ds_id == field.ds_id)).first() + if not obj: + raise HTTPException(status_code=500, detail='Resource ID does not matched') + update_field(session, field) # do table embedding