Están a salvo debido a la Política del mismo origen: un origen A (site.com) no puede leer un recurso de otro origen (other.fr) a menos que haya incluido en la lista blanca que usa Access-Control-Allow-Origin .
En el caso de CSRF básico, el ataque no consiste en leer la respuesta, sino que consiste en engañar al servidor para que realice una acción que fue disparada por un usuario víctima sin que esta víctima lo sepa.
Por lo tanto, en CSRF básico, la víctima tiene un token que el atacante no puede conocer (la política del mismo origen lo impide). Cuando la víctima solicita algo al servidor ( /user/delete?id=15
pero en el mundo real, no pase el ID por GET
sino por POST
porque está cambiando el estado del servidor), entonces el servidor verificará si ese token está presente y es válido. Si no (porque lo dispara el atacante, que no puede conocer el token), el servidor se niega a procesarlo y el usuario 15 no se elimina. Cuando el token está aquí y es válido, el servidor elimina al usuario y devuelve la respuesta (el atacante aún no puede leer esa respuesta).
Así, Same-Origin evita que el atacante lea la respuesta, mientras que el token CSRF evita que el servidor procese una solicitud no preparada.