Skip to content

feat(dotnet): add MCP protocol support with full OWASP coverage, multi-target .NET 8/10, ML-DSA post-quantum signing#775

Open
jackbatzner wants to merge 3 commits intomicrosoft:mainfrom
jackbatzner:jb/dotnet-mcp-support
Open

feat(dotnet): add MCP protocol support with full OWASP coverage, multi-target .NET 8/10, ML-DSA post-quantum signing#775
jackbatzner wants to merge 3 commits intomicrosoft:mainfrom
jackbatzner:jb/dotnet-mcp-support

Conversation

@jackbatzner
Copy link
Copy Markdown
Contributor

Description

Add comprehensive MCP (Model Context Protocol) security governance to the .NET SDK (agent-governance-dotnet) by implementing a full 5-stage gateway pipeline, 6-threat security scanner, post-quantum message signing, and ASP.NET Core / gRPC / official MCP SDK integrations. Multi-targets .NET 8.0 (LTS) and .NET 10.0 with ML-DSA-65 (NIST FIPS 204) post-quantum asymmetric signing on .NET 10+.

This PR covers 11/12 OWASP MCP Security Cheat Sheet sections (§11 Consent UI is N/A — client-side concern). The detailed OWASP mapping is documented in the package README.

OWASP Agentic Top 10 Coverage Context

Risk Existing coverage in Agent OS / ecosystem This PR contribution
ASI01 Agent Goal Hijack PromptInjectionDetector, GovernancePolicy.blocked_patterns, SemanticPolicyEngine No direct change
ASI02 Tool Misuse & Exploitation MCPGateway, MCPSecurityScanner, policy enforcement (Python) Adds .NET MCP gateway (5-stage pipeline), security scanner (6 threats), response scanner, credential redactor, tool fingerprinting, parameter sanitization (25 patterns)
ASI03 Identity & Privilege Abuse Human approval workflows, RBAC policies, tool budgets Adds .NET MCP session authentication with crypto binding, TTL, concurrent-session limits, TOCTOU-safe concurrency
ASI04 Agentic Supply Chain Broader ecosystem supply-chain controls and provenance No direct change
ASI05 Unexpected Code Execution Sandboxing, blocked patterns, execution controls Indirect — MCP parameter sanitization blocks shell injection, command substitution, backtick execution
ASI06 Memory & Context Poisoning MemoryGuard, integrity checks, injection detection No direct change
ASI07 Insecure Inter-Agent Communication AgentMesh trust handshake, reputation engine Adds .NET MCP message signing (HMAC-SHA256 + ML-DSA-65 post-quantum on .NET 10+) with nonce replay protection
ASI08 Cascading Failures Circuit breakers, reliability controls, Agent SRE Indirect — sliding-window rate limiter prevents MCP tool abuse cascades
ASI09 Human-Agent Trust Exploitation Human approval flows, audit logging Adds human-in-the-loop approval stage in MCP gateway, OTel metrics for MCP decisions/threats
ASI10 Rogue Agents Agent Runtime kill switch, isolation, trust controls No direct change

Before / After for .NET MCP

Area Before After
MCP gateway No .NET MCP pipeline McpGateway — 5-stage pipeline (deny→allow→sanitize→rate-limit→approve) with fail-closed semantics
MCP threat detection No .NET MCP scanner McpSecurityScanner — 6 threat types + SHA-256 fingerprinting
MCP output safety No output scanning McpResponseScanner — instruction tags, imperative overrides, credential leakage, exfiltration URLs
MCP session security No session auth McpSessionAuthenticator — crypto sessions, TTL, TOCTOU-safe concurrency
MCP message integrity No message signing McpMessageSigner — HMAC-SHA256 (.NET 8) + ML-DSA-65 post-quantum (.NET 10+)
Secret handling No credential redaction CredentialRedactor — 10 patterns, nested dict support
MCP rate limiting No per-agent limiter McpSlidingRateLimiter — per-agent sliding-window
MCP observability No MCP counters mcp_decisions, mcp_threats_detected, mcp_rate_limit_hits, mcp_scans OTel counters
ASP.NET integration No MCP middleware AddMcpGovernance(), UseMcpGovernance(), MapMcpGovernance(), IConfiguration, IHealthCheck
gRPC integration No MCP interceptor McpGrpcInterceptor — all 4 handler types
Official MCP SDK No adapter AgentGovernance.ModelContextProtocol sub-package — IMcpServerBuilder.WithGovernance()
Target frameworks .NET 8.0 only Multi-target .NET 8.0 + .NET 10.0, ML-DSA-65 on .NET 10+
Tests 441 tests 973 tests (532 new MCP tests, 0 failures)

OWASP MCP Security Cheat Sheet Coverage

Per the OWASP MCP Security Cheat Sheet:

§ Section .NET Implementation Status
1 Tool Poisoning McpSecurityScanner (description injection, hidden instructions)
2 Rug Pull ToolFingerprint SHA-256 + CheckRugPull()
3 Tool Shadowing McpSecurityScanner cross-server shadowing checks
4 Parameter Injection McpGateway stage 3 sanitization (25 regex patterns, 200ms ReDoS timeout)
5 Response Validation McpResponseScanner (HTML tags, imperatives, exfiltration URLs)
6 Session Management McpSessionAuthenticator (crypto binding, TTL, TOCTOU-safe limits)
7 Message Signing McpMessageSigner (HMAC-SHA256 + ML-DSA-65 + nonce + replay)
8 Rate Limiting McpSlidingRateLimiter + McpGateway stage 4
9 Logging & Audit OTel counters + ILogger<T> structured logging on all components
10 Credential Redaction CredentialRedactor (10 patterns, nested dict, static class)
11 Consent & UI N/A (client-side concern)
12 Data Exfiltration McpResponseScanner URL pattern detection

Additional notes

  • Ed25519 is not yet available in .NET 10 runtime (dotnet/runtime#63174 still open). ML-DSA-65 (NIST FIPS 204) was chosen instead — it's post-quantum resistant and natively available in .NET 10.
  • The AgentGovernance.ModelContextProtocol adapter sub-package keeps the core library dependency-free (no ModelContextProtocol NuGet reference in core).
  • Two sample apps included: McpGovernance.AspNetCore and McpGovernance.OfficialSdk.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Maintenance (dependency updates, CI/CD, refactoring)
  • Security fix

Package(s) Affected

  • agent-os-kernel
  • agent-mesh
  • agent-runtime
  • agent-sre
  • agent-governance
  • docs / root

Checklist

  • My code follows the project style guidelines (ruff check)
  • I have added tests that prove my fix/feature works
  • All new and existing tests pass (pytest)
  • I have updated documentation as needed
  • I have signed the Microsoft CLA

Related Issues

N/A

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 4, 2026

Welcome to the Agent Governance Toolkit! Thanks for your first pull request.
Please ensure tests pass, code follows style (ruff check), and you have signed the CLA.
See our Contributing Guide.

@github-actions github-actions bot added the size/XL Extra large PR (500+ lines) label Apr 4, 2026
@jackbatzner jackbatzner force-pushed the jb/dotnet-mcp-support branch 2 times, most recently from 607ac16 to 8660bd9 Compare April 4, 2026 06:08
Copy link
Copy Markdown
Member

@imran-siddique imran-siddique left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the .NET MCP work. However, this PR modifies ci.yml (+454/-452) and publish.yml (+264/-262) which are security-critical workflow files protected by CODEOWNERS.

Workflow changes need maintainer review of every line — with 700+ lines of changes, this needs to be split:

  1. One PR with the .NET SDK code changes only (no .github/ modifications)
  2. A separate PR with CI/publish workflow changes that we can review line-by-line

Please remove the .github/ changes and resubmit the code portion. We'll handle the CI integration.

@jackbatzner jackbatzner force-pushed the jb/dotnet-mcp-support branch from 8660bd9 to 4c82db5 Compare April 4, 2026 18:10
…get .NET 8/10, ML-DSA post-quantum signing

Add comprehensive MCP (Model Context Protocol) security governance to the .NET SDK
with 11/12 OWASP MCP Security Cheat Sheet sections covered. Multi-targets .NET 8.0
(LTS) and .NET 10.0 with post-quantum ML-DSA-65 (NIST FIPS 204) signing on .NET 10+.

Core components:
- McpGateway: 5-stage pipeline (deny→allow→sanitize→rate-limit→approve)
- McpSecurityScanner: 6-threat detection with SHA-256 fingerprinting
- McpMessageHandler: JSON-RPC routing with tool-to-ActionType classification
- McpResponseScanner: Output validation (injection, credentials, exfiltration)
- McpSessionAuthenticator: Crypto session binding with TOCTOU-safe concurrency
- McpMessageSigner: HMAC-SHA256 (.NET 8) + ML-DSA-65 post-quantum (.NET 10+)
- CredentialRedactor: 10 credential pattern redaction for audit logs
- McpSlidingRateLimiter: Per-agent sliding window rate limiting

Integration:
- ASP.NET Core: AddMcpGovernance(), UseMcpGovernance(), MapMcpGovernance()
- IConfiguration binding, ILogger<T>, IHealthCheck, gRPC interceptor
- McpToolRegistry with [McpTool] attribute auto-discovery
- AgentGovernance.ModelContextProtocol adapter sub-package (official SDK)
- OTel metrics: mcp_decisions, mcp_threats_detected, mcp_rate_limit_hits, mcp_scans

Tests: 973 passing (0 failures)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jackbatzner jackbatzner force-pushed the jb/dotnet-mcp-support branch from 4c82db5 to 4d9ca52 Compare April 4, 2026 18:15
@jackbatzner
Copy link
Copy Markdown
Contributor Author

@imran-siddique Great catch — the massive diff was a CRLF line-ending artifact from editing on Windows. The actual workflow change is just 3 lines per file (adding 10.0.x to dotnet-version for our .NET 10 multi-targeting).

Fixed in 4c82db5:

Converted all files back to match their original line endings
Removed temp files that were accidentally included
The .github/ diff is now 6 insertions, 2 deletions — just the dotnet-version addition needed for our net10.0 TFM. This is required because the PR multi-targets net8.0;net10.0.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jackbatzner
Copy link
Copy Markdown
Contributor Author

Enterprise Hardening Update

Latest push adds enterprise-grade MCP seam hardening and 3 self-review fixes:

Self-Review Fixes

  1. Fail-closed on store exceptionsMcpSessionAuthenticator now catches IMcpSessionStore exceptions and denies/revokes safely instead of letting backend outages escape.
  2. No token loggingCreateSession no longer logs any session token prefix/material.
  3. Non-DI helper injectionMcpGovernanceExtensions public helpers now accept optional seam dependencies (TimeProvider, session/nonce/rate-limit stores, audit sink) so enterprise callers can inject without DI.

Enterprise Patterns

  • Persistence seamsIMcpSessionStore, IMcpNonceStore, IMcpRateLimitStore, IMcpAuditSink interfaces with in-memory defaults, registered via AddMcpGovernance().
  • Clock injectionTimeProvider.System injected throughout; McpSession.IsExpired no longer uses DateTimeOffset.UtcNow directly.
  • Redaction-safe auditCredentialRedactor runs before storage; EnableCredentialRedaction defaults to true.

Validation

  • dotnet build ... -c Release
  • dotnet test ... -c Release ✅ (996/996 passed)
  • MIT license headers on all new .cs files ✅
  • No CRLF/LF diff inflation ✅
  • Self-review checklist passed ✅

Note: -warnaserror gate fails on 33 pre-existing warnings in unrelated test files (obsolete AgentIdentity.Sign/Verify usage, xUnit analyzer issues). Not introduced by this PR.

Copy link
Copy Markdown
Member

@imran-siddique imran-siddique left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thorough implementation with excellent test coverage (988 tests!). However, several security issues need addressing:

Blocking:

  1. CredentialRedactor only redacts PEM header, leaves key body intact — the regex pattern matches headers like BEGIN PRIVATE KEY but the body (the actual secret) remains in plaintext. The full PEM block must be redacted.
  2. 8 ML-DSA tests fail on CI — these need platform guards or skip markers since ML-DSA requires .NET 10 with specific crypto support.

Security concerns (should fix):

  • Exception messages leak internal details (stack traces, paths) to callers
  • HMAC minimum key size (16 bytes) is below NIST recommendation (32 bytes)
  • Regex timeout exceptions are swallowed = fail-open on crafted input
  • Rate limiter lock map grows unbounded (no eviction)
  • ToolRegistry uses unsynchronized mutable List (thread safety)

Architecture (nice to fix):

  • Session rate-limit key uses colon delimiter (ambiguous with IPv6)
  • Middleware consumes request body without enabling buffering
  • Hardcoded agent ID ignores configuration

Good test-to-code ratio (1:1.2). Consider splitting into 2-3 PRs for easier review if the fixes are substantial.

@imran-siddique imran-siddique self-assigned this Apr 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/XL Extra large PR (500+ lines)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants