3.1Kпросмотров
31.5%от подписчиков
28 марта 2026 г.
Score: 3.4K
errgroup в проде, однобуквенный баг и дыра в безопасности Короч, есть реальная история. В Ory Kratos (опенсорсный сервис авторизации на Go) при смене пароля параллелили две задачи через errgroup: хешировали bcrypt и проверяли пароль по базе утечек Код выглядел нормально. Тесты зелёные. Ревью прошёл А потом оказалось что утёкшие пароли спокойно проходят валидацию)) Дыра в безопасности! Баг был вот в чём: g, ctx := errgroup.WithContext(ctx) g.Go(func() error { / bcrypt / }) g.Go(func() error { / password check / }) g.Wait() // а тут ctx уже мёртвый, // потому что errgroup отменяет контекст // после Wait(). Даже если ошибок не было checkLeakedPasswords(ctx) // тихо фейлится g, ctx := errgroup.WithContext(ctx) перезатирает родительский ctx. После Wait() errgroup убивает свой контекст. Всё. Любой код дальше с этим ctx получает context canceled и молча дохнет Фикс, один символ: g, _ := errgroup.WithContext(ctx) Не перезатираешь родительский контекст, и всё работает Прикол в том, что проверка длины пароля len(password) < 4 рядом работала збс, потому что ей контекст не нужен. Это и путало, часть проверок проходит, часть нет И это не единственная подстава. Wait() возвращает только первую ошибку. Остальные молча проглатывает. Шлёшь нотификации в 5 каналов, один упал, ты получил одну ошибку и думаешь что всё ок. А там ещё два канала тоже легли, просто ты об этом не узнал Я в проде errgroup оборачиваю. Обёртка на ~50 строк, ничего магического: 🔍 сбор всех ошибок через errors.Join 🔍 лимит горутин (чтобы не стрельнуть 10к штук разом) 🔍 retry с бэкоффом для транзиентных ошибок Если интересно, могу код скинуть в следующем посте А у вас errgroup в проде с обёрткой или голый юзаете?
3.1K
просмотров
1712
символов
Нет
эмодзи
Нет
медиа

Другие посты @olezhek28go

Все посты канала →
errgroup в проде, однобуквенный баг и дыра в безопасности Ко — @olezhek28go | PostSniper