Graphql Introspection in Aspnet with Mutual Tls
Graphql Introspection in Aspnet with Mutual Tls — how this specific combination creates or exposes the vulnerability
GraphQL introspection in an ASP.NET context allows clients to query the schema, types, and operations of a GraphQL endpoint. When mutual TLS (mTLS) is used, the transport layer is authenticated via client certificates, but that does not inherently restrict what an authenticated client can query. If an endpoint enforces mTLS for access control yet leaves introspection enabled, an authorized client can still probe the full schema, potentially discovering sensitive types, queries, or operations that should not be exposed. middleBrick scans such endpoints and flags this as an information exposure finding under the Data Exposure and Authentication checks, noting that mTLS secures the channel but does not replace schema-level authorization.
In practice, an ASP.NET GraphQL server might accept a client certificate and route the request to the GraphQL middleware without further authorization checks on the introspection operation. For example, a client with a valid certificate could send an introspection query over HTTPS, and the server returns the complete schema, including queries, mutations, subscriptions, and argument types. middleBrick’s LLM/AI Security checks do not apply here because introspection is a standard GraphQL feature, but the scan highlights the risk of exposing implementation details through an authenticated channel. Attack patterns like this align with OWASP API Top 10:2023 — Broken Object Level Authorization (BOLA) and excessive data exposure, since the schema itself becomes an attack surface when not gated independently of transport-layer auth.
When scanning an ASP.NET GraphQL endpoint that uses mutual TLS, middleBrick runs unauthenticated checks against the public URL and reports findings such as ‘Introspection enabled over authenticated channel.’ The tool does not attempt to interpret the certificate but focuses on observable behavior: the presence of a 200 response to an introspection request over an mTLS-accepted connection. This helps teams understand that mTLS alone is insufficient to prevent schema discovery and that additional controls are required at the GraphQL resolver or middleware layer.
Mutual Tls-Specific Remediation in Aspnet — concrete code fixes
To secure an ASP.NET GraphQL endpoint when using mutual TLS, you should enforce both transport-layer authentication and schema-level restrictions. Disable introspection for production environments or gate it behind a policy that checks client certificate details or roles. Below are concrete code examples showing how to configure mTLS and conditionally allow introspection in an ASP.NET Core GraphQL server.
Enabling Mutual TLS in Program.cs
Configure Kestrel to require client certificates and map them to user identity:
// Program.cs
var builder = WebApplication.CreateBuilder(args);
// Require client certificates for mTLS
builder.WebHost.ConfigureKestrel(serverOptions =>
{
serverOptions.ListenAnyIP(5001, listenOptions =>
{
listenOptions.UseHttps(httpsOptions =>
{
httpsOptions.ServerCertificate = new X509Certificate2("server.pfx", "password");
httpsOptions.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
// Optional: map the client certificate to authentication
httpsOptions.ClientCertificateValidation = (cert, chain, errors) =>
{
// Add custom validation logic here, e.g., thumbprint checks
return errors == SslPolicyErrors.None;
};
});
});
});
builder.Services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate(options =>
{
options.AllowedCertificateTypes = CertificateTypes.All;
options.RevocationMode = X509RevocationMode.NoCheck;
options.Events = new CertificateAuthenticationEvents
{
OnCertificateValidated = context =>
{
var claims = new[]
{
new Claim(ClaimTypes.NameIdentifier, context.ClientCertificate.Thumbprint)
};
context.Principal = new ClaimsPrincipal(new ClaimsIdentity(claims, context.Scheme.Name));
return Task.CompletedTask;
}
};
});
builder.Services.AddAuthorization();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
// GraphQL endpoint
app.MapGraphQL("/graphql");
app.Run();
Restricting Introspection Based on mTLS Claims
In your GraphQL server setup, conditionally enable introspection only for specific client certificates or roles:
// GraphQL server configuration with introspection guard
var graphqlBuilder = WebApplication.CreateBuilder(args);
graphqlBuilder.Services
.AddGraphQLServer()
.AddQueryType()
.AddAuthorization(options =>
{
options.AddPolicy("IntrospectionAllowed", policy =>
{
policy.RequireAssertion(context =>
{
// Allow introspection only if the client certificate thumbprint is in the allowed list
var cert = context.HttpContext.Connection.ClientCertificate;
if (cert == null) return false;
var allowedThumbprints = new[] { "AA:BB:CC:..." }; // Replace with your trusted thumbprints
return allowedThumbprints.Contains(cert.GetCertHashString().ToUpper());
});
});
});
var graphQLApp = graphqlBuilder.Build();
graphQLApp.UseAuthentication();
graphQLApp.UseAuthorization();
// Apply the policy to introspection requests
graphQLApp.MapGraphQL("/graphql", new GraphQLServerOptions
{
EnableMetrics = false,
Schema = new MySchema(),
// Custom middleware to block introspection unless policy passes
ConfigureExecution = async (context, next) =>
{
var operation = context.Request.Document?.Operations?.FirstOrDefault();
if (operation?.OperationType == OperationType.Query &&
operation.Name?.Value?.ToString() == "__Schema")
{
var authService = context.RequestServices.GetRequiredService();
var authResult = await authService.AuthorizeAsync(context.HttpContext.User, null, "IntrospectionAllowed");
if (!authResult.Succeeded)
{
context.Result = new ExecutionResult
{
Errors = new[] { new ExecutionError("Introspection is not allowed for this client.") }
};
return;
}
}
await next(context);
}
});
graphQLApp.Run();
These examples show how to enforce mTLS and selectively allow introspection. middleBrick’s dashboard and CLI can be used to verify that introspection is not unintentionally exposed after deployment, and the Pro plan’s continuous monitoring can alert you if a change re-enables introspection on a production endpoint.
Related CWEs: dataExposure
| CWE ID | Name | Severity |
|---|---|---|
| CWE-200 | Exposure of Sensitive Information | HIGH |
| CWE-209 | Error Information Disclosure | MEDIUM |
| CWE-213 | Exposure of Sensitive Information Due to Incompatible Policies | HIGH |
| CWE-215 | Insertion of Sensitive Information Into Debugging Code | MEDIUM |
| CWE-312 | Cleartext Storage of Sensitive Information | HIGH |
| CWE-359 | Exposure of Private Personal Information (PII) | HIGH |
| CWE-522 | Insufficiently Protected Credentials | CRITICAL |
| CWE-532 | Insertion of Sensitive Information into Log File | MEDIUM |
| CWE-538 | Insertion of Sensitive Information into Externally-Accessible File | HIGH |
| CWE-540 | Inclusion of Sensitive Information in Source Code | HIGH |