Files
document-haness/docs/clean-architecture-backend-template/tech-log-studio/web-inbound-and-http-surface/case/case-analysis-finding-a14-f004.md
T
DongHyeonkaandClaude Fable 5.1 b25357c48a docs(clean-architecture-backend-template): fold analysis into final and re-select one topic
- analysis/·source-index·state.json 을 final/document.md 제2부·제3부로 접었다. SSOT 는 하나다
- 파일럿 — commit-ambiguity-as-a-result 를 새 기준으로 재선별. 후보 14 → 글감 5
  (PROMOTE 5 · MERGE_INTO 3 · KEEP_IN_SSOT 4 · 보류 2). 기록 5건을 다시 썼고 그림 1개를
  techviz 로 만들었다
- 재선별이 잡은 것: 제1부 §6.2·§11.1 이 자기 §13.2 와 어긋나 있었다(레인을 안 돌렸다 vs
  돌렸다) — 정정. 이미 답이 나와 있던 Question 을 HEAD 재실행 질문으로 다시 세웠다.
  Concept 이 인용한 코드가 SSOT 에 없어 뺐다
- candidateScope·sourceRepository 기록. 나머지 43개 주제는 재선별 대기(PENDING 905)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-07 12:39:20 +09:00

131 lines
6.1 KiB
Markdown

---
kind: CASE
slug: analysis-finding-a14-f004
title: 프레임워크 자유 신원 모델과 교차 테넌트 가드가 프로덕션에서 한 번도 참조되지 않는다
topic: web-inbound-and-http-surface
project: clean-architecture-backend-template
status: 게시 전
sourceRevision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916
rootTreeNode: case:analysis-finding-a14-f004
evidenceCapturedOn: 2026-09-01
body: case-analysis-finding-a14-f004.body.md
assets:
- key: analysis-finding-a14-f004
file: ../../../final/evidence/rendered/analysis-finding-a14-f004.svg
evidence:
- ../../../final/evidence/raw/analysis-finding-a14-f004.txt
source:
- 원본 분석 절은 final/document.md#a14#L562 이다.
---
# 프레임워크 자유 신원 모델과 교차 테넌트 가드가 프로덕션에서 한 번도 참조되지 않는다
보안 패키지 열한 파일이 서로만 참조하고 바깥에서 들어오는 화살표가 없다. 그 안에 클라이언트가 소속을 제안하는 헤더를 거부하는 가드가 있는데, 도달 경로의 호출자가 테스트뿐이다. 지금 이 플랫폼은 그 헤더를 거부도 무시도 하지 않는다.
## 관계
- **플랫폼 요청 컨텍스트가 서블릿에는 생산자가 없고 리액티브에는 익명 액터로 고정되어 있다**
이 가드를 고칠 때 함께 연결해야 하는 사례다.
- **용량 보호 계층 전체가 자기 테스트 픽스처 안에서만 실행된다**
같은 리프의 같은 형태다.
- **노출이 없는 것과 가드가 작동하는 것은 다르다**
이 사례가 그 규칙의 형태다.
## 문제
이 리프에 프레임워크에 의존하지 않는 신원 모델이 있다.
그 패키지가 바깥에서 쓰이는지 확인했다.
## 결론
쓰이지 않는다.
보안 패키지 열한 파일이 서로만 참조하고 바깥에서 들어오는 화살표가 없다.
인증 조회 값을 만드는 production 코드가 없으므로 보안 문맥 다리의 해석 메서드가 호출될 수 있는 상태 자체가 없다.
가장 값이 큰 부분이 그 안에 있다.
소속 문맥 해석기가 클라이언트가 소속을 제안하는 헤더 이름 넷을 알고 있고, 그 이름이 요청 입력에 있으면 거부 예외를 던진다.
도달 경로는 보안 문맥 다리의 두 인자 오버로드 하나뿐이고, 그 오버로드의 호출자는 테스트뿐이다.
그래서 지금 이 플랫폼은 그 헤더에 대해 거부도 무시도 하지 않는다. 그 헤더를 보는 코드가 아예 없다.
노출은 아니다.
소속을 소비하는 유일한 지점이 요청 컨텍스트의 소속을 읽는데, 그 값은 다른 사례 때문에 항상 비어 있다.
헤더가 소속이 되는 경로가 없으므로 교차 소속 읽기도 없다.
그러나 그것은 가드가 작동해서가 아니라 소속 기능 전체가 배선되지 않아서다.
요청 컨텍스트를 고치면서 이 가드를 함께 연결하지 않으면, 그때 노출이 생긴다.
이 패키지에는 교차 출처 정책 검증기와 위조 방지 정책 해석기도 있고 둘 다 production 참조가 0 이다.
실제 두 결정은 보안 설정이 프레임워크 API 로 직접 내린다.
같은 질문에 대한 두 번째 구현이 검증만 되고 쓰이지 않는다.
판정은 P2 다.
## 검증 환경
Spring Boot : 4.0.8
확인 방식 : 패키지 간 참조 방향 확인과 호출자 전수 검색
소스 수정 : x
## 재현 조건
원문은 final/evidence/raw/176 계열에 있다.
1. 보안 패키지의 파일 목록을 만든다.
2. 각 타입을 참조하는 바깥 코드를 검색한다.
3. 소속 해석기의 거부 메서드 도달 경로를 확인한다.
4. 그 경로의 호출자를 센다.
5. 소속을 소비하는 지점이 읽는 값이 무엇인지 확인한다.
6. 교차 출처와 위조 방지 결정이 실제로 어디서 내려지는지 확인한다.
## 본문
<!-- body:start -->
`security` 패키지 11개 파일이 서로만 참조하고 바깥에서 들어오는 화살표가 없다(§11.1).
## AuthenticationView 참조 위치
:::evidence key="analysis-finding-a14-f004" alt="코드베이스에서 AuthenticationView 를 검색한 출력 5줄. 이 기록이 세는 참조가 그 출력에 그대로 보인다." caption="AuthenticationView 코드베이스 검색 — 5줄 · exit 0" zoom="true"
:::
## 호출될 수 있는 상태 자체가 없다
`AuthenticationView`를 만드는 프로덕션 코드가 없으므로 `WebSecurityContextBridge.resolve(...)`가 호출될 수 있는 상태 자체가 없다.
## 가장 값이 큰 부분이 그 안에 있다
```java
// WebTenantContextResolver.java
private static final Set<String> TENANT_INPUT_NAMES =
Set.of("x-tenant-id", "tenant-id", "tenantid", "tenant");
public void rejectTenantInput(Map<String, String> requestInput) { ... throw new UntrustedTenantInputException(); }
```
클라이언트가 테넌트를 제안하는 헤더를 거부하는 가드다. 도달 경로는 `WebSecurityContextBridge.resolve(authentication, requestInput)` 오버로드 하나뿐이고, 그 오버로드의 호출자는 테스트뿐이다. 그래서 지금 이 플랫폼은 `X-Tenant-Id` 헤더에 대해 **거부도 무시도 하지 않는다** — 그 헤더를 보는 코드가 아예 없다.
## 노출은 아니지만 가드가 작동해서가 아니다
테넌트를 소비하는 유일한 지점(`OperationAccessPolicy:37-40`)이 `context.tenant()`를 읽고, 그 값은 §12.1 때문에 항상 비어 있다. 헤더가 테넌트가 되는 경로가 없으므로 교차 테넌트 읽기도 없다. 그러나 그것은 **테넌트 기능 전체가 배선되지 않아서**다. §12.1을 고치면서 이 가드를 함께 연결하지 않으면 그때 노출이 생긴다.
## 같은 질문에 대한 두 번째 구현
이 패키지에는 `WebCorsPolicyValidator`(96줄)와 `WebCsrfPolicyResolver`(43줄)도 있고 둘 다 프로덕션 참조 0이다. 실제 CORS·CSRF 결정은 `SecurityConfig`가 Spring Security API로 직접 내린다. P2.
## 확인하지 못한 것
소속 제안 헤더를 붙여 요청을 보내 아무 일도 일어나지 않는 것을 재현하지 않았다. 참조 부재상 그 결과가 나온다.
<!-- body:end -->