HIGH graphql introspectionaspnethmac signatures

Graphql Introspection in Aspnet with Hmac Signatures

Graphql Introspection in Aspnet with Hmac Signatures — how this specific combination creates or exposes the vulnerability

GraphQL introspection in an ASP.NET endpoint becomes a security concern when an API relies on HMAC signatures only for request authentication but does not restrict introspection operations. Introspection queries (e.g., an HTTP POST with Content-Type application/json and a query like { __schema { queryType { name } } }) return the full schema, including types, queries, and mutations. If the endpoint validates an HMAC signature to confirm the request originates from a trusted source but does not apply authorization checks on introspection, an authenticated caller can harvest detailed structural information. This can reveal sensitive field names, query patterns, and resolver behavior, which attackers may use to refine injection, IDOR, or BOLA attacks.

In ASP.NET, this often occurs when GraphQL middleware is configured to accept requests authenticated via HMAC without additional operation-level policies. The HMAC is typically computed over selected parts of the request (method, path, timestamp, and body), ensuring integrity and origin, yet it does not enforce whether the operation is allowed. Because introspection is a built-in GraphQL capability, it remains reachable if the route is accessible. Attackers can send crafted introspection queries to learn argument names, input structures, and object relationships, which can be combined with other weaknesses such as BOLA or IDOR discovered through introspection to escalate impact.

When combined, the presence of HMAC signatures and exposed introspection creates a scenario where authentication does not imply authorization for schema discovery. For example, an API might validate HMAC to allow trusted internal services to call mutation operations, but if introspection is not explicitly disabled or gated, any client with valid HMAC credentials can still retrieve the schema. This increases risk because detailed schema knowledge enables more precise attacks, such as parameter tampering or targeting specific nested objects. To mitigate this, schema access should be treated as a first-class security boundary, independent of transport-level integrity checks like HMAC.

Hmac Signatures-Specific Remediation in Aspnet — concrete code fixes

To secure GraphQL introspection in ASP.NET while retaining HMAC-based request authentication, explicitly control schema exposure and enforce authorization on operations. Below are concrete code examples demonstrating how to disable introspection and gate operations using HMAC validation and policy-based authorization.

1. Disable GraphQL introspection in ASP.NET

Configure the GraphQL server to disable introspection in production environments. Using GraphQL.Server.Transports.AspNetCore and GraphQL.Server.Core, you can set introspection disabled via schema configuration:

var schema = SchemaBuilder.New()
    .AddTypes(typeof(QueryType).Assembly, typeof(QueryType).Namespace)
    .AddSystemTextJson()
    .DisableIntrospection()
    .Create();

This ensures that introspection queries are rejected regardless of HMAC validity, reducing information leakage while preserving functionality for trusted operations.

2. HMAC validation middleware with operation authorization

Implement HMAC validation in middleware, then enforce per-operation policies. The example below shows HMAC computation and verification in ASP.NET Core, followed by a GraphQL middleware that checks authorization before executing the operation:

// HMAC validation middleware
app.Use(async (context, next) =>
{
    if (context.Request.Path.StartsWithSegments("/graphql") && context.Request.Method == "POST")
    {
        using var reader = new StreamReader(context.Request.Body);
        var body = await reader.ReadToEndAsync();
        context.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(body));

        var timestamp = context.Request.Headers["X-Timestamp"];
        var receivedMac = context.Request.Headers["X-Hmac-Signature"];
        var secret = Environment.GetEnvironmentVariable("HMAC_SECRET");

        var dataToSign = $"{context.Request.Method}{context.Request.Path}{timestamp}{body}";
        using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
        var computedMac = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(dataToSign)));

        if (!CryptographicOperations.FixedTimeEquals(Convert.FromBase64String(receivedMac), Convert.ToBase64String(computedMac)))
        {
            context.Response.StatusCode = 401;
            await context.Response.WriteAsync("Invalid signature");
            return;
        }
    }
    await next();
});

After HMAC validation, apply GraphQL-specific authorization. Use the GraphQL Context to pass user claims and enforce policies per operation type:

app.UseGraphQL("/graphql")
    .AddGraphQLServer()
    .AddAuthorization(options =>
    {
        options.AddPolicy("MutationPolicy", policy => policy.RequireClaim("scope", "mutations"));
        options.AddPolicy("QueryPolicy", policy => policy.RequireClaim("scope", "queries"));
    })
    .AddDocumentFromTypes(typeof(QueryType).Assembly)
    .AddType()
    .AddAuthorization();

This ensures that even when HMAC validates the request origin, individual operations are further restricted based on claims, preventing unauthorized introspection and mutation usage.

3. Schema filtering for introspection

Provide a filtered schema for specific roles, disabling introspection for untrusted consumers:

var filteredSchema = SchemaBuilder.New()
    .AddTypes(typeof(QueryType).Assembly, typeof(QueryType).Namespace)
    .AddSystemTextJson()
    .Create();

app.UseGraphQL("/graphql")
    .AddGraphQLServer()
    .AddSchema(filteredSchema)
    .ModifyOptions(o => o.EnableMetrics = false)
    .AddAuthorization();

By combining HMAC integrity checks with explicit schema and operation policies, you reduce the attack surface while maintaining legitimate access patterns.

Related CWEs: dataExposure

CWE IDNameSeverity
CWE-200Exposure of Sensitive Information HIGH
CWE-209Error Information Disclosure MEDIUM
CWE-213Exposure of Sensitive Information Due to Incompatible Policies HIGH
CWE-215Insertion of Sensitive Information Into Debugging Code MEDIUM
CWE-312Cleartext Storage of Sensitive Information HIGH
CWE-359Exposure of Private Personal Information (PII) HIGH
CWE-522Insufficiently Protected Credentials CRITICAL
CWE-532Insertion of Sensitive Information into Log File MEDIUM
CWE-538Insertion of Sensitive Information into Externally-Accessible File HIGH
CWE-540Inclusion of Sensitive Information in Source Code HIGH

Frequently Asked Questions

Does disabling introspection break existing clients that rely on schema discovery?
Yes, clients that depend on introspection for tooling or dynamic schema queries will need to obtain schema information through alternative, controlled channels, such as an internal registry or restricted admin endpoint.
Can HMAC validation alone protect a GraphQL API if introspection is left enabled?
No. HMAC validates request integrity and origin but does not enforce operation-level authorization. Introspection remains reachable by any client that passes HMAC checks, increasing information disclosure risk.