Слушай покопался в теме, стало интересно, у owasp есть просто набор правил который говорит о том что надо чистить данные перед выводом, но это общие правила, которые не учитывают никак твой бэк или вообще стек технологий.
Возникло пару вопросов об XSS
По поводу подмены ввода, которую ты описывал, ведь в двух подходах юзер увидит одинаковый результат, вне зависимости, почистил(или экранировал/подменил) я данные при получении их из инпута перед вставкой в БД или после получения данных из бд во время вывода на фронт.
Если конечный результат одинаковый, тогда зачем мне хранить в базе данных заведомо вредную инфу? И получается не доверять данным, которые в ней находятся.
По поводу кол-ва мест в которых можно провтыкать - похоже что оно абсолютно одинаковое, вопрос в том где тебе их легче отловить (хотя правильно конечно делать и там и там) на входе когда ты точно ожидаешь данные с фронта или каждый раз думать о выводе "а не вводил ли это юзер с фронта"
По поводу prepared statments и валидации абсолютно согласен, хочу понять в чем профит от такого подхода к XSS
Ну давай разбираться.
Согласимся, что речь идет о приложениях или системах, которые развиваются - к ним меняются требования, вносятся изменения, дописываются или удаляются фичи, фиксятся баги и т.д. Кто-то открывает исходный код и пытается его понять, а иногда и поменять.
Во-вторых, понятно, что мы говорим о достаточно сложных системах, в которых есть отдельное хранилище (БД), выделен пользовательский интерфейс (иначе нам не надо было бы кодировать данные в HTML/JSON), возможно есть внешние или внутренние сервисы (иначе не надо было бы париться об url_encoding).
Когда оба эти условия выполнены, всплывает такая размытая штука как архитектура и "хороший код". Про это написаны тонны книжек, иногда противоречивых, но есть вещи, с которыми согласны очень многие. Например понятия "зоны ответственности", separation of concerns, business rules. Если следовать этим понятиям, и у БД, и у "ядра" приложения, и у шаблонизатора, и у внешних сервисов есть то, что назвается "контракт" - свой набор функций (роль как у части единой системы) и интерфейс (API, "язык", на котором часть системы общается с другими частями). БД должна принять запрос в формате SQL и сохранить/выдать данные в точности как сказано в запросе. HTML шаблон должен принять текст и сделать так, чтобы в браузере он выглядел в точночти также, как был получен шаблоном. Сервис принимает команды по HTTP. И так далее. Разработчик, когда открывает исходный код, надеется, что код следует этим общепринятым правилам, что каждая часть системы делает ровно то, что должна, не больше и не меньше, и в любых обстоятельствах. Бизнес-требования меняются. За реализацию бизне-требований отвечает "ядро" приложения. То, что сегодня "заведомо вредная инфа" завтра станет багрепортом от пользователя "ой, я запостил важное сообщение, а ваша система его испортила" или судебным иском от клиента. Поэтому разработчик полезет менять логику бизнес-требований в ядро, а не в шаблонизатор или БД. Вообще, чем меньше частей системы затрагиваются для выполнения одного изменения, тем лучше, т.к. меньше шансов внести ошибку (гуглить Single Responsibility Principle).
Когда ты проектируешь транспортный (или сервисный, если угодно) уровень системы так, что он может работать только с "правильными" данными, ты расставляешь ловушки в коде. Слои системы начинают зависить друг от друга неочевидным образом. Поддерживать и развивать такую систему становится очень сложно, долго и дорого. В итоге это скажется на клиентах и на бизнесе. Так что "конечный результат одинаковый" это заблуждение.