From: Kristján Valur Jónsson Date: Sun, 30 Nov 2025 11:57:01 +0000 (+0000) Subject: 🐛 Fix hierarchical security scope propagation (#5624) X-Git-Tag: 0.122.1~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=378ad688b7e57efb190506b3b36be65eb8ad5e6f;p=thirdparty%2Ffastapi%2Ffastapi.git 🐛 Fix hierarchical security scope propagation (#5624) Co-authored-by: Sebastián Ramírez Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Co-authored-by: svlandeg Co-authored-by: Sofie Van Landeghem --- diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index 1e92c1ba2a..45353835b4 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -278,7 +278,9 @@ def get_dependant( use_security_scopes = security_scopes or [] if isinstance(param_details.depends, params.Security): if param_details.depends.scopes: - use_security_scopes.extend(param_details.depends.scopes) + use_security_scopes = use_security_scopes + list( + param_details.depends.scopes + ) sub_dependant = get_dependant( path=path, call=param_details.depends.dependency, diff --git a/tests/test_security_scopes_dont_propagate.py b/tests/test_security_scopes_dont_propagate.py new file mode 100644 index 0000000000..2bbcc749d3 --- /dev/null +++ b/tests/test_security_scopes_dont_propagate.py @@ -0,0 +1,45 @@ +# Ref: https://github.com/tiangolo/fastapi/issues/5623 + +from typing import Any, Dict, List + +from fastapi import FastAPI, Security +from fastapi.security import SecurityScopes +from fastapi.testclient import TestClient +from typing_extensions import Annotated + + +async def security1(scopes: SecurityScopes): + return scopes.scopes + + +async def security2(scopes: SecurityScopes): + return scopes.scopes + + +async def dep3( + dep1: Annotated[List[str], Security(security1, scopes=["scope1"])], + dep2: Annotated[List[str], Security(security2, scopes=["scope2"])], +): + return {"dep1": dep1, "dep2": dep2} + + +app = FastAPI() + + +@app.get("/scopes") +def get_scopes( + dep3: Annotated[Dict[str, Any], Security(dep3, scopes=["scope3"])], +): + return dep3 + + +client = TestClient(app) + + +def test_security_scopes_dont_propagate(): + response = client.get("/scopes") + assert response.status_code == 200 + assert response.json() == { + "dep1": ["scope3", "scope1"], + "dep2": ["scope3", "scope2"], + }