Skip to main content

Security Matrix

Сводная матрица защит по всем доменам GOLOOT.


1. Summary

Goal: Централизованный обзор всех защитных механизмов для аудита и планирования.

User Value: Быстрая проверка "какие защиты применены к этому действию?" без копания в коде.


2. Rate Limit Configs

Конфигурации из backend/src/common/middleware/rate-limits.middleware.ts:

Централизованные константы

Все лимиты определены в backend/src/common/constants/validation.tsRATE_LIMITS. В dev-режиме автоматически применяется множитель ×10.

ConfigЛимитИспользование
feedback1/minОтправка фидбека — защита от спама
mutations5/minИзменение данных (create/update/delete)
achievementClaim15/minПолучение наград
auth5/minАвторизация — защита от брутфорса
verify30/minВерификация (2FA, email)
unauth20/minНеавторизованные запросы
general100/minОбщие операции
content200/minЧтение контента (высокий лимит)
personalContent10/minЛичные данные пользователя
critical5/minКритичные мутации (UTM create/delete)
tracking60/minTracking события (UTM)
analytics30/minАналитика запросы
shortlinks100/minПубличные редиректы
onboarding20/minПубличный onboarding (subscription check)
feed30/minПубличный feed событий
botCheck30/minПроверка статуса бота
adminApiLimiter50/minАдминские API операции
presetDownloads5/minСкачивание preset файлов

3. Authentication Types

ТипMiddlewareОписание
telegramtelegramAuthTelegram WebApp initData verification
telegramLighttelegramAuthLightTelegram auth без ban-check (для апелляций)
telegram + seasontelegramAuth + requireActiveSeasonTelegram auth + проверка активного сезона
telegram + season + steamtelegramAuth + requireActiveSeason + steam checkДля raffle: требуется верифицированный Steam
adminadminAuthMiddlewareJWT + role: admin check
pluginpluginAuthMiddlewareBearer API Key (Rust сервер)
none-Публичный эндпоинт

4. Content Security Policy (CSP)

TMA работает в iframe Telegram Web, поэтому CSP настроена для совместимости:

Enforcement Mode

CSP включена в режиме enforcement — нарушения блокируются браузером.

ДирективаЗначениеПричина
defaultSrc'self'Базовая политика
scriptSrc'self', 'unsafe-inline', telegram.org, *.telegram.orgTelegram SDK + inline scripts
styleSrc'self', 'unsafe-inline'CSS-in-JS, inline styles
imgSrc'self', data:, https:, blob:Изображения из разных источников
connectSrc'self', https://api.goloot.online, wss:, https://telegram.orgAPI + WebSocket + Telegram
fontSrc'self', data:Шрифты
frameAncestors'self', https://web.telegram.org, https://t.meРазрешённые iframe parents (TMA)
formAction'self'Ограничение form submissions
objectSrc'none'Блокировка object/embed
baseUri'self'Защита от base tag injection

Конфигурация: backend/src/server.tshelmet({ contentSecurityPolicy: {...} })


5. Protection Matrix

DomainActionRate LimitAuthValidationAtomicNotes
casesopengeneraltelegramOpenCaseSchemaBalance + reward
casescreatemutationsadminCreateCaseSchema-Admin only
craftcheckgeneraltelegramCheckCraftAbilitySchema-Read only
craftcraft itemmutationstelegram + seasonCraftItemSchemaMaterials + scrap
craftget availablegeneraltelegramGetCraftableItemsSchema-Read only
daily-spinsspingeneraltelegramSpinSchemaBalance + reward
inventorylistgeneraltelegramGetInventorySchema-Read only
inventorysalvagegeneraltelegram + seasonSalvageItemSchemaXP grant

6. Security Middleware Stack

Порядок применения middleware в Fastify:

Request

1. Rate Limit (по IP/telegramId)

2. Auth (telegramAuth / adminAuth)

3. CSRF Check (для admin mutations)

4. Ban Check (isBanned)

5. Season Check (requireActiveSeason)

6. Schema Validation

7. Handler

7. Security Principles

Принципы безопасности, которым должен следовать весь код.

SQL Injection Prevention

Prisma ORM защищает от SQL injection по умолчанию, но raw queries требуют внимания.

Tagged Template Literals

При использовании $queryRaw / $executeRawТОЛЬКО tagged template literals. Prisma автоматически экранирует параметры в tagged templates.

// ✅ ПРАВИЛЬНО — параметры экранируются автоматически
const result = await prisma.$queryRaw`
SELECT * FROM users WHERE id = ${userId}
`;

// ✅ ПРАВИЛЬНО — несколько параметров
await prisma.$executeRaw`
UPDATE user_season_stats SET rank = ${rank}
WHERE "seasonId" = ${seasonId} AND id = ${odbc}
`;

// ❌ ОПАСНО — string interpolation = SQL injection
const result = await prisma.$queryRaw(`
SELECT * FROM users WHERE id = '${userId}'
`);

// ❌ ОПАСНО — конкатенация строк
const query = "SELECT * FROM users WHERE name = '" + userName + "'";

Файлы с raw queries: Все используют безопасный паттерн (проверено).

ФайлИспользование
seasons/repositories/season.repository.tsBatch rank update (window functions)
referrals/services/referral-analytics.service.tsAggregation queries
utm/services/utm-analytics.service.tsDate-based stats
banners/services/banner-analytics.service.tsBanner analytics

IDOR Prevention

Insecure Direct Object Reference (IDOR) — когда пользователь может получить доступ к чужим данным, подставив чужой ID.

Золотое правило

userId берётся ТОЛЬКО из request.user (установленного auth middleware), НИКОГДА из params/body/query.

// ✅ ПРАВИЛЬНО — userId из auth middleware
async getProfile(request: FastifyRequest) {
const { userId } = request.user; // Из telegramAuth
return this.service.getProfile(userId);
}

// ✅ ПРАВИЛЬНО — проверка ownership
async getTicket(request: FastifyRequest) {
const { ticketId } = request.params;
const { userId } = request.user;

const ticket = await this.service.getTicket(ticketId);
if (ticket.userId !== userId) {
throw new ForbiddenError('Not your ticket');
}
return ticket;
}

// ❌ ОПАСНО — userId из params (атакующий подставит чужой ID)
async getProfile(request: FastifyRequest) {
const { userId } = request.params; // IDOR vulnerability!
return this.service.getProfile(userId);
}

// ❌ ОПАСНО — userId из body
async updateBalance(request: FastifyRequest) {
const { userId, amount } = request.body; // IDOR vulnerability!
return this.service.addBalance(userId, amount);
}

Исключения:

  • Admin endpoints — админ может работать с любым userId (защищено adminAuthMiddleware)
  • Public endpoints — данные и так публичные (feed, referral codes)

Input Validation

Валидация входных данных на всех уровнях.

УровеньИнструментЧто валидирует
Request bodyZod schemasТипы, форматы, ограничения
Route paramsFastify JSON SchemaUUID format, required params
ResponseFastify JSON SchemaСтруктура ответа (убирает лишние поля)
Business logicService layerБизнес-правила (достаточно баланса, не забанен)
// ✅ ПРАВИЛЬНО — Zod schema для body
export const CreateQuestSchema = z.object({
title: z.string().min(3).max(100),
targetValue: z.number().int().positive(),
rewardScrap: z.number().int().min(0).max(10000),
type: z.nativeEnum(QuestType),
});

// ✅ ПРАВИЛЬНО — Fastify schema для route
fastify.post('/quests', {
schema: {
body: CreateQuestBodySchema,
response: {
200: CreateQuestResponseSchema,
},
},
preHandler: [telegramAuth],
handler: controller.create,
});

// ❌ ОПАСНО — без валидации
fastify.post('/quests', async (request) => {
const data = request.body; // Не валидировано!
return service.create(data);
});
Response Schema

Fastify автоматически удаляет поля, не описанные в response schema. Если добавляешь новое поле в service — добавь его и в schema!

XSS Prevention

Cross-Site Scripting предотвращается на нескольких уровнях:

ЗащитаГде применяетсяКак работает
CSPBackend (helmet)Блокирует inline scripts из недоверенных источников
React escapingFrontendАвтоматически экранирует output в JSX
No dangerouslySetInnerHTMLFrontendЗапрещено в code review
Input sanitizationBackendZod валидация + типизация
// ✅ ПРАВИЛЬНО — React экранирует автоматически
function UserName({ name }: { name: string }) {
return <span>{name}</span>; // Безопасно даже если name = "<script>..."
}

// ❌ ОПАСНО — прямой HTML (запрещено в проекте)
function UserBio({ html }: { html: string }) {
return <div dangerouslySetInnerHTML={{ __html: html }} />; // XSS!
}

Проверка: dangerouslySetInnerHTML не найден в frontend/src/.

Plugin Authentication (Rust)

Rust серверы аутентифицируются через API Key, не через rate limiting.

МеханизмОписание
Bearer TokenAuthorization: Bearer {apiKey}
Server lookupКлюч → RustServer в БД
isActive checkДеактивированные серверы отклоняются
Request decorationrequest.rustServer = { id, name }
// Plugin auth middleware
const apiKey = authHeader.slice(7); // "Bearer " prefix
const server = await prisma.rustServer.findUnique({
where: { apiKey },
});

if (!server) return 401; // Invalid key
if (!server.isActive) return 403; // Deactivated

Почему нет Rate Limit:

  • Trusted source (только свои серверы)
  • API Key = identity (можно отключить конкретный сервер)
  • Low traffic (~10-20 req/min на сервер)

Конфигурация: backend/src/domains/rust-integration/middleware/plugin-auth.middleware.ts

Telegram Bot Webhook Security

Telegram webhook endpoint принимает updates от Telegram Bot API. Без защиты атакующий может отправить поддельный HTTP-запрос и выполнить действия от имени бота.

Вектор атаки

Через модифицированный Telegram-клиент видны callback_data inline-кнопок. Через Telegram Bot API (Postman) можно отправить поддельный webhook-запрос на /api/telegram/webhook, подставив нужный callback_data и chat.id.

Защита (defense in depth):

УровеньМеханизмЧто защищает
1. Webhook Secret TokenX-Telegram-Bot-Api-Secret-Token headerПодделка webhook-запросов
2. Admin User WhitelistTELEGRAM_ADMIN_IDS + ctx.from.idПодмена admin-пользователя
3. Budget Amount ValidationWhitelist допустимых суммПроизвольные суммы через callback_data
4. Rate Limiting100 req/sec на webhook endpointDoS через массовые запросы

Webhook Secret Token:

  • При setWebhook() передаётся secret_token
  • Telegram включает его в каждый запрос как заголовок X-Telegram-Bot-Api-Secret-Token
  • Backend проверяет заголовок перед обработкой update
  • Без валидного токена — 401 Unauthorized

Admin Callback Protection:

  • Admin inline-кнопки (budget_add, season_pause, season_ok) доступны в admin-группе Telegram
  • Двойная проверка: chat.id === TELEGRAM_GROUP_ID AND from.id in TELEGRAM_ADMIN_IDS
  • Все admin-действия логируются с adminUserId

Переменные окружения:

ПеременнаяОбязательнаОписание
TELEGRAM_WEBHOOK_SECRETНет (dev), Да (prod)64-символьный hex-токен (openssl rand -hex 32)
TELEGRAM_ADMIN_IDSНетComma-separated Telegram user IDs для admin-кнопок
TELEGRAM_GROUP_IDНетID admin-группы для уведомлений

Конфигурация:

  • Webhook route: backend/src/domains/telegram/routes/telegram-bot.routes.ts
  • Admin callbacks: backend/src/domains/telegram/handlers/admin-callback.handler.ts
  • Secret config: backend/src/common/utils/secrets.service.ts

  • TMA Auth Architecture — архитектура авторизации TMA (HMAC vs JWT)
  • Settings — настройки пользователя
  • Steam Verification — верификация Steam-аккаунтов
  • Seasons — система сезонов и рейтингов
  • Quests — система квестов и заданий
  • Buffs — система временных бонусов
  • Streaks & Raffle — система лояльности и розыгрышей
  • Quizzes — система викторин для TG канала
  • Live Feed — публичная лента событий (SSE)
  • Referrals — реферальная система и пассивный доход
  • Feedback — система обратной связи и поддержки
  • Promo Codes — система промокодов
  • UTM Tracking — система маркетинговых ссылок
  • Docs Access — система доступа к документации
  • Docs Deployment — CI/CD для документации
  • Rust Integration — интеграция с Rust серверами
  • Steam Trade Bot — автоматизированный вывод скинов в Steam
  • Telegram Bot — Telegram бот, push-уведомления, квизы