fix(backend): 공개 헬스 엔드포인트가 인프라 상세를 인증 없이 노출하던 문제 - #185
Merged
Conversation
마지막 점검에서 나왔다. `/api/system/*` 는 permitAll 인데 컴포넌트 상세를 그대로 담고 있었다:
"rabbitmq": { "version": "4.3.5" }
"s3": { "bucket": "stackup" }
"aiServer": { "queue": "ai.generate.questions", "consumers": 1, "pendingMessages": 0 }
Actuator 는 기본값이 `show-details: never` 다. 그런데 `SystemHealthService` 가 descriptor 에서
상세를 직접 꺼내 자기 응답에 담으면서 **그 보호를 우회**하고 있었다. RabbitMQ 버전은 알려진
CVE 를 겨냥하는 데 쓰이고, 버킷명·큐 이름·적체량은 내부 토폴로지와 부하를 그대로 드러낸다.
`rabbitmq` 상세는 #183(키 오타 수정)으로, `s3`·`aiServer` 상세는 #184(indicator 구현)로
오늘 내가 늘린 것이다 — 늘린 김에 닫는다.
`ComponentHealthResponse` 에서 `details` 를 제거해 **이름·상태만** 담는다. 프로브 용도에는
그것으로 충분하고, 상세가 필요하면 호스트에서 Spring 자체 `/actuator/health` 를 본다
(nginx 가 외부로 라우팅하지 않는 것을 확인했다 — 공개 URL 로는 SPA HTML 이 돌아온다).
반사(reflection)로 상세를 꺼내던 `extractDetails` 도 함께 사라진다.
프론트·realtime 어디서도 이 엔드포인트를 호출하지 않아 소비자 영향은 없다.
테스트: `health_doesNotExposeComponentDetails` — 상태는 전달되지만 응답 타입에 상세 필드가
아예 없다는 것을 record 컴포넌트로 못 박는다.
## 함께: frontend/.env.example 의 잘못된 호스트
`VITE_API_BASE_URL`·`VITE_SSE_BASE_URL` 가 `https://www.udangtang.site` 를 가리키고 있었다.
실제 배포 호스트는 `https://stack-up.shop` 다(deploy-app.yml 이 프론트 빌드에 주입하는 값).
새로 온 사람이 그대로 복사하면 존재하지 않는 백엔드를 보게 된다.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
변경 사항
마지막 점검에서 나왔다.
/api/system/*는SecurityConfig의 permitAll 목록에 있는데, 컴포넌트 상세를 그대로 담고 있었다:Actuator 는 기본값이
show-details: never다. 그런데SystemHealthService가HealthDescriptor에서 상세를 직접 꺼내 자기 응답에 담으면서 그 보호를 우회하고 있었다.이 중 대부분은 오늘 내가 늘렸다.
rabbitmq상세는 #183(키 오타 수정)으로 처음 나오기 시작했고,s3·aiServer상세는 #184(indicator 구현)로 추가했다. 늘린 김에 닫는다.수정
ComponentHealthResponse에서details를 제거해 이름·상태만 담는다./actuator/health를 본다. 외부로 라우팅되지 않는 것을 확인했다 — 공개 URL 로/actuator/health를 치면 SPA HTML 이 돌아온다(nginx 가 백엔드로 넘기지 않음)extractDetails도 함께 사라진다(원래도ReflectiveOperationException을 삼키던 취약한 코드였다)프론트·realtime 어디서도 이 엔드포인트를 호출하지 않아(생성 타입에만 존재) 소비자 영향은 없다.
테스트
health_doesNotExposeComponentDetails— 상태는 그대로 전달되지만 응답 타입에 상세 필드가 아예 없다는 것을RecordComponent로 못 박는다. 다시 추가하려면 이 테스트를 지워야 하므로 의도가 드러난다.기존 테스트의 상세 단언은 제거했다(필드 자체가 없어졌다).
함께:
frontend/.env.example의 잘못된 호스트점검 중 발견.
VITE_API_BASE_URL·VITE_SSE_BASE_URL가https://www.udangtang.site를 가리키고 있었다. 실제 배포 호스트는https://stack-up.shop다 —deploy-app.yml이 프론트 빌드에 주입하는 값이 진실이다. 새로 온 사람이 그대로 복사하면 존재하지 않는 백엔드를 본다.영향 범위
ComponentHealthResponse.details제거. 소비자 없음 확인.env.example문서값만 교정)리뷰어 체크포인트
/api/system/health를 permitAll 에서 빼는 선택지도 있다. 프로브가/live·/ready만 쓰면 가능하다