POOOLING FOREST
[긴급] LangChain Core 보안 취약점 분석과 대응 가이드 (CVE-2025-68664) - LangChain Core에서 발견된 치명적 보안 취약점(CVE-2025-68664)의 기술적 원리와 대응
Engineering & Tech

[긴급] LangChain Core 보안 취약점 분석과 대응 가이드 (CVE-2025-68664)

LangChain Core에서 발견된 치명적 보안 취약점(CVE-2025-68664)의 기술적 원리와 대응 방안을 분석합니다. 직렬화의 함정과 환경 변수 탈취 위험을 확인하세요.

김영태

테크리드

안녕하세요, 8년차 개발자 김테크입니다.

연말연시 다들 잘 보내셨나요? 개발자들에게 연말이란 트래픽과의 전쟁이거나, 혹은 조용히 밀린 기술 부채를 갚는 시간이죠. 그런데 이번 크리스마스 시즌에는 AI 진영에서 꽤 심각한 보안 이슈가 하나 터졌습니다. 일명 랭그린치(LangGrinch)라고 불리는 LangChain Core의 취약점(CVE-2025-68664)입니다.

오늘은 이 취약점이 왜 위험한지, 기술적으로 어떤 원리로 작동하는지, 그리고 우리 백엔드 엔지니어들이 어떻게 대응해야 하는지 실무 관점에서 풀어보겠습니다.

LangChain을 사용 중인 팀이라면 오늘 글을 꼭 정독하시고 바로 버전 확인부터 하시길 바랍니다.

1. 왜 이 취약점이 중요한가?

보통 프레임워크의 취약점은 특정 플러그인이나 잘 안 쓰는 엣지 케이스에서 발견되곤 합니다. 하지만 이번 건은 다릅니다. 바로 langchain-core 자체에서 발견되었습니다.

LangChain은 현재 전 세계적으로 가장 널리 쓰이는 AI 프레임워크 중 하나입니다. 수억 건의 다운로드를 기록하고 있죠. Core에 문제가 있다는 건, LangChain을 사용하는 거의 모든 애플리케이션이 잠재적 위험에 노출되었다는 뜻입니다.

가장 무서운 점은 공격 벡터입니다. 거창한 해킹 툴이 필요한 게 아닙니다. LLM이 생성한 텍스트나 사용자의 프롬프트 한 줄만으로도 내부 시스템의 연쇄 반응을 일으켜 익스플로잇을 촉발할 수 있습니다.

2. 기술적 분석: 직렬화의 함정

이 취약점의 핵심은 객체의 직렬화(Serialization)와 역직렬화(Deserialization) 과정에 있습니다. LangChain은 내부적으로 객체를 저장하거나 전송하기 위해 딕셔너리 형태로 직렬화합니다. 이때 이 딕셔너리가 단순 데이터인지, 아니면 LangChain의 실행 가능한 객체인지를 구분하기 위해 lc라는 특수한 키(Key)를 사용합니다.

문제는 dumps()dumpd() 함수에 있었습니다.

사용자가 입력한 데이터나 LLM이 생성한 응답 딕셔너리에 우연히, 혹은 악의적으로 lc라는 키가 포함되어 있다고 가정해 봅시다. 정상적인 보안 로직이라면 "어? 이건 사용자가 만든 데이터니까 실행 가능한 객체로 변환하면 안 돼"라고 판단하고 이스케이프(Escape) 처리를 해야 합니다.

하지만 패치 이전 버전에서는 이 과정이 누락되었습니다. 즉, 공격자가 lc 키를 포함한 정교한 딕셔너리를 주입하면, 시스템은 이를 안전한 데이터가 아니라 시스템 내부의 신뢰할 수 있는 객체로 착각하고 역직렬화를 수행해 버립니다.

이해를 돕기 위해 개념적인 코드를 살펴보겠습니다.

# 공격자가 주입할 수 있는 악성 페이로드 예시 (개념적)
malicious_payload = {
    "lc": 1,
    "type": "constructor",
    "id": ["langchain", "some_dangerous_class"],
    "kwargs": {
        "api_key": "공격자가_원하는_값",
        # ... 기타 위험한 파라미터
    }
}

# 취약한 버전에서는 이 페이로드가 필터링 없이 직렬화되었다가,
# 로드(load) 되는 순간 해당 클래스가 실제로 인스턴스화 됩니다.
# from langchain_core.load import load
# load(malicious_payload) -> 위험한 객체 생성 및 실행

3. 실제 발생할 수 있는 피해

단순히 객체가 생성되는 게 뭐가 문제냐고 생각하실 수 있습니다. 하지만 LangChain의 구조를 들여다보면 상황이 심각해집니다.

첫째, 환경 변수 탈취입니다.

LangChain의 많은 컴포넌트들은 초기화될 때 API 키 같은 비밀 정보를 환경 변수에서 가져옵니다. 이번 취약점 보고서에 따르면 secrets_from_env=True 옵션이 역직렬화 시 기본값이었습니다. 공격자가 특정 객체를 역직렬화하도록 유도하면, 서버의 환경 변수에 저장된 AWS 키나 OpenAI 키 같은 민감한 정보를 추출해낼 수 있는 경로가 열립니다.

둘째, 부작용(Side Effects) 발생입니다.

허용된 리스트(Allowlist)에 있는 클래스라 하더라도, 생성자가 실행될 때 네트워크 호출을 하거나 파일 시스템에 접근하는 경우가 있습니다. 공격자는 이를 이용해 SSRF(Server-Side Request Forgery) 같은 공격을 트리거할 수 있습니다.

셋째, 임의 코드 실행(RCE)입니다.

특정 조건이 맞아떨어지면 단순한 객체 생성을 넘어 서버에서 임의의 코드를 실행할 수 있는 상황까지 갈 수 있습니다. CVSS 점수가 9.3(치명적)으로 매겨진 이유가 바로 이것입니다.

4. 대응 방법

다행히 대응 방법은 명확합니다. LangChain 팀은 이 문제를 인지하고 빠르게 패치를 내놓았습니다.

업데이트 필수

현재 운영 중인 LangChain 패키지를 다음 버전 이상으로 즉시 업데이트해야 합니다.

  • langchain-core: 0.3.29 이상

  • langchain: 0.3.13 이상

  • 구버전을 사용 중이라면 1.2.5 또는 0.3.81 버전으로 패치되었습니다.

개발자의 마음가짐: 신뢰의 경계

이번 사태가 우리에게 주는 교훈은 명확합니다. "AI 모델의 출력도 신뢰할 수 없는 데이터로 취급해야 한다"는 것입니다.

우리는 보통 사용자의 입력(Input)에 대해서는 SQL 인젝션 등을 방어하며 꼼꼼하게 검증합니다. 하지만 LLM이 뱉어내는 출력(Output)이나, 프레임워크 내부에서 도는 데이터에 대해서는 상대적으로 관대한 경향이 있습니다.

하지만 LLM 애플리케이션에서 프롬프트 인젝션이 발생하면, LLM의 출력조차 공격자가 통제하는 데이터가 될 수 있습니다. 이번 취약점은 바로 그 '신뢰의 구간'이라고 믿었던 곳을 찌르고 들어온 것입니다.

추가 인자(additional_kwargs)나 응답 메타데이터(response_metadata) 같은 필드에 공격 코드가 섞여 들어갈 수 있다는 점을 항상 기억해야 합니다.

마치며

보안은 언제나 "설마 여기까지?"라고 생각하는 지점에서 뚫립니다. 특히 AI 생태계처럼 발전 속도가 빠르고 복잡도가 높은 환경에서는 기본을 지키는 것이 무엇보다 중요합니다.

지금 당장 pip list | grep langchain을 입력해 버전을 확인해 보세요. 여러분의 서비스는 안전한가요?

김테크였습니다. 감사합니다.

지금 읽으신 내용, 귀사에 적용해보고 싶으신가요?

상황과 목표를 알려주시면 가능한 옵션과 현실적인 도입 경로를 제안해드립니다.