惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

大猫的无限游戏
大猫的无限游戏
Security Archives - TechRepublic
Security Archives - TechRepublic
T
Threat Research - Cisco Blogs
A
Arctic Wolf
S
Securelist
O
OpenAI News
T
Threatpost
Forbes - Security
Forbes - Security
N
News and Events Feed by Topic
S
Secure Thoughts
H
Heimdal Security Blog
S
Security Affairs
P
Privacy International News Feed
C
Cisco Blogs
C
CERT Recently Published Vulnerability Notes
Cyberwarzone
Cyberwarzone
N
News and Events Feed by Topic
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Palo Alto Networks Blog
S
Security @ Cisco Blogs
Hacker News - Newest:
Hacker News - Newest: "LLM"
博客园 - 三生石上(FineUI控件)
月光博客
月光博客
T
Tailwind CSS Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Hacker News: Ask HN
Hacker News: Ask HN
T
Troy Hunt's Blog
S
SegmentFault 最新的问题
腾讯CDC
V
Visual Studio Blog
Last Week in AI
Last Week in AI
H
Hacker News: Front Page
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Project Zero
Project Zero
WordPress大学
WordPress大学
NISL@THU
NISL@THU
博客园 - 【当耐特】
博客园 - Franky
Webroot Blog
Webroot Blog
博客园_首页
T
Tenable Blog
雷峰网
雷峰网
Google Online Security Blog
Google Online Security Blog
阮一峰的网络日志
阮一峰的网络日志
V2EX - 技术
V2EX - 技术
Recent Commits to openclaw:main
Recent Commits to openclaw:main
L
Lohrmann on Cybersecurity
The Hacker News
The Hacker News

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
FastCGI исполнилось 30 лет, и он до сих пор лучше HTTP для прокси-к-бэкенду
arthurpro · 2026-05-04 · via Все публикации подряд на Хабре

Уровень сложностиСредний

Время на прочтение9 мин

Охват и читатели1.4K

Обзор

Перевод

Знаете, кому 29 апреля стукнуло 30 лет? Спецификации FastCGI. Тридцать лет с 1996 года. Погодите. Эта заметка не про ностальгию по .fcgi-скриптам, которые на каждый запрос форкали отдельный процесс и которыми сегодня никто не пользуется. И не про CGI вообще.

Разговор о другом. У нас всех в проде между прокси и бэкендом обычно стоит HTTP. nginx перед Go-приложением, Caddy перед Python-сервисом, Apache перед PHP-FPM, неважно, поверх там HTTP/1.1 или HTTP/2. И вот Эндрю Айер на agwa.name к юбилею FastCGI собрал аргументы, что этот участок инфраструктуры всё это время сидит на не самом удачном протоколе. Айер основатель SSLMate, и в SSLMate всё крутится на FastCGI в проде уже больше десяти лет. Так что пишет не теоретически.

Заметка короткая и по делу. HN-тред собрал сотню комментариев, для 2026 года это не топ, но там пишут люди, которые знают, о чём говорят. Если попроще, аргумент такой: у HTTP как протокола между прокси и бэкендом есть два структурных бага, которых у FastCGI нет, и индустрия за тридцать лет так и не нашла повода переехать. А обсуждение в треде ушло дальше: почему вообще HTTP победил, если он хуже технически. И ответ оказался любопытнее самого аргумента.

Что у HTTP сломано — десинк-атаки

Первый структурный баг это request smuggling, он же desync. Звучит страшно, но суть простая.

У HTTP/1.1 есть свойство, которое Айер называет «it’s just text!»: вроде бы всё прозрачно. А на деле распарсить HTTP корректно очень непросто. В протоколе нет явного фрейминга. Сообщение само описывает, где оно заканчивается: либо через Content-Length, либо через Transfer-Encoding, иногда через оба сразу. И в правилах разбора накопилось столько edge case’ов, что две реализации HTTP могут по-разному определять, где одно сообщение закончилось, а второе началось.

Дальше история становится неприятной. Допустим, в одном звене у вас reverse proxy, в другом бэкенд. Парсят они HTTP чуть-чуть по-разному. Атакующий может протащить второй запрос внутри тела первого. Прокси обработает один запрос, а бэкенд распарсит его как два. Второй запрос приедет на бэкенд с привилегиями чужой сессии. Так и работает desync.

Каноничный пример: смесь Content-Length и Transfer-Encoding в одном запросе.

POST / HTTP/1.1
Host: example.com
Content-Length: 35
Transfer-Encoding: chunked

0

GET /admin HTTP/1.1
Host: example.com

Прокси смотрит на Content-Length: 35 и считает, что тело POST занимает все 35 байт ниже (включая «GET /admin…»). Бэкенд смотрит на Transfer-Encoding: chunked, видит 0\r\n\r\n и считает, что тело закончилось. Хвост GET /admin HTTP/1.1 он распарсит как новый запрос, пришедший по той же сессии. Класс называется CL.TE smuggle, есть и зеркальный TE.CL.

Свежий пример, с которого Айер начинает: десинк в Discord media proxy, раскрытый в начале этого года. Можно было читать чужие приватные вложения. Класс багов старый, его подробно описала Watchfire ещё в 2005 году, и тогда же предупредила. Попытки лечить это в духе «починим парсеры» обречены, потому что парсеров много и они продолжат расходиться. Двадцать лет спустя Джеймс Кеттл из PortSwigger примерно раз в год находит новые варианты. После последней пачки запустил сайт с одним адресом и одним сообщением: http1mustdie.com, «HTTP/1.1 must die».

HTTP/2 эту проблему решает, но только если он стоит и на прокси, и на бэкенде. Тогда у сообщений есть чёткие границы. FastCGI решил то же самое в 1996 году, более простым протоколом, потому что у него границы тоже чёткие. И вот тут Айер замечает интересную деталь. nginx поддерживает FastCGI-бэкенды с самого первого релиза. А HTTP/2 на бэкенд у nginx появился только в конце 2025-го. У Apache бэкендный HTTP/2 до сих пор экспериментальный. FastCGI был под рукой всё это время.

Что у HTTP сломано — путаница с заголовками

Второй баг — про заголовки.

У HTTP нет нормального способа отличить доверенные данные о запросе от того, что прислал клиент. Реальный IP клиента, имя авторизованного пользователя, детали клиентского сертификата — всё это прокси хочет передать дальше. Но передаёт через те же HTTP-заголовки, которые отправляет и клиент. Обычная схема такая: внутри команды договорились, что X-Real-IP, X-Forwarded-For, True-Client-IP это «наши» прокси-заголовки. Прокси сам их выставляет, а в клиентских запросах их заранее режет.

В теории нормально. На практике это минное поле, потому что между «доверенным заголовком» и «недоверенным заголовком» в HTTP нет никакой структурной разницы. Это всё просто заголовки. И где-нибудь в стеке у вас сидит библиотека, которая читает не тот заголовок, который вы зачистили, а соседний.

Конкретно у Айера такой пример. Go-шный middleware Chi сначала читает True-Client-IP, и только если его нет, читает X-Real-IP. Вы добросовестно зачистили X-Real-IP на прокси. Атакующий шлёт True-Client-IP. Chi читает его. И реальный IP клиента в вашем приложении это то, что прислал атакующий.

У FastCGI этого бага не может быть по определению. Параметры запроса и HTTP-заголовки от клиента живут в одном словаре key/value, но клиентские заголовки имеют префикс HTTP_. Прокси выставляет, например, REMOTE_ADDR напрямую. Чтобы клиент сумел подделать REMOTE_ADDR, ему нужно прислать заголовок с буквальным именем HTTP_REMOTE_ADDR, а бэкенд распознает его как клиентский, а не как доверенный.

На уровне wire-формата это видно сразу. Параметры приходят к бэкенду как набор пар ключ-значение:

REMOTE_ADDR             = 203.0.113.42          # доверенный (выставил прокси)
SERVER_NAME             = example.com           # доверенный
HTTP_HOST               = example.com           # клиентский (был в Host: header)
HTTP_USER_AGENT         = Mozilla/5.0           # клиентский
HTTP_X_FORWARDED_FOR    = evil.com              # клиентский (попытка прикинуться прокси)

Префикс HTTP_ буквально на уровне формата отделяет то, что прислал клиент, от того, что выставил прокси. По именам столкнуться нельзя.

То есть в FastCGI попытка подделки выглядит иначе, чем настоящая атака. Класса коллизий по именам заголовков там просто нет: разделение «доверенное / недоверенное» заложено в сам формат wire-протокола.

Сводка по двум классам багов:

Структурный баг

HTTP/1.1

HTTP/2

FastCGI

Request smuggling / desync

уязвим

защищён, если используется на всём пути

защищён по конструкции

Подделка X-Forwarded-For и подобных

уязвим

уязвим

защищён через HTTP_

FastCGI это не CGI

Главное возражение в HN-треде звучит сразу: FastCGI ассоциируется со старыми .fcgi-скриптами. Те самые, что на каждый запрос форкали процесс и которыми сегодня никто не пользуется. Айер аккуратно разделяет эти две сущности: FastCGI как wire-протокол и FastCGI как process model это разные вещи. Process model устарел. Wire-протокол всё ещё актуален. Сегодня FastCGI это просто альтернативный транспорт для HTTP-запросов поверх TCP- или Unix-сокета.

В Go переход делается тривиально. Было:

l, _ := net.Listen("tcp", "127.0.0.1:8080")
http.Serve(l, handler)

Стало:

l, _ := net.Listen("tcp", "127.0.0.1:8080")
fcgi.Serve(l, handler)

fcgi.Serve это drop-in замена для http.Serve. Хендлер тот же. http.ResponseWriter и http.Request остаются те же типы.

nginx, Apache, Caddy, HAProxy: у каждого FastCGI-бэкенды настраиваются одной-двумя строчками конфига. Например, в nginx разница между HTTP-бэкендом и FastCGI-бэкендом одна строчка плюс инклуд:

# HTTP бэкенд
location / {
    proxy_pass http://127.0.0.1:8080;
}

# FastCGI бэкенд
location / {
    fastcgi_pass 127.0.0.1:8080;
    include fastcgi_params;
}

По объёму работы это как прикрутить TLS-терминирование. Только потом возни сильно меньше.

Айер ещё отмечает приятный момент. Стандартная Go-шная либа net/http/fcgi сама достаёт Request.RemoteAddr из доверенного REMOTE_ADDR. И сама же выставляет ненулевое поле Request.TLS, если прокси сообщил, что клиент пришёл по HTTPS. Тот middleware, который в Go-сервисах обычно достаёт реальный IP из X-Forwarded-For, в случае с FastCGI просто не нужен. «It Just Works», пишет Айер, и это редкий момент эмоций в очень сухом тексте.

Честные минусы у FastCGI тоже есть, и Айер их перечисляет.

WebSocket’ов в FastCGI нет, так и не доделали. Тулинг победнее: curl его не понимает, хотя умеет в FTP, Gopher и SMTP. Когда Айер прогонял бенчмарки Go-шного FastCGI-сервера через разные reverse proxy, на части нагрузок пропускная способность оказывалась хуже, чем на HTTP/1.1 или HTTP/2. Сам он это объясняет тем, что код-пути FastCGI в индустрии оптимизировали в разы меньше, чем HTTP. Не врождённый дефект протокола, а недополученное внимание. И сегодняшний облачный подход в духе «просто давайте HTTP, мы обработаем» места под FastCGI в инфраструктуре особо не оставил, хотя технически большинство компонентов его поддерживают.

Почему HTTP всё-таки победил

Тут начинается интересное. Если FastCGI и правда структурно лучше, и при этом он тридцать лет как готовый, то почему рынок остался на HTTP?

Самый полезный комментарий в HN-треде объясняет это через end-to-end principle. Идея этого принципа простая: пусть сеть будет максимально тупой, а вся прикладная логика живёт на концах. Тогда между endpoint’ами можно набрасывать любые промежуточные звенья: кеш, фильтр от DDoS, региональный роутер, TLS-терминатор, шлюз авторизации. И каждое из них может ничего не знать про остальные. HTTP-везде это и есть буквальное воплощение принципа для веба. У вас одно приложение работает в дев-режиме с прямым подключением из браузера, и оно же работает в проде за пятью слоями прокси. И кода при этом менять не надо.

А у Айера в статье на знамени стоит другой принцип, principle of least privilege. По-русски «минимально необходимые привилегии», но в контексте сетевой безопасности удобнее переводить как «доверять только тому, что явно ожидаешь». «Allowlist your communications to only what you expect, so that you aren’t unwittingly contributing to a compromise elsewhere in the network», пишет Айер. Не доверяй заголовкам, которых не просил. И не оставляй неоднозначностей фрейминга в формате: разделяй «доверенное» и «недоверенное» структурно.

Оба принципа правильные. И вот в чём дело: они спорят за одно и то же место. End-to-end даёт вебу композициональную гибкость, ту самую, благодаря которой веб тридцать лет уделывает любые закрытые альтернативы. Least privilege ловит ровно тот класс багов, про который пишет Айер: где у пользователя Discord утекают приватные вложения, потому что два парсера разошлись в edge case’е Content-Length. И там, и там вред реальный. Вопрос только в том, какой класс вреда сейчас больнее. Практический ответ: смотря что вы запускаете.

Вторая ветка обсуждения в треде идёт в другую сторону. Аргумент такой: connection caching и multiplexing, которыми современный HTTP-стек пользуется буквально на каждом шагу, и так уже нарушают end-to-end. Класса desync-багов мы получили не потому, что выбрали HTTP. Мы получили его, потому что выбрали HTTP, плюс закешировали соединения, плюс мультиплексировали запросы по этим соединениям через весь стек. И при этом продолжали делать вид, что топология осталась end-to-end. Десинк-атаки живут ровно в тех точках, где эта иллюзия рассыпается.

Третья ветка приводит ещё один кейс. Гугл уже давно внутри своих сервисов пользуется собственным RPC под названием Stubby. Stubby оборачивает HTTP-семантику в другой wire-протокол для service-to-service трафика. На границе с интернетом у Гугла HTTP. А между сервисами внутри границы уже не HTTP. По этому аргументу, композициональная гибкость имеет смысл на границе сети. Внутри границы, на участке прокси-к-бэкенду, никакой границы уже нет. Принцип применяется там, где ему делать нечего.

Если посмотреть под этим углом, вся статья Айера читается иначе. Айер не утверждает, что HTTP плохой протокол. HTTP отлично справляется с участком браузер-к-краю, где как раз и нужна end-to-end-композициональность. Он показывает, что участок прокси-к-бэкенду уже не end-to-end, и HTTP туда импортирует класс багов, которого там быть не должно. FastCGI как wire-формат это и есть HTTP, переосмысленный под актуальные ограничения этого участка: явный фрейминг, структурное разделение доверенного и недоверенного, нет класса коллизий имён.

Что говорят те, кто давно в проде

Тред в основном собран из спокойных свидетельств людей, которые давно с этим живут в проде.

SSLMate на FastCGI больше десяти лет — это один пример. Другие в комментариях писали, что у них «все веб-клиенты» живут на FastCGI больше десяти лет.

Подробнее всего в треде разбирали uWSGI. Один комментатор писал, что в нескольких местах прокси-бэкенд жил на uWSGI много лет, и в основном это был положительный опыт. Ещё один описывал собственный протокол под названием WAS (Web Application Socket), который у него на работе в CM4all лет пятнадцать назад спроектировали с нуля как отдельный открытый протокол. WAS до сих пор крутится в проде CM4all, в хостинговых окружениях с PHP.

У всех таких историй один общий вывод: если на участке прокси-бэкенд использовать не-HTTP протокол и какое-то время его погонять, целый класс багов из стека просто пропадает.

В треде звучали и возражения, и они тоже по делу. Один комментатор описывал, как в эпоху FastCGI/SCGI/HTTP основывал Web 2.0-стартап и выбрал HTTP, потому что «вместо ещё одного протокола в стеке можно просто использовать HTTP, который вам всё равно нужен на гейтвее». Экономия на сетапе реальная. nginx тогда работал заметно быстрее большинства FastCGI/SCGI-модулей того времени и был стабильнее. Это тоже не выдумка. Когда годы спустя стоимость security-багов выросла до бесконечной серии CVE, стоимость миграции уже выросла соразмерно.

Сам Айер в треде дал отдельное уточнение про CGI, и это важная сноска. У классического CGI был свой footgun, httpoxy: переменные окружения, через которые передавались HTTP-заголовки, могли совпасть с переменной HTTP_PROXY и переадресовать исходящий трафик приложения. К FastCGI это не относится, потому что FastCGI передаёт параметры не через окружение, а через свой словарь. Различие конструктивное, не косметическое.

Так что же, переезжать?

Если без пафоса, ответ для большинства сервисов скучный: скорее всего, нет.

Стоимость миграции реальная. Сервис у вас уже работает на HTTP, у вас отлажены конфиги прокси, есть мониторинг, есть привычки команды. Threat model можно держать в рабочем состоянии и без смены wire-протокола: аккуратно зачищать заголовки на прокси, держать актуальный HTTP/2-стек на маршруте прокси-бэкенд, следить за странностями в логах. Если вы не Discord и не личный кабинет крупного банка, шанс, что вы первый словите свежий вариант desync-атаки, невелик.

Но интересный вопрос здесь не «переезжать или нет». Интересный вопрос: почему индустрия двадцать лет лечит request smuggling в стиле «починим парсеры построже», а не в стиле «возьмём протокол, у которого этого класса багов нет в принципе». Статья Watchfire вышла в 2005 году. С тех пор счёт CVE по request smuggling идёт на сотни. Каждый раз новая порция, потому что парсеры опять разошлись в новой точке. А ответ из индустрии всегда один: вместо «может, проблема в самой спецификации» получаем «давайте быстренько подкрутим спецификацию».

Айер в финале пишет, что выбор wire-протокола на стыке прокси-бэкенда — это решение про безопасность, и что мы тридцать лет делаем вид, что это решение про удобство. Счёт по CVE отражает разницу. И тридцатилетие FastCGI это хороший повод запомнить, что счёт ещё пополняется, и что альтернатива доступна — совсем не новая, не экзотическая, и поставить её можно без особых сложностей. «Happy 30th birthday, FastCGI», заканчивает он. Запомним год, в котором этот вопрос задали ещё раз, даже если ответ снова не сдвинет рынок ближайшие десять лет.


Оригинал — мой авторский разбор для англоязычной аудитории. Перевод и доводка — с AI на подхвате.