Skip to content

Commit

Permalink
Use constant-time comparison for anti-csrf tokens
Browse files Browse the repository at this point in the history
This is probably completely overkill, but since anti-csrf tokens are secrets,
they should be compared against untrusted inputs in constant time.
  • Loading branch information
jvoisin committed Mar 3, 2024
1 parent abdd587 commit da048ae
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 1 deletion.
8 changes: 8 additions & 0 deletions internal/crypto/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"crypto/hmac"
"crypto/rand"
"crypto/sha256"
"crypto/subtle"
"encoding/base64"
"encoding/hex"
"fmt"
Expand Down Expand Up @@ -60,3 +61,10 @@ func GenerateUUID() string {
b := GenerateRandomBytes(16)
return fmt.Sprintf("%X-%X-%X-%X-%X", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
}

func ConstantTimeCmp(a, b string) bool {
if subtle.ConstantTimeCompare([]byte(a), []byte(b)) == 1 {

Check failure on line 66 in internal/crypto/crypto.go

View workflow job for this annotation

GitHub Actions / Golang Linter

S1008: should use 'return subtle.ConstantTimeCompare([]byte(a), []byte(b)) == 1' instead of 'if subtle.ConstantTimeCompare([]byte(a), []byte(b)) == 1 { return true }; return false' (gosimple)
return true
}
return false
}
3 changes: 2 additions & 1 deletion internal/ui/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"net/http"

"miniflux.app/v2/internal/config"
"miniflux.app/v2/internal/crypto"
"miniflux.app/v2/internal/http/cookie"
"miniflux.app/v2/internal/http/request"
"miniflux.app/v2/internal/http/response/html"
Expand Down Expand Up @@ -92,7 +93,7 @@ func (m *middleware) handleAppSession(next http.Handler) http.Handler {
formValue := r.FormValue("csrf")
headerValue := r.Header.Get("X-Csrf-Token")

if session.Data.CSRF != formValue && session.Data.CSRF != headerValue {
if !crypto.ConstantTimeCmp(session.Data.CSRF, formValue) && !crypto.ConstantTimeCmp(session.Data.CSRF, headerValue) {
slog.Warn("Invalid or missing CSRF token",
slog.Any("url", r.RequestURI),
slog.String("form_csrf", formValue),
Expand Down

0 comments on commit da048ae

Please sign in to comment.