NOW Briefing
roslyn-codelens-mcp) 서버의 get_diagnostics 도구에서 임의 코드 실행 결함이 확인됐습니다(CVE-2026-45555).
.sln·.csproj에 악성 DiagnosticAnalyzer DLL(컴파일된 .NET 라이브러리 파일)을 포함시키면, 피해자가 해당 솔루션을 MCP 서버로 열고 진단 도구를 한 번 호출하는 순간 서버 프로세스 권한으로 임의 코드가 실행됩니다.
RoslynCodeLens.Mcp v1.17.0 이상으로 즉시 업그레이드해야 합니다. 적용 전까지는 get_diagnostics 호출 시 includeAnalyzers=false를 명시하고 MCP 도구 등록을 해제해 호출 경로를 차단해야 합니다.
Roslyn CodeLens MCP 분석기 임의 코드 실행 취약점 제보 사례 (CVE-2026-45555)
■ 개요
RoslynCodeLens.Mcp는 .NET 코드베이스에 의미 기반 분석을 제공하는 MCP(Model Context Protocol, 모델 컨텍스트 프로토콜) 서버입니다. NuGet 패키지로 배포되며 Claude·Cursor 같은 AI 코딩 도우미가 도구 호출 방식으로 사용합니다. 결함은 커밋 3ad1cb5(v1.4.0) 시점의 AnalyzerRunner 구현 로직에 있으며, RoslynCodeLens.Mcp 0.0.9 이상 1.17.0 미만 모든 배포 버전이 같은 위험에 노출됩니다. v1.17.0에서는 트러스트 게이트(솔루션 신뢰 승인 단계)와 분석기 허용 목록을 도입해 패치했습니다.
구체적으로 get_diagnostics 호출 시 서버는 대상 프로젝트의 AnalyzerReferences에 등록된 DLL을 검증·허용 목록 없이 모두 적재합니다. 도구 매개변수 includeAnalyzers의 기본값이 true이므로 호출자가 인자를 생략해도 분석기가 실행됩니다. 솔루션 파일만 통제할 수 있는 공격자는 MCP 서버 프로세스 권한으로 임의 코드를 실행할 수 있습니다.
주요 영향 범위는 보안 검토·코드 리뷰를 위해 외부 저장소를 자주 클론하는 개발자 PC와 CI 노드, MCP 도구를 자동 호출하는 AI 도우미 사용 환경입니다. AI 도우미는 사용자 확인 없이 호출하는 경우가 많아 "이 프로젝트를 분석해 줘" 수준의 평범한 지시 한 줄로도 악성 DLL이 실행됩니다. 한 번의 호출만으로 호스트 권한 코드 실행이 발생하므로, 사용 중인 환경이라면 즉시 임시 대응책을 적용해야 합니다.
■ 요약
| 항목 | 내용 |
|---|---|
| CVE ID | CVE-2026-45555 (MarcelRoozekrans/roslyn-codelens-mcp 분석기 DLL 임의 실행) |
| CVSS 점수 | CVSS v3.1 7.8 / High (CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H) |
| 취약점 유형 | CWE-94: 코드 생성 제어 부적절('코드 인젝션'), 신뢰하지 않은 분석기 DLL 로딩 |
| 영향/위험 |
• 악성 솔루션 1회 열람만으로 MCP 서버 프로세스 권한 코드 실행 가능 • 호스트 파일시스템·자격증명 탈취, 지속성 확보 가능 • AI 도우미 자동 호출 경로로 사용자 확인 없이 트리거 가능 |
| 영향 버전 | RoslynCodeLens.Mcp >= 0.0.9, < 1.17.0 (commit 3ad1cb5(v1.4.0) 포함) |
| 패치 버전 | v1.17.0 이상 |
■ 기술 분석
이 취약점의 직접 원인은 src/RoslynCodeLens/AnalyzerRunner.cs의 GetAnalyzers 메서드에 있습니다. 이 메서드는 대상 프로젝트의 project.AnalyzerReferences 컬렉션을 순회하며 analyzerRef.GetAnalyzers(project.Language)를 호출합니다. 호출 시점에 Roslyn 워크스페이스가 어셈블리를 리플렉션으로 적재하고, 적재된 각 DiagnosticAnalyzer 인스턴스의 Initialize()가 MCP 서버 프로세스에서 실행됩니다.
private static ImmutableArray<DiagnosticAnalyzer> GetAnalyzers(Project project)
{
var analyzers = ImmutableArray.CreateBuilder<DiagnosticAnalyzer>();
foreach (var analyzerRef in project.AnalyzerReferences)
{
foreach (var analyzer in analyzerRef.GetAnalyzers(project.Language))
{
analyzers.Add(analyzer);
}
}
return analyzers.ToImmutable();
}
악성 분석기를 등록할 수 있는 경로는 .csproj의 <Analyzer Include="...dll" /> 항목과 NuGet 패키지의 analyzers/ 폴더 두 가지입니다. MSBuildWorkspace가 솔루션을 로드하면 이 항목들을 AnalyzerReferences로 자동 채웁니다. 따라서 공격자는 별도 권한 없이 .sln·.csproj만 작성해도 임의 DLL을 서버 메모리에 로드시킬 수 있습니다.
여기에 더해 도구 진입점인 Tools/GetDiagnosticsTool.cs의 Execute 시그니처는 includeAnalyzers 매개변수 기본값을 true로 둡니다. 이 때문에 MCP 클라이언트가 인자를 생략한 평범한 호출도 분석기 실행 경로로 진입합니다. "프로젝트의 빌드 오류를 알려 줘" 같은 일반적인 AI 도우미 지시 한 줄이 공격을 트리거합니다.
📌 NOTE
<Analyzer> 항목과 NuGet 분석기 패키지는 표면적으로 정상적인 코드 분석 자산입니다.
그러나 Roslyn은 이를 신뢰된 빌드 자산으로 간주해 로드 시점에 검증하지 않습니다.
임의 솔루션을 분석 대상으로 받는 모든 도구·서비스에서 같은 패턴이 재현될 가능성이 있습니다.
■ PoC
위 실행 경로는 공개된 검증 흐름에서도 확인됐으며, ① 사용자 정의 DiagnosticAnalyzer 서브클래스의 Initialize()에서 부수효과(표식 파일 생성, 명령 실행 등)를 일으키도록 DLL을 작성하고, ② 이 DLL을 <Analyzer> 항목으로 등록한 악성 .csproj·.sln을 만든 뒤, ③ MCP 서버에 솔루션을 지정해 기동하고 get_diagnostics를 호출하는 세 단계입니다. 피해자가 정상 도구 호출을 한 번 트리거하는 순간이 곧 코드 실행 시점이 됩니다.
// 방어용으로 단순화한 예시 — 실행 가능한 익스플로잇이 아닙니다.
// 1) 공격자 산출물: 솔루션이 참조하는 분석기 DLL
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public sealed class EvilAnalyzer : DiagnosticAnalyzer
{
public override void Initialize(AnalysisContext context)
{
MarkExecuted(); // 적재만 되어도 임의 코드 실행 시점이 발생
// ... 권한 상승·자격증명 탈취 등 무기화 로직 생략 ...
}
// ... SupportedDiagnostics 등 인터페이스 충족용 멤버 생략 ...
}
// 2) 악성 .csproj 발췌: 솔루션 로딩 시 AnalyzerReferences로 자동 등록
// <ItemGroup>
// <Analyzer Include="evil.dll" />
// </ItemGroup>
// 3) 피해자 트리거(정상 MCP 도구 호출 한 줄)
// {"jsonrpc":"2.0","id":1,"method":"tools/call",
// "params":{"name":"get_diagnostics","arguments":{}}}
검증 환경에서는 get_diagnostics 응답에 분석기가 보고한 진단(EVIL001 등)이 포함됐고, 동시에 분석기 Initialize()가 남긴 부수효과(표식 파일·프로세스 생성)가 MCP 서버 프로세스 권한으로 호스트에 남았습니다. 피해자 측 추가 입력은 필요하지 않으며, includeAnalyzers를 명시하지 않은 호출도 기본값 true로 동일 경로를 탑니다.
⚠️ WARN
이 코드는 실제 익스플로잇이 아니라 공개 PoC의 검증 관점을 방어용으로 단순화한 예시입니다.
신뢰할 수 없는 출처의 .sln·.csproj·NuGet 분석기 패키지를 본 도구로 직접 열지 마십시오.
■ 탐지 및 점검
• 위 실행 경로를 점검하려면 분석 대상 솔루션의 모든 .csproj를 검사해 <Analyzer Include="..."/> 항목 또는 분석기 NuGet 패키지의 출처를 확인하고, 솔루션 내부 경로·알 수 없는 출처의 DLL을 가리키면 즉시 차단해야 합니다.
• 사용 중인 MCP 도구 식별자가 RoslynCodeLens.Mcp이고 버전이 1.17.0 미만(0.0.9 이상)인지 dotnet tool list -g 출력으로 확인해야 합니다.
• MCP 서버 프로세스(roslyn-codelens-mcp, dotnet RoslynCodeLens.dll)의 어셈블리 로드 이벤트를 ETW(Microsoft-Windows-DotNETRuntime/AssemblyLoader)나 dotnet-trace로 수집해, NuGet 캐시 외부 경로의 DLL 적재를 우선 위험 신호로 다뤄야 합니다.
• AI 도우미 호출 로그에서 get_diagnostics 도구 호출 인자에 includeAnalyzers가 명시되지 않은 항목과, 외부 저장소를 막 클론한 직후 발생한 호출을 우선 검토해야 합니다.
• 컨테이너·VM 환경에서는 MCP 서버 프로세스가 호스트 비밀 경로(~/.ssh, ~/.aws, 자격증명 캐시)와 사용자 홈 디렉터리에 접근한 흔적을 감사해야 합니다.
■ 대응 방안
• 점검 결과 영향 버전 사용이 확인되면 RoslynCodeLens.Mcp v1.17.0 이상(트러스트 게이트·분석기 허용 목록 도입 버전)으로 즉시 업그레이드하고, 신뢰되지 않은 솔루션은 trust_solution 도구로 명시 승인 절차를 거치도록 운영 정책을 정비해야 합니다.
• 즉시 업그레이드가 불가한 환경에서는 v1.17.0 미만 버전의 RoslynCodeLens.Mcp 도구 호출을 중단하고, AI 도우미 설정에서 MCP 서버 등록을 해제하거나 분석 대상 디렉터리를 자체 관리 저장소로만 제한해야 합니다.
• 패치 전 도구를 계속 사용해야 한다면 모든 get_diagnostics 호출에 includeAnalyzers=false를 명시해 분석기 적재 경로를 강제로 우회해야 합니다.
• 검토 대상 외부 저장소는 별도 컨테이너·VM에서 클론·열람하고, 호스트의 SSH 키·클라우드 자격증명·토큰 마운트를 차단해야 합니다.
• 자체 포크를 운영하는 경우 AnalyzerRunner.GetAnalyzers 진입부에 분석기 어셈블리 경로 또는 강한 이름 공개키 허용 목록을 추가하고, 비허용 어셈블리는 로드 전에 건너뛰도록 패치해야 합니다.
💡 TIP
AI 도우미가 자동 호출하는 MCP 도구는 사용자 확인 없이 트리거됩니다.
따라서 임시 대응책은 클라이언트 정책(도구 비활성화·승인 강제)과 서버 인자(includeAnalyzers=false)에 동시에 두는 것이 안전합니다.
[참고 자료]
MarcelRoozekrans/roslyn-codelens-mcp 저장소
RoslynCodeLens.Mcp v1.17.0 릴리스 노트 (Trust gate + analyzer allowlist)
CWE-94: Improper Control of Generation of Code ('Code Injection')



