Jwt None Algorithm in Actix (Rust)
Jwt None Algorithm in Actix with Rust
The JWT none algorithm is a known vulnerability class (CVE‑2016‑10555 and similar patterns) where a token with {"alg":"none"} is accepted without signature verification. When used in an Actix web service written in Rust, this can occur if the server-side JWT validation logic does not explicitly enforce a required algorithm. An attacker can craft a token with alg: none and a valid user payload (e.g., {"sub": "admin"}), then send it in the Authorization header as Bearer eyJhbGciOiJub25lIn0.eyJzdWIiOiJhZG1pbiJ9. Because the signature is empty and the server does not reject the algorithm, the token may be accepted as authenticated, leading to unauthorized access, privilege escalation, or bypass of Actix guards.
In Rust Actix applications, developers often use crates like jsonwebtoken or actix-web-httpauth. If the validation configuration does not specify an expected algorithm, or if the deserialization step trusts the header, the server may default to accepting none. For example, deserializing the token header without enforcing algorithm constraints can be represented in Rust as:
use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation};
fn validate_token(token: &str) -> Result<jsonwebtoken::TokenData<Claims>, jsonwebtoken::errors::Error> {
let mut validation = Validation::new(Algorithm::HS256);
// Danger: not restricting algorithms strictly can allow "none"
validation.leeway = 0;
validation.validate_exp = true;
decode<Claims>(token, &DecodingKey::from_secret(&[]), &validation)
}
In the above, specifying Algorithm::HS256 in Validation::new is intended to restrict accepted algorithms. However, if the validation setup is incomplete—such as omitting algorithm checks or using a permissive configuration—Actix may process the request, and the unchecked header can lead to acceptance of the none algorithm. This is particularly risky when combined with role claims in the payload, enabling attackers to gain elevated permissions without valid credentials.
middleBrick detects this class of issue during unauthenticated scans by analyzing OpenAPI specifications and runtime behavior. If your API is defined with security schemes that expect a bearer token but do not explicitly require a strong algorithm, or if the runtime behavior accepts unsigned tokens, middleBrick flags this as a high-severity finding under Authentication and BOLA/IDOR checks. Reports include prioritized findings with severity, references to the relevant OWASP API Top 10 category, and remediation guidance. For teams using the Pro plan, continuous monitoring can alert on such regressions as APIs evolve, while the CLI allows quick local verification via middlebrick scan <url>.
To ensure robust security, always pair runtime scanning with code-level enforcement. Combine specification-driven validation with strict algorithm settings in Rust, and verify that your Actix middleware rejects tokens that do not match the expected cryptographic properties.
Rust-Specific Remediation in Actix
To remediate the JWT none algorithm risk in Actix with Rust, explicitly configure token validation to accept only the required algorithm(s) and enforce strict header checks. The following example demonstrates a hardened approach using the jsonwebtoken crate within an Actix extractor or guard.
First, define your claims and a validation function that rejects unsigned tokens:
use actix_web::{dev::ServiceRequest, Error, HttpMessage};
use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation, TokenData};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
#[derive(Debug, Serialize, Deserialize, Clone)]
struct Claims {
sub: String,
roles: Vec<String>,
}
fn validate_jwt(token: &str, secret: &[u8]) -> Result<TokenData<Claims>, jsonwebtoken::errors::Error> {
let mut validation = Validation::new(Algorithm::HS256);
validation.leeway = 0;
validation.validate_exp = true;
// Explicitly require the expected algorithm; reject "none"
validation.set_required_spec_claims(&["exp", "iat"]);
decode<Claims>(token, &DecodingKey::from_secret(secret), &validation)
}
Second, integrate this validation into Actix via an extractor or middleware that fails the request if the token is invalid or uses a disallowed algorithm:
pub async fn auth_middleware(
req: ServiceRequest,
secret: Arc<[u8]>
) -> Result<ServiceRequest, (Error, ServiceRequest)> {
let auth_header = req.headers().get("Authorization");
let token = match auth_header {
Some(h) => h.to_str().map_err(|_| (/* unauthorized error */))?.strip_prefix("Bearer ").ok_or(...)?,
None => return Err((/* unauthorized error */, req)),
};
match validate_jwt(token, &secret) {
Ok(token_data) => {
req.extensions_mut().insert(token_data);
Ok(req)
}
Err(_) => Err((/* unauthorized error */, req)),
}
}
Additionally, if you use actix-web-httpauth, configure the bearer extractor to validate algorithms explicitly:
use actix_web_httpauth::extractors::bearer::BearerAuth;
async fn protected_route(auth: BearerAuth) -> impl Responder {
let token = auth.token();
match validate_jwt(token, &SECRET) {
Ok(_) => HttpResponse::Ok().finish(),
Err(_) => HttpResponse::Unauthorized().finish(),
}
}
These Rust-specific fixes ensure the server does not trust the JWT header’s algorithm field implicitly. By specifying Algorithm::HS256 (or another concrete algorithm) and setting required claims, you prevent acceptance of the none algorithm. middleBrick can verify the effectiveness of these controls by scanning the unauthenticated attack surface and, for Pro users, by running continuous checks that detect regressions in API security posture.