Браузери історично вміли «вгадувати» тип вмісту (MIME sniffing): якщо сервер віддав файл як text/plain, а всередині схоже на HTML чи JavaScript, браузер міг обробити його як HTML чи скрипт. Це допомагало погано налаштованим серверам, але відкривало вразливість.
Атака: користувач завантажує на ваш сайт файл, нібито зображення чи текст, але з вмістом-скриптом. Якщо потім цей файл підключають як <script src="/uploads/avatar.jpg"> (наприклад, через XSS, що дозволяє лише посилання на свій домен) чи відкривають напряму, браузер може «впізнати» в ньому HTML або JavaScript і виконати.
X-Content-Type-Options: nosniff вимикає вгадування:
X-Content-Type-Options: nosniff
- скрипти виконуються лише з JavaScript-типом (
text/javascriptта подібні) - файл зimage/jpegу<script>буде заблоковано; - стилі застосовуються лише з
text/css; - браузер довіряє заголовку
Content-Type, а не вмісту.
Що з цього випливає для бекенду:
- правильний
Content-Typeдля всього, що віддає сервер: JSON -application/json, JavaScript -text/javascript. Зnosniffнеправильний тип ламає сайт одразу, тому помилки знаходяться швидко; - файли користувачів - з типом, визначеним сервером за вмістом, а не за назвою файлу від користувача. Небезпечні типи (HTML, SVG з можливими скриптами) - з
Content-Disposition: attachment, щоб браузер завантажував їх, а не відкривав; - окремий домен для користувацького контенту (як
githubusercontent.com) - найнадійніший захист: навіть якщо файл виконається, він не матиме доступу до cookie й даних основного сайту.
Як додати в Laravel: власний middleware для групи web або налаштування вебсервера (Nginx/Caddy) для всіх відповідей. Заголовок дешевий і майже не має побічних ефектів - його ставлять завжди, разом з Referrer-Policy, frame-ancestors і CSP.