security
Security — чеклист безопасности Go-сервисов: валидация входа, секреты, auth, CVE-зависимости. Используй при правке auth-middleware, обработке user input, внешних вызовах, или как чеклист в /go-review.
- License 许可
- MIT
- 最近更新
- 2026-11-05
- Stars
- ★ 7
- Forks
- 1
01 前言 Front Matter
- name
- security
- description
- Security — чеклист безопасности Go-сервисов: валидация входа, секреты, auth, CVE-зависимости. Используй при правке auth-middleware, обработке user input, внешних вызовах, или как чеклист в /go-review.
03 SKILL.md 正文
Security — безопасность vmkteam Go-сервисов
Справочник по безопасности для vmkteam-стека: JSON-RPC API, go-pg, zenrpc, auth middleware. Используется автоматически при code review (/go-review) и разработке (/solve).
Инструменты
| Инструмент | Что ищет | Команда |
|---|---|---|
gosec |
SQL injection, hardcoded credentials, weak crypto, command injection | gosec ./... |
govulncheck |
Уязвимости в зависимостях (только реально используемые функции) | govulncheck ./... |
gitleaks |
API keys, tokens, passwords в коде и git-истории | gitleaks detect --source . |
trivy |
Уязвимости в Docker-образах | CI only |
SQL Injection
Главная точка риска — _repo_ext.go (кастомные запросы).
Плохо — пользовательский ввод в raw SQL:
// УЯЗВИМО: searchText попадает в SQL напрямую
func (r OrderRepo) SearchOrders(ctx context.Context, searchText string) ([]Order, error) {
var orders []Order
_, err := r.db.Query(&orders,
"SELECT * FROM orders WHERE title LIKE '%"+searchText+"%'", nil)
return orders, err
}
Хорошо — параметризованный запрос через go-pg:
func (r OrderRepo) SearchOrders(ctx context.Context, searchText string) ([]Order, error) {
var orders []Order
err := r.db.Model(&orders).
Where("title ILIKE ?", "%"+searchText+"%").
Select()
return orders, err
}
Хорошо — если нужен raw SQL, использовать pg.SafeQuery:
q := r.db.Model(&orders)
q = q.Where("? ILIKE ?", pg.Ident("title"), "%"+searchText+"%")
Правило: go-pg ORM экранирует автоматически. Опасность только в Query() с конкатенацией строк.
Аутентификация и авторизация
Auth middleware (типичная ошибка — IDOR)
Middleware проверяет аутентификацию (есть ли валидный токен), но не авторизацию (может ли этот пользователь делать это действие).
Плохо — middleware пропустил, но метод не проверяет ownership:
func (s OrderService) GetByID(ctx context.Context, id int) (*Order, error) {
// Любой авторизованный пользователь может получить любой заказ
return s.repo.OrderByID(ctx, id)
}
Хорошо — проверка ownership:
func (s OrderService) GetByID(ctx context.Context, id int) (*Order, error) {
user := UserFromContext(ctx)
order, err := s.repo.OrderByID(ctx, id)
if err != nil {
return nil, newInternalError(err)
}
if order == nil {
return nil, ErrNotFound
}
if order.UserID != user.ID {
return nil, ErrForbidden
}
return NewOrder(order), nil
}
Auth whitelist
В server.go middleware пропускает определённые методы без авторизации. Whitelist должен быть минимальным:
// Только auth.Login не требует токен
if ns == NSAuth && method == RPC.AuthService.Login {
return h(ctx, method, params)
}
Error Information Leakage
zenrpc.NewError(code, err) кладёт err.Error() в message ответа. Для кода 500 (и отрицательных) это безопасно только благодаря middleware: zm.WithErrorSLog (legacy — zm.WithErrorLogger) логирует такую ошибку, отправляет её в Sentry и заменяет message на "Internal error". Для остальных кодов маскировки нет.
Хорошо — внутренняя ошибка: причина уходит в Sentry, клиент видит "Internal error":
func newInternalError(err error) *zenrpc.Error {
return zenrpc.NewError(http.StatusInternalServerError, err)
}
return nil, newInternalError(err)
Работает, только если zm.WithErrorSLog есть в rpc.Use(...) в server.go — без него клиент получит текст ошибки.
Хорошо — клиентская ошибка с фиксированным текстом:
var ErrNotFound = zenrpc.NewStringError(http.StatusNotFound, "not found")
Плохо — NewError с кодом 4xx: текст внутренней ошибки уходит клиенту как есть:
return nil, zenrpc.NewError(http.StatusBadRequest, err)
// Клиент увидит: {"error":{"code":400,"message":"pq: relation \"orders\" does not exist"}}
Плохо — zenrpc.NewStringError(500, "internal error") вместо newInternalError(err): клиенту безопасно, но в Sentry уходит строка без причины, и диагностировать нечем.
Sensitive Data in Logs
zenrpc-middleware (WithSLog, WithAPILogger) логирует параметры запросов. Если метод принимает пароль — он попадёт в логи.
Решение: не передавать секреты как RPC-параметры, или фильтровать в middleware.
JSON-RPC специфика
- Все методы через один POST endpoint (
/rpc/) — стандартные WAF-правила для REST не работают - Rate limiting на уровне reverse proxy (traefik/nginx) — по IP, не по методу
- CORS:
AllowOrigins: []string{"*"}допустим в dev, но в production ограничивать доменами
Чеклист для code review
| Категория | Проверить |
|---|---|
| SQL | Нет конкатенации строк в _repo_ext.go |
| Auth | Whitelist методов минимальный |
| Authz | Проверка ownership/прав внутри методов (не только middleware) |
| Validation | Все входы через go-playground/validator, max длины строк |
| Errors | 4xx — NewStringError с фиксированным текстом; 500 — newInternalError(err), и в цепочке middleware есть zm.WithErrorSLog |
| Logging | Пароли/токены не в параметрах логируемых методов |
| Secrets | cfg/local.toml в .gitignore, нет hardcoded credentials |
| CORS | Ограничен в production |
04 同仓库更多 Skills
zenrpc
Zenrpc — справочник по JSON-RPC 2.0 серверу для Go. Используй при создании и редактировании RPC-сервисов.
youtrack
YouTrack — задачи через REST API и pcurl. Используй для поиска issues, создания, обновления описаний, смены assignee/stage/приоритета, логирования времени и работы с комментариями.
topsrv
topsrv — метрики, алерты, CVE и HTTP-логи серверов проекта через публичный JSON-RPC API app.topsrv.io. Используй, когда нужна загрузка CPU, памяти или диска хоста, метрики PostgreSQL/nginx/angie агента topsrv (`topsrv_*`), какие алерты горят, уязвимые пакеты на серверах или кто (боты, сети, IP) нагружает сайт.
testing
Testing — используй всегда, когда пишешь или правишь Go-тесты (*_test.go), в том числе по сценариям Given/When/Then из spec: фреймворк как в соседних файлах, префикс TestDB, фабрики pkg/db/test, реальная БД без моков. Также при настройке TestMain/test-short и когда тесты падают в gate, но проходят локально.
solve
Solve — полный цикл решения задачи из YouTrack: preflight → анализ → план → реализация → ревью → коммит. Используй при любой YouTrack-задаче (`/solve PLF-819`); флаг `--fast` сокращает HITL для тривиальных багфиксов.
skills-check
Skills Check — smoke-тесты интеграций из project-index.md. Используй для проверки что pcurl-профили и URL всех data-source скиллов ещё живы.