Browsers can send a cross origin request without OPTIONS
preflight only for safe requests.
CORS-safelisted methods: GET
, HEAD
, POST
CORS-safelisted request-headers: Accept
, Accept-Language
, Content-Language
, Content-Type
CORS-safelisted content-types: application/x-www-form-urlencoded
, multipart/form-data
, text/plain
Separators | Browsers | Example |
---|---|---|
; | Content-Type: text/plain;xxx | |
, | Content-Type: text/plain,xxx |
Symbol | Browsers | Example |
---|---|---|
Fetch Spec: CORS-unsafe request-header byte 0x01-0x08 0x0E-0x1F : < > ? @ [ \ ] { } 0x7F |
Content-Type: text/plain;<xxx | |
0x09 0x20 ! # $ % & ' * + - . / 0-9 ; = A-Z ^ _ ` a-z | ~ | Content-Type: text/plain;#xxx | |
, 0x80-0xFF | Content-Type: text/plain;,xxx |
fetch("http://localhost/", {
method: "POST",
headers: {
"Content-Type": "$Content-Type$"
}
credentials: "include",
body: "test"
});
xhr = new XMLHttpRequest();
xhr.open("POST", "http://localhost/", true);
xhr.setRequestHeader("Content-Type", "$Content-Type$");
xhr.withCredentials = true;
xhr.send("test");
➖ - CORS preflight request
Content-Type | ||||
---|---|---|---|---|
text/plain | text/plain | text/plain | text/plain | text/plain |
TEXT/PLAIN | TEXT/PLAIN | TEXT/PLAIN | TEXT/PLAIN | TEXT/PLAIN |
text/plain; x=x | text/plain; x=x | text/plain; x=x | text/plain; x=x | text/plain; x=x |
text/plain; x="x" | ➖ | ➖ | text/plain; x="x" | ➖ |
text/plain; application/json | text/plain; application/json | text/plain; application/json | text/plain; application/json | text/plain; application/json |
text/plain;, application/json | text/plain;, application/json | ➖ | text/plain;, application/json | text/plain;, application/json |
text/plain;, application/json, text/plain | text/plain;, application/json, text/plain | ➖ | text/plain;, application/json, text/plain | text/plain;, application/json, text/plain |
application/json;, text/plain | ➖ | ➖ CVE-2015-7193 |
➖ | ➖ |
ct = '$Content-Type$';
blob = new Blob(["test"], {type: ct});
fetch("http://localhost/", {
method: 'POST',
credentials: "include",
body: blob
});
navigator.sendBeacon("http://localhost/", blob);
xhr = new XMLHttpRequest();
xhr.open("POST", "http://localhost/", true);;
xhr.withCredentials = true;
xhr.send(blob);
➖ - CORS preflight request
fetch("https://localhost/", {
method: "POST",
headers: [
["Content-Type", "text/plain"],
["Content-Type", "application/json"]
],
credentials: "include",
body: "test"
});
xhr = new XMLHttpRequest();
xhr.open("POST", "https://localhost/", true);
xhr.setRequestHeader("Content-Type", "text/plain");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.withCredentials = true;
xhr.send("test");
➖ - CORS preflight request