fix(invites): код приглашения не подменяется слабым при отказе crypto/rand
Вместо предсказуемого запасного кода ручка возвращает 500: приглашение — это доступ к серверу, маскировать отказ источника энтропии нельзя.
This commit is contained in:
@@ -93,8 +93,12 @@ func (s *Server) registerInviteRoutes(api huma.API) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
code, err := newInviteCode()
|
||||
if err != nil {
|
||||
return nil, humaErrorStatus(http.StatusInternalServerError, "internal.error", "cannot generate invite code")
|
||||
}
|
||||
params := store.CreateInviteParams{
|
||||
Code: newInviteCode(),
|
||||
Code: code,
|
||||
GuildID: guildID,
|
||||
CreatorID: user.ID,
|
||||
MaxUses: input.Body.MaxUses,
|
||||
@@ -359,20 +363,18 @@ func (s *Server) inviteOutput(ctx context.Context, user *store.User, invite *sto
|
||||
}
|
||||
|
||||
// newInviteCode генерирует код приглашения криптографическим источником.
|
||||
func newInviteCode() string {
|
||||
// Ошибка источника энтропии не маскируется слабым кодом: приглашение —
|
||||
// это доступ к серверу, поэтому лучше вернуть ошибку (AGENT.md 9.2).
|
||||
func newInviteCode() (string, error) {
|
||||
const length = 10
|
||||
buf := make([]byte, length)
|
||||
if _, err := rand.Read(buf); err != nil {
|
||||
// Откат на время: код остаётся уникальным за счёт монотонности.
|
||||
seed := uint64(time.Now().UnixNano()) //nolint:gosec // не криптография: запасной путь при отказе rand
|
||||
for i := range buf {
|
||||
buf[i] = byte(seed >> (uint(i) * 5))
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
var builder strings.Builder
|
||||
builder.Grow(length)
|
||||
for _, value := range buf {
|
||||
builder.WriteByte(inviteCodeAlphabet[int(value)%len(inviteCodeAlphabet)])
|
||||
}
|
||||
return builder.String()
|
||||
return builder.String(), nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user