Категория: Веб-сервер и инфраструктураОбновлено 2026-10-27

CORS (cross-origin resource sharing)

CORS (cross-origin resource sharing, совместное использование ресурсов между источниками) это механизм на основе HTTP-заголовков, с помощью которого сервер указывает, каким другим источникам браузер может разрешить загрузку его ресурсов. Без нужных заголовков Access-Control браузер не даст странице прочитать кросс-доменный ответ. Это правило браузера, а не файрвол, и аутентификацию API оно не заменяет.

Три шага CORS: страница вызывает API другого источника, браузер шлёт проверку preflight OPTIONS, затем идёт сам запрос
CORS проверяет браузер, поэтому curl и скрипты он не останавливает.

Источники, политика одного источника и роль CORS

Источник (origin) это сочетание схемы, хоста и порта. Страница на https://app.example.com и API на https://api.example.com это разные источники. По умолчанию, как объясняет руководство MDN по CORS, скрипты с fetch() подчиняются политике одного источника, и кросс-доменный ответ можно использовать, только если в нём есть правильные заголовки CORS. Через CORS сервер даёт на это согласие.

Простые запросы, например GET с безопасными заголовками, отправляются сразу, и сервер всё равно должен ответить заголовком Access-Control-Allow-Origin. Другие запросы, например с телом JSON или заголовком Authorization, вызывают preflight: браузер сначала посылает запрос OPTIONS с заголовками Access-Control-Request-Method и Access-Control-Request-Headers и отправляет настоящий запрос, только если ответ это разрешает. «Ошибка CORS» в консоли обычно значит, что в ответе не было заголовков, нужных браузеру.

Правильный ответ

Этот ответ на preflight разрешает вызывать API одному конкретному фронтенду:

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400
Vary: Origin

MDN отмечает, что если сервер указывает один источник, а не *, он должен также отправлять Vary: Origin. Заголовок Access-Control-Max-Age говорит, как долго браузер может кэшировать результат preflight. Ответ на preflight лишь даёт разрешение, поэтому настоящий ответ, который идёт следом, тоже должен содержать Access-Control-Allow-Origin.

Если фронтенд отправляет cookie или другие учётные данные, правила строже. Сервер обязан ответить Access-Control-Allow-Credentials: true и указать конкретный источник. По MDN, подстановочный знак * для запросов с учётными данными использовать нельзя, а браузер заблокирует такой ответ. Для публичных данных, запрашиваемых без учётных данных, Access-Control-Allow-Origin: * допустим.

Типичные ошибки

Разработчики часто вставляют подстановочный знак, чтобы ошибка исчезла из консоли. Вот шаблоны, которые ослабляют CORS:

Где настроить и как проверить

Настраивайте CORS только в одном месте: в промежуточном ПО приложения или на обратном прокси перед ним. В nginx это выглядит так:

add_header Access-Control-Allow-Origin "https://app.example.com" always;
add_header Vary Origin always;

В документации nginx сказано, что директивы add_header наследуются с верхнего уровня, только если на текущем их нет, а параметр always добавляет заголовок к любому коду ответа, включая ошибки. Поэтому location со своим add_header теряет унаследованные заголовки CORS.

Проверьте из командной строки, отправив Origin и прочитав заголовки ответа:

curl -i -H "Origin: https://app.example.com" https://api.example.com/items

Заголовки CORS отделены от заголовков безопасности, которые защищают саму страницу. Разрешайте только нужные источники, в духе политики «запрет по умолчанию», и включите проверку в свой чек-лист безопасности для вайб-кодинга.

Связанные термины: Обратный прокси, nginx, Заголовки безопасности, Политика «запрет по умолчанию».

Часто задаваемые вопросы

Что означает CORS и что он делает?

CORS расшифровывается как cross-origin resource sharing. Это механизм на основе HTTP-заголовков, с помощью которого сервер объявляет, каким другим источникам браузер может разрешить загрузку его ресурсов, смягчая политику одного источника.

Почему я получаю ошибку CORS?

Обычно в ответе сервера нет нужных браузеру заголовков Access-Control или они не совпадают с запросом. По MDN, большинство ошибок CORS можно исправить только на сервере, например вернув правильный разрешённый источник.

Безопасен ли Access-Control-Allow-Origin: *?

Для публичных данных, запрашиваемых без учётных данных, допустим. С cookie или другими учётными данными подстановочный знак запрещён, и браузер заблокирует ответ, поэтому укажите точный источник.

Защищает ли CORS мой API от атакующих?

Нет. CORS применяют браузеры, он не останавливает curl, скрипты и другие серверы. PortSwigger подчёркивает, что он не заменяет серверную защиту, поэтому оставляйте аутентификацию и авторизацию в своём API.

Почему браузер сначала отправляет запрос OPTIONS?

Это preflight. Для запросов, которые могут повлиять на данные пользователя, например с нестандартными заголовками, браузер сначала спрашивает сервер через OPTIONS, разрешён ли настоящий запрос.

Хотите увидеть, в каком состоянии ваш сервер?

Запустите бесплатную read-only проверку сервера или откройте Security Lab и посмотрите цикл обнаружение, сдерживание, восстановление, проверка в действии.

Получить бесплатную проверку сервераОткрыть Security Lab