Правила Security Кодирования
Назначение
Документ фиксирует обязательные security-правила для backend разработчиков Pin. Платформа PIN работает с реальными деньгами, PII, регуляторными данными — нарушение security правил имеет прямые финансовые и юридические последствия.
Многоуровневая Авторизация
Каждый запрос проходит три независимых барьера:
- Endpoint Policy —
[Authorize(Policy = "...")]на каждом контроллере/экшене. - MediatR AuthorizationBehavior — проверка
IActorContext.HasPermission()для command. - Handler Ownership Check — явная проверка
withdrawal.TenantId == actorContext.TenantId.
Ни один барьер не заменяет другой. Endpoint без [Authorize] — это blocker в code review.
Repository scope filters автоматически добавляют tenant_id / brand_id к каждому запросу как четвёртый слой.
Secrets И Credentials
- Secrets, credentials, API keys, webhook signing keys хранятся в Vault или k8s Secrets.
appsettings.jsonиappsettings.Production.jsonне содержат реальных secrets.- Secrets читаются через
IOptions<T>— не черезIConfiguration["key"]inline. IOptionsконфигурация валидируется при старте черезValidateDataAnnotations().ValidateOnStart().- Нет hardcoded strings с паролями, connection strings, token values в коде.
PII И Secrets В Логах
Следующее никогда не попадает в логи:
- пароли, PIN, секретные ключи, API tokens, webhook secrets;
- CVV, full PAN, IBAN, bank account numbers;
- access token, refresh token, session cookie;
- полные ФИО + дата рождения + адрес в одном log entry;
- содержимое KYC документов;
- encryption keys.
Поля, помеченные [Sensitive], автоматически маскируются через SensitiveDataMaskingPolicy.
Structured logging: в лог передаются Id (UserId, WithdrawalId), status, amount — но не имя, email, адрес пользователя.
Input Validation
- API validator (
AbstractValidator<TRequest>) проверяет формат, диапазон, MaxLength, Regex. - MediatR validator проверяет бизнес-правила (лимиты, статусы, наличие сущностей).
- Нет
AutoMapper.Map(request, existingEntity)— только явный mapping в command. - Строки из user input, используемые в имени файла, санируются через whitelist символов.
- Загружаемые файлы проверяются по extension whitelist и MaxSize.
- URL для redirect проверяются по origin whitelist.
SQL Injection
- Используется EF Core — параметризация автоматическая.
- Raw SQL через
ExecuteSqlRawAsyncс конкатенацией строк запрещён. FromSql($"...")с FormattableString — безопасно (compile-time параметризация).- Elasticsearch queries строятся через typed builder, не через JSON строки с интерполяцией.
Callback / Webhook Security
- Каждый payment/provider webhook callback валидируется по HMAC signature перед обработкой.
- Callback без подписи →
401 Unauthorized+ warning log. - Idempotency key webhook-а проверяется до бизнес-логики — дубль callback не меняет state.
JWT Tokens
ValidateIssuer,ValidateAudience,ValidateLifetime,ValidateIssuerSigningKey— всеtrue.ValidAlgorithms— whitelist разрешённых алгоритмов:["HS256", "RS256"].ClockSkew— не более 30 секунд.- Алгоритм
noneиHS1запрещены в TokenValidationParameters. - Access token TTL: user 15 мин, admin 8 часов.
Rate Limiting
- Auth endpoints (login, register, password reset) — strict rate limit per IP.
- Sensitive operations (withdrawal create, KYC submit, admin approve) — per-actor sliding window.
- SignalR — не более 10 push/s на пользователя.
429 Too Many Requestsвозвращается какProblemDetails, не пустой ответ.
Tenant Isolation
- Repository scope filters автоматически применяют
tenant_idиbrand_id. - Handler явно проверяет
entity.TenantId == actorContext.TenantIdдля критических операций. - Global admin bypass (
ScopeOptions.BypassAll) требует explicit permission + audit log. - User не может видеть данные другого user или другого tenant.
Чувствительные Операции
Для KYC approve/reject, balance adjustment, withdrawal approve, limit change, PII access обязательно:
[Authorize(Policy = AuthorizationPolicies.AdminWithMfa)];[AuditApiAction("event-type")];- Explicit permission check в handler;
- Ownership check в handler;
- Audit запись с before/after state через
AuditDbContext.
Code Review Security Блокеры
Pull request не принимается, если:
- endpoint без
[Authorize](кроме явно public); - handler без ownership check для tenant-scoped entity;
- secret в appsettings или hardcoded в коде;
- лог содержит password, token, email + name вместе, PAN, CVV;
- callback endpoint без HMAC validation;
- raw SQL с конкатенацией строк;
ValidateLifetime = falseв JWT config;- отсутствует rate limit на auth или sensitive endpoint.
Детальный Справочник
14 — Security Patterns — полное руководство с примерами кода.
Обратные ссылки
Автоссылки: где используется этот документ.
- adr (1): ADR-0046: Security Coding Standards
- 14-security-patterns.md (1): Security Patterns — Authorization, PII, OWASP
- backend-rules.md (1): Правила Backend Разработки
- backend-shared-standards-index.md (1): Backend Shared Standards Index