openai/codex · error · anyhow::Error
invalid agent identity JWT format
Error message
invalid agent identity JWT format
What it means
An inject_request_headers entry selected secret_file as its secret source, but the string is empty or whitespace-only. parse_secret_file requires a usable path because the proxy reads the file's contents at request time to build the header value, so a blank path can never resolve. Raised during validate_injected_headers at config load and again when hooks compile.
Source
Thrown at codex-rs/agent-identity/src/lib.rs:296
let jwk = jwks
.find(&kid)
.with_context(|| format!("agent identity JWT kid {kid} is not trusted"))?;
let decoding_key = DecodingKey::from_jwk(jwk).context("failed to build JWT decoding key")?;
let mut validation = Validation::new(Algorithm::RS256);
validation.set_audience(&[AGENT_IDENTITY_JWT_AUDIENCE]);
validation.set_issuer(&[AGENT_IDENTITY_JWT_ISSUER]);
validation.required_spec_claims.insert("iss".to_string());
validation.required_spec_claims.insert("aud".to_string());
decode::<AgentIdentityJwtClaims>(jwt, &decoding_key, &validation)
.map(|data| data.claims)
.context("failed to verify agent identity JWT")
}
fn decode_agent_identity_jwt_payload<T: DeserializeOwned>(jwt: &str) -> Result<T> {
let mut parts = jwt.split('.');
let (_header_b64, payload_b64, _sig_b64) = match (parts.next(), parts.next(), parts.next()) {
(Some(h), Some(p), Some(s)) if !h.is_empty() && !p.is_empty() && !s.is_empty() => (h, p, s),
_ => anyhow::bail!("invalid agent identity JWT format"),
};
anyhow::ensure!(parts.next().is_none(), "invalid agent identity JWT format");
let payload_bytes = URL_SAFE_NO_PAD
.decode(payload_b64)
.context("agent identity JWT payload is not valid base64url")?;
serde_json::from_slice(&payload_bytes).context("agent identity JWT payload is not valid JSON")
}
pub fn sign_task_registration_payload(
key: AgentIdentityKey<'_>,
timestamp: &str,
) -> Result<String> {
let signing_key = signing_key_from_private_key_pkcs8_base64(key.private_key_pkcs8_base64)?;
let payload = format!("{}:{timestamp}", key.agent_runtime_id);
Ok(BASE64_STANDARD.encode(signing_key.sign(payload.as_bytes()).to_bytes()))
}
View on GitHub (pinned to 339751715c)
Solutions
- Set secret_file to a non-empty absolute path the proxy can read: secret_file = "/etc/codex/github.token"
- If the secret should come from the environment instead, remove secret_file and set secret_env_var
- Check file permissions — the proxy process must be able to read it at request time
Example fix
// config.toml — before [[network.mitm_hooks.actions.inject_request_headers]] name = "authorization" secret_file = "" // after [[network.mitm_hooks.actions.inject_request_headers]] name = "authorization" secret_file = "/etc/codex/github.token" prefix = "Bearer "
Defensive patterns
Strategy: validation
Validate before calling
for header in &hook.actions.inject_request_headers {
if let Some(file) = header.secret_file.as_deref() {
if file.trim().is_empty() {
return Err(anyhow!("{} has a blank secret_file", header.name));
}
}
} Type guard
fn secret_file_nonempty(header: &InjectedHeaderConfig) -> bool {
header.secret_file.as_deref().map_or(true, |f| !f.trim().is_empty())
} Prevention
- Treat a present-but-empty secret_file as a missing field in config linters
- Verify the file exists and is readable by the proxy user before launch
- Pick one secret mechanism per deployment and template only that field
When it happens
Trigger: [[network.mitm_hooks.actions.inject_request_headers]] with secret_env_var removed and secret_file = "" (or whitespace-only) — validation aborts config load before the proxy starts.
Common situations: A placeholder empty string that was never replaced; migration from secret_env_var where the env key was deleted but the file field was never filled in.
Related errors
- invalid agent graph store request: {message}
- agent graph store internal error: {message}
- Unsupported platform: ${platform} (${arch})
- Unsupported target triple: ${targetTriple}
- Missing optional dependency ${platformPackage}. Reinstall Co
AI-assisted analysis of openai/codex@339751715c (2026-08-25).
Data as JSON: /api/errors/1d1239c5d3836103.
Report an issue: GitHub.