Scriban의 TemplateContext는 객체 멤버 접근자를 캐싱할 때 타입 정보만 키로 씁니다. 런타임에 MemberFilter 정책을 바꿔도 기존 캐시된 접근자를 그대로 쓰는 바람에 필터링이 우회되죠. 샌드박스 정책을 강화한 뒤에도 이전 요청에서 허용했던 민감 멤버에 대한 비인가 접근이 계속 이어집니다.
CVE-2026-74790 개요
CVE-2026-74790은.NET 환경에서 널리 쓰이는 Scriban 템플릿 엔진의 보호 메커니즘 고장(CWE-693) 취약점입니다. 2026년 3월 22일 GitHub 보안 고지(GHSA-5wr9-m6jw-xx44)로 공개되었고, 보안 연구원 Zwique가 처음 보고했습니다. TemplateContext를 재사용할 때 MemberFilter나 MemberRenamer 변경 사항이 내부 캐싱 로직에 반영되지 않아 생기는 문제입니다. 결국 개발자가 의도한 샌드박스 정책이 무력화되죠. 인프라 환경에서 템플릿 엔진을 고성능 풀링(Pooling) 방식으로 운영하는 서비스는 특히 빠른 점검이 필요합니다.
취약점의 기술적 근본 원인
Scriban은 템플릿 렌더링 성능을 높이려 TemplateContext.GetMemberAccessor() 메서드로 타입별 접근자를 _memberAccessors 딕셔너리에 캐시합니다. 하지만 캐시 키를 만들 때 객체의 Type 정보만 보고 현재 적용된 MemberFilter 상태를 변수에 넣지 않는 설계 결함이 있습니다. 첫 렌더링 때 특정 필터 정책으로 만든 TypedObjectAccessor가 캐시에 저장되면, 이후 같은 컨텍스트를 재사용하며 더 엄격한 필터를 설정해도 Scriban은 캐시된 구 접근자를 그대로 줍니다. TemplateContext 풀링이나 장기 재사용 시 필터링하려던 프로퍼티나 필드 접근 권한이 남아 보안 경계가 무너집니다.
영향 받는 버전 및 패치 정보
이 취약점은 Scriban 0 버전 이상 7.0.0 미만 버전 전체에 영향을 줍니다. GitHub 공식 고지는 6.6.0 이하라고 하지만, 실제 영향 범위는 초기 릴리스부터 7.0.0 이전까지 모든 버전입니다. 보안 연구소와 취약점 데이터베이스도 포괄적인 버전 범위를 두고 경고를 보냈습니다. 취약점을 해결하려면 Scriban 7.0.0으로 패치해야 하며, 이 버전에서 캐시 리셋 로직이 공식 적용되었습니다.
CVSS 심각도 평가 및 공격 벡터
CVE-2026-74790은 Critical 심각도입니다. GitHub 보안 고지 기준 CVSS v3.1 점수는 9.1점, VulnCheck의 CVSS v4.0 평가 점수는 9.3점입니다. 공격 벡터는 네트워크 원격 환경에서 가능하고 공격 복잡도도 낮습니다. 인증이나 사용자 상호작용 없이 악용할 수 있죠. 기밀성과 무결성에 영향은 크지만, 가용성엔 직접적인 타격을 주지 않는 것으로 평가됩니다. CVSS v4.0 벡터는 CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N입니다. 원격 공격자가 시스템 데이터 무결성과 기밀성을 심각하게 훼손할 수 있다는 뜻입니다.
증명 개념(POC) 및 실제 영향
실제 환경 악용 시나리오를 검증한 증명 개념(POC)은 이렇습니다. 첫 렌더링 때 MemberFilter가 꺼진 상태에서 Secret 속성에 접근해 leaked 값을 출력합니다. 두 번째 렌더링에 같은 컨텍스트를 재사용하며 엄격한 필터를 걸어도 여전히 leaked 값이 노출되죠. 캐시된 접근자가 필터 변경을 무시하고 작동해서입니다. 실제 서비스 환경에서는 필터링한 속성 및 필드에 대한 비인가 읽기 접근이 발생하고, 해당 멤버에 세터가 있으면 비인가 쓰기도 가능합니다. 특히 TemplateContext를 풀링해 여러 요청이나 다중 테넌트 간에 공유하는 아키텍처는 요청 간 정책 우회로 이어져 심각한 보안 사고로 번질 위험이 큽니다.
완화 조치 및 권장 사항
CVE-2026-74790을 근본적으로 해결하려면 Scriban 7.0.0으로 즉시 업그레이드해야 합니다. 7.0.0 버전에는 MemberFilter 변경 시 캐시를 자동 리셋하는 로직이 추가됐고, TemplateContext.Reset() 메서드도 이전 필터를 포함한 캐시된 접근자를 지우도록 개선되었습니다.
당장 라이브러리 업그레이드가 어렵다면, 임시 완화 조치를 신속히 적용하세요.
TemplateContext인스턴스를 요청 단위나 렌더링 단위별로 새로 만들어 절대 재사용하지 않도록 코드 구조를 바꾸세요.- 템플릿 엔진 초기화 시 모든 세션에 동일한 보안 정책을 적용하도록
MemberFilter를 일관되게 고정하고, 컨텍스트 풀링을 즉시 멈춥니다. - 민감한 비즈니스 객체를 템플릿에 넘기기 전에 접근 제어 검증 로직을 별도 레이어에서 수행해 엔진 내부 필터링에만 의존하지 않도록 합니다.
| 평가 항목 | 세부 내용 |
|---|---|
| 취약점 식별자 | CVE-2026-74790 |
| CWE 분류 | CWE-693 (Protection Mechanism Failure) |
| 영향 받는 버전 | 0 이상 7.0.0 미만 |
| 패치 버전 | 7.0.0 |
| CVSS v3.1 / v4.0 | 9.1 / 9.3 (Critical) |
| 근본 원인 | Type 기반 캐싱으로 MemberFilter 상태 무시 |
.NET 기반 서비스에서 Scriban을 샌드박스나 동적 렌더링 엔진으로 쓰는 개발자와 인프라 보안 담당자는 프로젝트 의존성을 바로 점검하고 패치 적용 여부를 확인해야 합니다. 캐시 최적화 설계의 부수적 영향으로 인한 보안 메커니즘 우회는 예측이 어렵습니다. 서비스 중단 없이도 데이터 유출이나 무결성 훼손으로 이어질 수 있어 신속한 대응이 필수적입니다.