77 "encoding/json"
88 "errors"
99 "fmt"
10+ "math"
1011 "net/url"
1112 "regexp"
1213 "strings"
@@ -25,6 +26,12 @@ const defaultChallengeExpiryDuration float64 = 300
2526const defaultFactorExpiryDuration time.Duration = 300 * time .Second
2627const defaultFlowStateExpiryDuration time.Duration = 300 * time .Second
2728
29+ // maxOtpExp is the largest OTP validity window, in seconds, that survives
30+ // conversion to a time.Duration, which counts nanoseconds in an int64. That is
31+ // roughly 292 years. ApplyDefaults clamps OtpExp to it so the conversion cannot
32+ // overflow into a negative duration, which would expire tokens at creation.
33+ const maxOtpExp uint = math .MaxInt64 / uint (time .Second )
34+
2835// See: https://www.postgresql.org/docs/7.0/syntax525.htm
2936var postgresNamesRegexp = regexp .MustCompile (`^[a-zA-Z_][a-zA-Z0-9_]{0,62}$` )
3037
@@ -696,7 +703,8 @@ type MailerConfiguration struct {
696703}
697704
698705func (c * MailerConfiguration ) OtpExpAsDuration () time.Duration {
699- return time .Duration (c .OtpExp ) * time .Second // #nosec G115 -- OtpExp comes from trusted config, not user input
706+ // OtpExp is clamped to maxOtpExp in ApplyDefaults, so this cannot overflow.
707+ return time .Duration (c .OtpExp ) * time .Second // #nosec G115
700708}
701709
702710func (c * MailerConfiguration ) Validate () error {
@@ -789,7 +797,8 @@ type SmsProviderConfiguration struct {
789797}
790798
791799func (c * SmsProviderConfiguration ) OtpExpAsDuration () time.Duration {
792- return time .Duration (c .OtpExp ) * time .Second // #nosec G115 -- OtpExp comes from trusted config, not user input
800+ // OtpExp is clamped to maxOtpExp in ApplyDefaults, so this cannot overflow.
801+ return time .Duration (c .OtpExp ) * time .Second // #nosec G115
793802}
794803
795804func (c * SmsProviderConfiguration ) GetTestOTP (phone string , now time.Time ) (string , bool ) {
@@ -1211,6 +1220,10 @@ func (config *GlobalConfiguration) ApplyDefaults() error {
12111220 config .Mailer .OtpExp = 86400 // 1 day
12121221 }
12131222
1223+ if config .Mailer .OtpExp > maxOtpExp {
1224+ config .Mailer .OtpExp = maxOtpExp
1225+ }
1226+
12141227 if config .Mailer .OtpLength == 0 || config .Mailer .OtpLength < 6 || config .Mailer .OtpLength > 10 {
12151228 // 6-digit otp by default
12161229 config .Mailer .OtpLength = 6
@@ -1228,6 +1241,10 @@ func (config *GlobalConfiguration) ApplyDefaults() error {
12281241 config .Sms .OtpExp = 60
12291242 }
12301243
1244+ if config .Sms .OtpExp > maxOtpExp {
1245+ config .Sms .OtpExp = maxOtpExp
1246+ }
1247+
12311248 if config .Sms .OtpLength == 0 || config .Sms .OtpLength < 6 || config .Sms .OtpLength > 10 {
12321249 // 6-digit otp by default
12331250 config .Sms .OtpLength = 6
0 commit comments