-
Notifications
You must be signed in to change notification settings - Fork 0
🎨 Palette: Swagger UI 인증 정보 유지 기능 추가 #775
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
9355b96
0a4b4da
340272e
31bf14c
6c4a584
623b14f
bbaed06
281ace5
282d5d9
31d441f
d919954
ad06fc5
db02668
69d9f69
d6085a2
cc918a8
7dea6f6
b581cbb
e8a8375
ad0616d
af7386e
75f895e
b26d998
4d701f9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| """Regression tests for the interactive API documentation security boundary.""" | ||
|
|
||
| from fastapi.testclient import TestClient | ||
|
|
||
| from newsdom_api.config import AuthenticationMode, RuntimeProfile, RuntimeSettings | ||
| from newsdom_api.main import create_app | ||
|
|
||
| LOCKED_DOWN_CSP = "default-src 'none'; frame-ancestors 'none'; base-uri 'none'" | ||
|
|
||
|
|
||
| def _settings(profile: RuntimeProfile) -> RuntimeSettings: | ||
| """Build an authenticated runtime configuration for one profile.""" | ||
|
|
||
| return RuntimeSettings( | ||
| authentication_mode=AuthenticationMode.REQUIRED, | ||
| runtime_profile=profile, | ||
| api_token="swagger-test-token", | ||
| ) | ||
|
|
||
|
|
||
| def test_swagger_authorization_persistence_is_development_only() -> None: | ||
| """Persist bearer authorization only in the explicit development profile.""" | ||
|
|
||
| production = TestClient(create_app(_settings(RuntimeProfile.PRODUCTION))) | ||
| development = TestClient(create_app(_settings(RuntimeProfile.DEVELOPMENT))) | ||
|
|
||
| production_docs = production.get("/docs") | ||
| development_docs = development.get("/docs") | ||
|
|
||
| assert production_docs.status_code == 200 | ||
| assert development_docs.status_code == 200 | ||
| assert '"persistAuthorization": false' in production_docs.text | ||
| assert '"persistAuthorization": true' in development_docs.text | ||
| assert '"validatorUrl": null' in development_docs.text | ||
|
Comment on lines
+30
to
+34
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- test file outline ---'
ast-grep outline tests/test_swagger_docs_security.py
printf '%s\n' '--- targeted test sections ---'
sed -n '1,140p' tests/test_swagger_docs_security.py
printf '%s\n' '--- documentation/CSP definitions and routes ---'
rg -n -C 8 'Content-Security-Policy|LOCKED_DOWN_CSP|oauth2-redirect|docs' src/newsdom_api tests/test_swagger_docs_security.pyRepository: ContextualWisdomLab/newsdom-api Length of output: 11220 Security Misconfiguration (CWE-693) CSP 정책 전체와 모든 변경 경로를 검증하세요. 개발 🤖 Prompt for AI AgentsSource: Coding guidelines |
||
|
|
||
|
|
||
| def test_swagger_csp_allows_only_required_origins_in_each_profile() -> None: | ||
| """Swagger UI can execute in each runtime profile with a route-scoped CSP.""" | ||
|
|
||
| for profile in (RuntimeProfile.PRODUCTION, RuntimeProfile.DEVELOPMENT): | ||
| client = TestClient(create_app(_settings(profile))) | ||
| response = client.get("/docs") | ||
|
|
||
| assert response.status_code == 200 | ||
| csp = response.headers["Content-Security-Policy"] | ||
| assert "default-src 'none'" in csp | ||
| assert "script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net" in csp | ||
| assert "style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net" in csp | ||
| assert "img-src 'self' data: https://fastapi.tiangolo.com" in csp | ||
| assert "connect-src 'self'" in csp | ||
| assert "frame-ancestors 'none'" in csp | ||
| assert "base-uri 'none'" in csp | ||
| assert "form-action 'self'" in csp | ||
|
|
||
|
|
||
| def test_redoc_csp_allows_only_required_origins_in_each_profile() -> None: | ||
| """ReDoc can load its script, fonts, schema and favicon in each profile.""" | ||
|
|
||
| for profile in (RuntimeProfile.PRODUCTION, RuntimeProfile.DEVELOPMENT): | ||
| client = TestClient(create_app(_settings(profile))) | ||
| response = client.get("/redoc") | ||
|
|
||
| assert response.status_code == 200 | ||
| csp = response.headers["Content-Security-Policy"] | ||
| assert "default-src 'none'" in csp | ||
| assert "script-src 'self' https://cdn.jsdelivr.net" in csp | ||
| assert "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com" in csp | ||
| assert "font-src 'self' https://fonts.gstatic.com" in csp | ||
| assert "img-src 'self' data: https://fastapi.tiangolo.com" in csp | ||
| assert "connect-src 'self'" in csp | ||
| assert "frame-ancestors 'none'" in csp | ||
| assert "base-uri 'none'" in csp | ||
| assert "form-action 'self'" in csp | ||
|
|
||
|
|
||
| def test_non_docs_responses_keep_the_locked_down_csp() -> None: | ||
| """The docs exception must not weaken the API response security boundary.""" | ||
|
|
||
| for profile in (RuntimeProfile.PRODUCTION, RuntimeProfile.DEVELOPMENT): | ||
| client = TestClient(create_app(_settings(profile)), base_url="https://testserver") | ||
| response = client.get("/health") | ||
|
|
||
| assert response.status_code == 200 | ||
| assert response.headers["Content-Security-Policy"] == LOCKED_DOWN_CSP | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟨 Production documentation weakens CSP
Production documentation loads third-party assets through
SWAGGER_DOCS_CSPandREDOC_DOCS_CSP. Compromised CDNs can execute code within the API origin.Was this helpful? React with 👍 or 👎 to provide feedback.