Graphql Introspection in Actix with Hmac Signatures
Graphql Introspection in Actix with Hmac Signatures — how this specific combination creates or exposes the vulnerability
GraphQL introspection allows clients to query the schema, types, and operations of an API. When an Actix service exposes a GraphQL endpoint without protective measures, introspection can reveal sensitive field names, query patterns, and relationships that aid reconnaissance. If the endpoint also uses Hmac Signatures for request authentication but applies the signature only to selected routes or a subset of operations, an attacker can compare signed and unsigned paths to infer which operations require authentication.
In this combination, the vulnerability arises when introspection is permitted over HTTP methods that are not protected by Hmac Signatures. For example, a POST /graphql may validate an Hmac header for mutation operations but allow queries (including introspection) without signature verification. Because introspection can be performed unauthenticated, an attacker can enumerate operations and arguments, then craft valid-looking queries that bypass intended access controls. The presence of Hmac Signatures may create a false sense of protection if coverage is inconsistent, leading to privilege escalation via BOLA/IDOR-style traversal discovered through introspection data.
Consider an Actix GraphQL server where the introspection query is reachable without Hmac validation:
{
__schema {
queryType {
name
}
mutationType {
name
}
types {
...FullType
}
}
}
fragment FullType on __Type {
kind
name
description
fields(includeDeprecated: true) {
name
description
args {
name
description
type {
...TypeRef
}
}
}
inputFields {
name
description
type {
...TypeRef
}
}
interfaces {
...TypeRef
}
enumValues(includeDeprecated: true) {
name
description
}
possibleTypes {
...TypeRef
}
}
fragment TypeRef on __TypeRef {
kind
name
ofType {
kind
name
ofType {
kind
name
}
}
}
If this query reaches an Actix handler that does not enforce Hmac Signatures, an attacker obtains the full schema without needing credentials. This information can be used to identify endpoints with Hmac protection and focus further exploitation on inconsistencies. The risk is compounded when the API uses opaque identifiers (BOLA/IDOR) revealed through introspection, enabling horizontal privilege escalation across user boundaries.
Hmac Signatures-Specific Remediation in Actix — concrete code fixes
To secure the combination of GraphQL introspection and Hmac Signatures in Actix, enforce signature validation uniformly across all GraphQL operations, including queries and introspection. Use middleware to inspect the presence and correctness of the Hmac header before routing to the GraphQL handler. Ensure the signature covers the full request path, method, and body to prevent selective bypass.
Below is a concrete, working example of Hmac signature verification in Actix. The middleware computes the Hmac over the request method, path, and body using a shared secret, then compares it with the header value in constant time.
use actix_web::{dev::ServiceRequest, dev::ServiceResponse, Error, HttpMessage};
use actix_web_lab::middleware::Next;
use hmac::{Hmac, Mac};
use sha2::Sha256;
use std::time::SystemTime;
type HmacSha256 = Hmac;
async fn verify_hmac(req: ServiceRequest, next: Next<impl actix_web::body::MessageBody>) -> Result<ServiceResponse, Error> {
// In production, load secret securely (e.g., env, vault)
let secret = std::env::var("HMAC_SECRET").expect("HMAC_SECRET must be set");
let secret = secret.as_bytes();
let method = req.method().clone();
let path = req.path().to_string();
let body = match req.body().as_ref() {
actix_web::web::Bytes::from_ref(b) => b.as_ref(),
_ => &[],
};
let mut mac = HmacSha256::new_from_slice(secret).expect("HMAC can take key of any size");
mac.update(method.as_str().as_bytes());
mac.update(path.as_bytes());
mac.update(body);
let result = mac.finalize();
let computed = result.into_bytes();
let provided = match req.headers().get("X-Auth-Hmac") {
Some(h) => h.to_str().unwrap_or(""),
None => "",
};
// Constant-time comparison to avoid timing attacks
if computed.len() != provided.len() || subtle::ConstantTimeEq::ct_eq(&computed, provided.as.as_bytes()).into() {
let response = req.into_response(
actix_web::HttpResponse::Unauthorized()
.body("Invalid or missing Hmac signature")
);
return Err(actix_web::error::ErrorUnauthorized("Invalid Hmac"));
}
Ok(req.call_next(next).await?)
}
Apply this middleware globally so that introspection requests are also authenticated. In your GraphQL route configuration, ensure no path pattern excludes /graphql or allows OPTIONS/preflight without checks. Combine with query cost analysis and depth limiting to reduce exposure of schema details even when introspection is permitted for trusted clients.
For teams using the middleBrick ecosystem, the CLI can validate that your endpoints consistently enforce authentication by scanning the unauthenticated attack surface and flagging paths where introspection is reachable without Hmac Signatures. The GitHub Action can fail builds if risk scores drop below your defined threshold, while the MCP Server enables quick scans from your IDE during development.
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 |