FlawOpen

flawopen.com/AI Security/semantic-kernel-inmemory-vector-filter-cve-2026-26030

● CVE-2026-26030 · CVSS 9.9[1] · 심각
보안 연구 · FlawOpen

Semantic Kernel CVE-2026-26030: 필터 코드 인젝션

프롬프트 영향을 받은 벡터 필터가 AST 검사를 우회해 Python eval에 도달했습니다. SDK 1.39.4 이상으로 업데이트하세요.[1], [4]

CVSS 벡터CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H[1]
💡 알기 쉬운 설명 (ELI5)

검색 규칙 카드에서 익숙한 단어를 확인한 사서가 컴퓨터에 카드 전체를 작은 프로그램처럼 실행하라고 하는 장면을 떠올려 보세요. 카드에 영향을 줄 수 있는 사람은 검사의 빈틈을 이용할 수 있습니다. CVE-2026-26030은 모델 영향을 받은 필터가 데이터 검색에서 애플리케이션 프로세스 내부 코드 실행으로 넘어가게 했습니다.[4]

핵심 개념 및 용어

InMemoryVectorStore
Semantic Kernel 프로세스 내 벡터 저장소이며 검색 전에 레코드를 필터링할 수 있습니다.[4]
Filter expression
레코드가 벡터 검색 결과에 포함될지 정하는 조건식입니다. 취약한 Python 경로는 문자열 필터를 Python 표현식으로 파싱하고 평가했습니다.[4]
Abstract Syntax Tree (AST)
파싱한 코드의 구조적 표현입니다. 불완전한 AST 검사는 Python 객체 인트로스펙션 경로를 남길 수 있습니다.[2], [4]
Prompt injection
신뢰할 수 없는 텍스트가 AI 모델에 영향을 주어 의도하지 않은 작업을 유도합니다. 애플리케이션이 모델 입력을 취약한 필터에 전달할 때 위험합니다.[4]

프레임워크 매핑

  • 이 가이드에서 설명하는 약점의 CWE 참조: CWE-94

단계별 공격 실행 흐름

단계 1

취약한 필터 경로가 배포됨

Semantic Kernel Python 1.39.4 미만과 InMemoryVectorStore 필터가 대상입니다. Microsoft는 Critical(CVSS 3.1 9.9, CWE-94)로 평가하고 1.39.4 이상을 권고합니다.[1], [4]

단계 2

신뢰할 수 없는 콘텐츠가 모델 선택 필터에 영향

공격에는 에이전트 입력을 바꾸는 프롬프트 인젝션 경로와 기본 필터를 사용하는 Search Plugin이 필요합니다. 타입 지정 도구 호출도 모델 생성 필터를 신뢰 가능하게 만들지 않습니다.[4]

단계 3

필터가 Python 코드로 바뀜

수정 전에는 필터를 AST로 파싱하고 builtins를 제거한 뒤 평가했지만 객체 모델 탐색을 충분히 제한하지 못했습니다. 1.39.4는 레코드 필드 접근을 위해 ast.Subscript를 허용하면서 AST 노드 허용 목록, 위험 속성 차단 목록, 단독 이름을 lambda 매개변수로 제한하는 검사, 호출 허용 목록을 함께 적용합니다. 업스트림 코드는 첨자 접근 자체를 거부하지 않으며 builtins를 제거한 eval도 샌드박스가 아닙니다.[2], [4]

단계 4

실행이 애플리케이션 프로세스에 도달

검사를 우회하면 공격자 영향을 받은 로직이 에이전트 Python 프로세스에서 실행될 수 있습니다. 범위는 OS 권한, 환경, 자격 증명, 네트워크 접근성에 달려 있습니다.[4]

단계 5

파서 경계를 수정하고 노출 조사

semantic-kernel을 1.39.4 이상으로 업데이트하세요. 패치는 위험 속성을 검사하고 이름을 lambda 매개변수로 제한합니다. 영향을 받은 기간의 프로세스, 네트워크, 자격 증명 이상을 조사하세요.[1], [2], [3], [4]

소스 코드 비교: 취약한 구현 vs 보안 패치

취약 코드 패널은 제품의 원본 코드가 아닌 대표 패턴입니다. 모델 제어 값이 eval 전에 Python 구문에 삽입됩니다. 수정 패널은 업스트림 1.39.4 검사를 발췌합니다. 구성된 AST 허용 목록은 레코드 필드 접근을 위해 ast.Subscript를 의도적으로 포함하며, 위험 속성 차단, 단독 이름을 lambda 매개변수로 제한하는 검사, 허용된 함수 호출 확인을 함께 적용합니다. builtins를 제거해도 eval은 샌드박스가 아닙니다. 패키지를 업데이트하고 이 발췌를 독립 검증기로 복사하지 마세요.[2], [6], [4]

취약한 구현
# 수정 전 대표 패턴: 모델 제어 텍스트가 표현식을 바꿉니다.
filter_text = f"lambda x: x.city == '{model_selected_city}'"
tree = ast.parse(filter_text, mode="eval")
code = compile(tree, filename="<filter>", mode="eval")
filter_fn = eval(code, {"__builtins__": {}}, {})  # nosec
보안 강화 패치
def validate_filter(self, tree):
    # 업스트림 1.39.4 핵심 검사이며 예외 메시지는 줄였습니다.
    # 최상위 필터는 lambda 식이어야 합니다.
    if not (isinstance(tree, ast.Expression) and isinstance(tree.body, ast.Lambda)):
        raise VectorStoreOperationException("Filter must be a lambda expression")

    lambda_param_names = {arg.arg for arg in tree.body.args.args}
    for node in ast.walk(tree):
        if type(node) not in self.allowed_filter_ast_nodes:
            raise VectorStoreOperationException("AST node type is not allowed")

        if isinstance(node, ast.Attribute) and node.attr in self.blocked_filter_attributes:
            raise VectorStoreOperationException("Dangerous attribute is not allowed")

        if isinstance(node, ast.Name) and node.id not in lambda_param_names:
            raise VectorStoreOperationException("Only lambda parameter names are allowed")

        if isinstance(node, ast.Call):
            if isinstance(node.func, ast.Name):
                func_name = node.func.id
            elif isinstance(node.func, ast.Attribute):
                func_name = node.func.attr
            else:
                func_name = None
            if func_name and func_name not in self.allowed_filter_functions:
                raise VectorStoreOperationException("Function is not allowed")

    code = compile(tree, filename="<filter>", mode="eval")
    func = eval(code, {"__builtins__": {}}, {})  # nosec

엔지니어링 및 시스템 보안 강화 체크리스트

출처

← AI Security Directory →