FastAPI 0.140.0-0.141.1 버전에서는 응답 모델(response model) 없이 일반 딕셔너리(dictionary)나 리스트(list)를 반환하는 라우트의 경우, Pydantic의 Secret 클래스로 감싸진 원본 값이 노출될 수 있습니다. 이 유출로 인해 개발자가 숨기려 했던 비밀번호, API 키 또는 기타 자격 증명이 드러날 수 있습니다.

이 버그가 중요한 이유

FastAPI는 뷰 함수(view function)의 반환 타입을 검사하여 JSON 응답을 생성합니다. 응답 모델을 제공하면 FastAPI는 해당 객체를 Pydantic에 전달하며, Pydantic은 SecretStr"**********"로 마스킹 처리합니다. 문제가 되는 버전에서는 프레임워크가 내장된 SecretStr 타입만 인식합니다. 만약 Secret을 상속받거나(또는 커스텀 시크릿 타입을 사용하거나) 일반 딕셔너리나 리스트 안에 객체를 담아 반환하면, FastAPI는 일반적인 객체-딕셔너리 변환(object-to-dict conversion) 방식을 사용하게 됩니다. 이 변환 과정에서 실제 비밀 값을 보유한 프라이빗 속성(private attribute)에 접근하게 되어, 값이 변경되지 않은 채 클라이언트로 전송됩니다.

유출은 다음 세 가지 조건이 모두 충족될 때만 발생합니다:

  • 시크릿 타입이 Pydantic의 Secret 기본 클래스를 상속받음.
  • 라우트에 응답 모델이 선언되어 있지 않음.
  • 뷰가 일반 dict 또는 list 안에 시크릿을 담아 반환함.

지금 바로 시크릿을 보호하는 방법

  • 시크릿이 포함된 데이터를 반환할 수 있는 모든 엔드포인트에 응답 모델을 선언하세요. 그러면 FastAPI가 Pydantic을 통해 직렬화(serialization)를 처리하게 되어 값이 올바르게 마스킹됩니다.
  • 일반 컨테이너를 반환하는 대신 시크릿을 Pydantic BaseModel 필드 내에 포함시키세요. 모델의 필드 타입을 인식 가능한 시크릿 클래스로 지정하면 적절한 처리가 보장됩니다.
  • 현재의 반환 방식을 유지해야 한다면, 시크릿 서브클래스에 대해 커스텀 JSON 인코더를 등록하세요. 인코더가 마스킹된 표현식("**********")을 반환하도록 설정할 수 있습니다.

심각도 및 커뮤니티 대응

이 문제는 심각도가 낮습니다. 발생하려면 특정 설정이 필요하지만, 자격 증명이 실수로 노출되는 것은 특히 공개 API나 응답을 로그로 남기는 서비스에서 위험 요소가 될 수 있습니다.

요약: 응답 모델을 누락하면 의도적으로 만든 시크릿 래퍼(wrapper)가 데이터 유출 통로가 될 수 있습니다. FastAPI에서 내장 수정 사항이 나올 때까지 명시적인 응답 모델을 추가하거나 커스텀 인코더를 사용하는 것은 자격 증명을 숨길 수 있는 저렴하고 신뢰할 수 있는 방법입니다.