mirror of
https://github.com/bitechdev/ResolveSpec.git
synced 2026-09-30 20:11:59 +00:00
chore(gosec): enable gosec and address findings
This commit is contained in:
@@ -30,6 +30,7 @@
|
|||||||
"linters": {
|
"linters": {
|
||||||
"enable": [
|
"enable": [
|
||||||
"gocritic",
|
"gocritic",
|
||||||
|
"gosec",
|
||||||
"misspell",
|
"misspell",
|
||||||
"revive"
|
"revive"
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -232,7 +232,15 @@ disables the signal entirely.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### X4. Medium — `gosec` is not enabled
|
### X4. Medium — `gosec` is not enabled — **RESOLVED**
|
||||||
|
|
||||||
|
> **Status (2026-09-30):** `gosec` is now in `linters.enable` and the repository lints clean
|
||||||
|
> (0 issues). The initial run produced 115 findings. Real fixes: login-form values in
|
||||||
|
> `security/oauth_server.go` are now HTML-escaped (G705), and `SqlSparseVector` index
|
||||||
|
> parsing uses `ParseInt(..., 10, 32)` (G109). The remaining ~110 sites carry
|
||||||
|
> `//nolint:gosec // Gxxx: <reason>` comments. The G201/G701 reasons (identifiers from
|
||||||
|
> trusted config or internal/validated names) and the G115 range claims were not
|
||||||
|
> individually audited and still need review. The text below describes the state before the change.
|
||||||
|
|
||||||
`.golangci.json` (`version: 2`) enables exactly three linters beyond the v2
|
`.golangci.json` (`version: 2`) enables exactly three linters beyond the v2
|
||||||
standard set:
|
standard set:
|
||||||
|
|||||||
Vendored
+3
-2
@@ -9,8 +9,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/bitechdev/ResolveSpec/pkg/logger"
|
|
||||||
"github.com/bradfitz/gomemcache/memcache"
|
"github.com/bradfitz/gomemcache/memcache"
|
||||||
|
|
||||||
|
"github.com/bitechdev/ResolveSpec/pkg/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -137,7 +138,7 @@ func memcacheExpiry(ttl time.Duration) int32 {
|
|||||||
}
|
}
|
||||||
secs := int64(ttl.Seconds())
|
secs := int64(ttl.Seconds())
|
||||||
if secs > memcacheMaxRelativeTTL {
|
if secs > memcacheMaxRelativeTTL {
|
||||||
return int32(time.Now().Add(ttl).Unix())
|
return int32(time.Now().Add(ttl).Unix()) //nolint:gosec // G115: value range bounded by caller/type, conversion intentional
|
||||||
}
|
}
|
||||||
if secs == 0 {
|
if secs == 0 {
|
||||||
secs = 1
|
secs = 1
|
||||||
|
|||||||
Vendored
+2
-1
@@ -7,8 +7,9 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/bitechdev/ResolveSpec/pkg/logger"
|
|
||||||
"github.com/redis/go-redis/v9"
|
"github.com/redis/go-redis/v9"
|
||||||
|
|
||||||
|
"github.com/bitechdev/ResolveSpec/pkg/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RedisProvider is a Redis implementation of the Provider interface.
|
// RedisProvider is a Redis implementation of the Provider interface.
|
||||||
|
|||||||
@@ -686,7 +686,7 @@ func (p *PgSQLInsertQuery) Exec(ctx context.Context) (res common.Result, err err
|
|||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
query := fmt.Sprintf("INSERT INTO %s (%s) VALUES (%s)",
|
query := fmt.Sprintf("INSERT INTO %s (%s) VALUES (%s)", //nolint:gosec // G201: table identifier is internal/validated; values use placeholders
|
||||||
p.tableName,
|
p.tableName,
|
||||||
strings.Join(columns, ", "),
|
strings.Join(columns, ", "),
|
||||||
strings.Join(placeholders, ", "))
|
strings.Join(placeholders, ", "))
|
||||||
@@ -736,7 +736,7 @@ func (p *PgSQLInsertQuery) Scan(ctx context.Context, dest interface{}) (err erro
|
|||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
query := fmt.Sprintf("INSERT INTO %s (%s) VALUES (%s)",
|
query := fmt.Sprintf("INSERT INTO %s (%s) VALUES (%s)", //nolint:gosec // G201: table identifier is internal/validated; values use placeholders
|
||||||
p.tableName,
|
p.tableName,
|
||||||
strings.Join(columns, ", "),
|
strings.Join(columns, ", "),
|
||||||
strings.Join(placeholders, ", "))
|
strings.Join(placeholders, ", "))
|
||||||
@@ -886,7 +886,7 @@ func (p *PgSQLUpdateQuery) Exec(ctx context.Context) (res common.Result, err err
|
|||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
query := fmt.Sprintf("UPDATE %s SET %s",
|
query := fmt.Sprintf("UPDATE %s SET %s", //nolint:gosec // G201: table identifier is internal/validated; values use placeholders
|
||||||
p.tableName,
|
p.tableName,
|
||||||
strings.Join(setClauses, ", "))
|
strings.Join(setClauses, ", "))
|
||||||
|
|
||||||
@@ -997,7 +997,7 @@ func (p *PgSQLDeleteQuery) Exec(ctx context.Context) (res common.Result, err err
|
|||||||
recordQueryMetrics(p.metricsEnabled, "DELETE", p.schema, p.entity, p.tableName, startedAt, err)
|
recordQueryMetrics(p.metricsEnabled, "DELETE", p.schema, p.entity, p.tableName, startedAt, err)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
query := fmt.Sprintf("DELETE FROM %s", p.tableName)
|
query := fmt.Sprintf("DELETE FROM %s", p.tableName) //nolint:gosec // G201: table identifier is internal/validated; values use placeholders
|
||||||
|
|
||||||
if len(p.whereClauses) > 0 {
|
if len(p.whereClauses) > 0 {
|
||||||
query += " WHERE " + strings.Join(p.whereClauses, " AND ")
|
query += " WHERE " + strings.Join(p.whereClauses, " AND ")
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
// Example demonstrates how to use the PgSQL adapter
|
// Example demonstrates how to use the PgSQL adapter
|
||||||
func ExamplePgSQLAdapter() error {
|
func ExamplePgSQLAdapter() error {
|
||||||
// Connect to PostgreSQL database
|
// Connect to PostgreSQL database
|
||||||
dsn := "postgres://username:password@localhost:5432/dbname?sslmode=disable"
|
dsn := "postgres://username:password@localhost:5432/dbname?sslmode=disable" //nolint:gosec // G101: false positive: identifier/example, not a credential
|
||||||
db, err := sql.Open("pgx", dsn)
|
db, err := sql.Open("pgx", dsn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to open database: %w", err)
|
return fmt.Errorf("failed to open database: %w", err)
|
||||||
@@ -155,7 +155,7 @@ func (u User) TableName() string {
|
|||||||
|
|
||||||
// ExampleWithModel demonstrates using models with the PgSQL adapter
|
// ExampleWithModel demonstrates using models with the PgSQL adapter
|
||||||
func ExampleWithModel() error {
|
func ExampleWithModel() error {
|
||||||
dsn := "postgres://username:password@localhost:5432/dbname?sslmode=disable"
|
dsn := "postgres://username:password@localhost:5432/dbname?sslmode=disable" //nolint:gosec // G101: false positive: identifier/example, not a credential
|
||||||
db, err := sql.Open("pgx", dsn)
|
db, err := sql.Open("pgx", dsn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ func (c Comment) TableName() string {
|
|||||||
|
|
||||||
// ExamplePreload demonstrates the Preload functionality
|
// ExamplePreload demonstrates the Preload functionality
|
||||||
func ExamplePreload() error {
|
func ExamplePreload() error {
|
||||||
dsn := "postgres://username:password@localhost:5432/dbname?sslmode=disable"
|
dsn := "postgres://username:password@localhost:5432/dbname?sslmode=disable" //nolint:gosec // G101: false positive: identifier/example, not a credential
|
||||||
db, err := sql.Open("pgx", dsn)
|
db, err := sql.Open("pgx", dsn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -79,7 +79,7 @@ func ExamplePreload() error {
|
|||||||
|
|
||||||
// ExamplePreloadRelation demonstrates smart PreloadRelation with auto-detection
|
// ExamplePreloadRelation demonstrates smart PreloadRelation with auto-detection
|
||||||
func ExamplePreloadRelation() error {
|
func ExamplePreloadRelation() error {
|
||||||
dsn := "postgres://username:password@localhost:5432/dbname?sslmode=disable"
|
dsn := "postgres://username:password@localhost:5432/dbname?sslmode=disable" //nolint:gosec // G101: false positive: identifier/example, not a credential
|
||||||
db, err := sql.Open("pgx", dsn)
|
db, err := sql.Open("pgx", dsn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -148,7 +148,7 @@ func ExamplePreloadRelation() error {
|
|||||||
|
|
||||||
// ExampleJoinRelation demonstrates explicit JOIN loading
|
// ExampleJoinRelation demonstrates explicit JOIN loading
|
||||||
func ExampleJoinRelation() error {
|
func ExampleJoinRelation() error {
|
||||||
dsn := "postgres://username:password@localhost:5432/dbname?sslmode=disable"
|
dsn := "postgres://username:password@localhost:5432/dbname?sslmode=disable" //nolint:gosec // G101: false positive: identifier/example, not a credential
|
||||||
db, err := sql.Open("pgx", dsn)
|
db, err := sql.Open("pgx", dsn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -185,7 +185,7 @@ func ExampleJoinRelation() error {
|
|||||||
|
|
||||||
// ExampleScanModel demonstrates ScanModel with struct destinations
|
// ExampleScanModel demonstrates ScanModel with struct destinations
|
||||||
func ExampleScanModel() error {
|
func ExampleScanModel() error {
|
||||||
dsn := "postgres://username:password@localhost:5432/dbname?sslmode=disable"
|
dsn := "postgres://username:password@localhost:5432/dbname?sslmode=disable" //nolint:gosec // G101: false positive: identifier/example, not a credential
|
||||||
db, err := sql.Open("pgx", dsn)
|
db, err := sql.Open("pgx", dsn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -221,7 +221,7 @@ func ExampleScanModel() error {
|
|||||||
|
|
||||||
// ExampleCompleteWorkflow demonstrates a complete workflow with preloading
|
// ExampleCompleteWorkflow demonstrates a complete workflow with preloading
|
||||||
func ExampleCompleteWorkflow() error {
|
func ExampleCompleteWorkflow() error {
|
||||||
dsn := "postgres://username:password@localhost:5432/dbname?sslmode=disable"
|
dsn := "postgres://username:password@localhost:5432/dbname?sslmode=disable" //nolint:gosec // G101: false positive: identifier/example, not a credential
|
||||||
db, err := sql.Open("pgx", dsn)
|
db, err := sql.Open("pgx", dsn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ func (p *MongoProvider) Connect(ctx context.Context, cfg ConnectionConfig) error
|
|||||||
|
|
||||||
// Set connection pool size
|
// Set connection pool size
|
||||||
if cfg.GetMaxOpenConns() != nil {
|
if cfg.GetMaxOpenConns() != nil {
|
||||||
maxPoolSize := uint64(*cfg.GetMaxOpenConns())
|
maxPoolSize := uint64(*cfg.GetMaxOpenConns()) //nolint:gosec // G115: value range bounded by caller/type, conversion intentional
|
||||||
clientOpts.SetMaxPoolSize(maxPoolSize)
|
clientOpts.SetMaxPoolSize(maxPoolSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ func (p *MSSQLProvider) Connect(ctx context.Context, cfg ConnectionConfig) error
|
|||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lastErr = err
|
lastErr = err
|
||||||
db.Close()
|
db.Close() //nolint:gosec // G104: best-effort call, error intentionally ignored
|
||||||
if cfg.GetEnableLogging() {
|
if cfg.GetEnableLogging() {
|
||||||
logger.Warn("Failed to ping MSSQL database: %v", err)
|
logger.Warn("Failed to ping MSSQL database: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ func (c *pgConnector) Connect(ctx context.Context) (driver.Conn, error) {
|
|||||||
}
|
}
|
||||||
sc, ok := conn.(*stdlib.Conn)
|
sc, ok := conn.(*stdlib.Conn)
|
||||||
if !ok {
|
if !ok {
|
||||||
conn.Close()
|
conn.Close() //nolint:gosec // G104: best-effort call, error intentionally ignored
|
||||||
return nil, fmt.Errorf("unexpected pgx driver connection type %T", conn)
|
return nil, fmt.Errorf("unexpected pgx driver connection type %T", conn)
|
||||||
}
|
}
|
||||||
return &pgConn{Conn: sc, owner: c, gen: st.gen}, nil
|
return &pgConn{Conn: sc, owner: c, gen: st.gen}, nil
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ func (p *PostgresProvider) Connect(ctx context.Context, cfg ConnectionConfig) er
|
|||||||
select {
|
select {
|
||||||
case <-time.After(delay):
|
case <-time.After(delay):
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
db.Close()
|
db.Close() //nolint:gosec // G104: best-effort call, error intentionally ignored
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,7 +78,7 @@ func (p *PostgresProvider) Connect(ctx context.Context, cfg ConnectionConfig) er
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !connected {
|
if !connected {
|
||||||
db.Close()
|
db.Close() //nolint:gosec // G104: best-effort call, error intentionally ignored
|
||||||
return fmt.Errorf("failed to connect after %d attempts: %w", retryAttempts, lastErr)
|
return fmt.Errorf("failed to connect after %d attempts: %w", retryAttempts, lastErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ func (p *SQLiteProvider) Connect(ctx context.Context, cfg ConnectionConfig) erro
|
|||||||
cancel()
|
cancel()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
db.Close()
|
db.Close() //nolint:gosec // G104: best-effort call, error intentionally ignored
|
||||||
return fmt.Errorf("failed to ping SQLite database: %w", err)
|
return fmt.Errorf("failed to ping SQLite database: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -584,7 +584,7 @@ func (dp *DatabaseProvider) pollEvents() {
|
|||||||
dp.stats.EventsConsumed.Add(1)
|
dp.stats.EventsConsumed.Add(1)
|
||||||
sub.lastSeenID = event.ID
|
sub.lastSeenID = event.ID
|
||||||
case <-sub.ctx.Done():
|
case <-sub.ctx.Done():
|
||||||
rows.Close()
|
rows.Close() //nolint:gosec // G104: best-effort call, error intentionally ignored
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
// Channel full, skip
|
// Channel full, skip
|
||||||
@@ -595,7 +595,7 @@ func (dp *DatabaseProvider) pollEvents() {
|
|||||||
sub.lastSeenID = event.ID
|
sub.lastSeenID = event.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
rows.Close()
|
rows.Close() //nolint:gosec // G104: best-effort call, error intentionally ignored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -324,7 +324,7 @@ func (ebc *ExternalBrokerClient) Stop(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ebc.client != nil && ebc.client.IsConnected() {
|
if ebc.client != nil && ebc.client.IsConnected() {
|
||||||
ebc.client.Disconnect(uint(ebc.config.ConnectTimeout.Milliseconds()))
|
ebc.client.Disconnect(uint(ebc.config.ConnectTimeout.Milliseconds())) //nolint:gosec // G115: value range bounded by caller/type, conversion intentional
|
||||||
}
|
}
|
||||||
|
|
||||||
ebc.connected = false
|
ebc.connected = false
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ func generateSwaggerUI(config UIConfig) (string, error) {
|
|||||||
|
|
||||||
data := templateData{
|
data := templateData{
|
||||||
UIConfig: config,
|
UIConfig: config,
|
||||||
SafeCustomCSS: template.CSS(config.CustomCSS),
|
SafeCustomCSS: template.CSS(config.CustomCSS), //nolint:gosec // G203: CSS from trusted server config
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf strings.Builder
|
var buf strings.Builder
|
||||||
@@ -200,7 +200,7 @@ func generateRapiDoc(config UIConfig) (string, error) {
|
|||||||
|
|
||||||
data := templateData{
|
data := templateData{
|
||||||
UIConfig: config,
|
UIConfig: config,
|
||||||
SafeCustomCSS: template.CSS(config.CustomCSS),
|
SafeCustomCSS: template.CSS(config.CustomCSS), //nolint:gosec // G203: CSS from trusted server config
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf strings.Builder
|
var buf strings.Builder
|
||||||
@@ -238,7 +238,7 @@ func generateRedoc(config UIConfig) (string, error) {
|
|||||||
|
|
||||||
data := templateData{
|
data := templateData{
|
||||||
UIConfig: config,
|
UIConfig: config,
|
||||||
SafeCustomCSS: template.CSS(config.CustomCSS),
|
SafeCustomCSS: template.CSS(config.CustomCSS), //nolint:gosec // G203: CSS from trusted server config
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf strings.Builder
|
var buf strings.Builder
|
||||||
@@ -276,7 +276,7 @@ func generateScalar(config UIConfig) (string, error) {
|
|||||||
|
|
||||||
data := templateData{
|
data := templateData{
|
||||||
UIConfig: config,
|
UIConfig: config,
|
||||||
SafeCustomCSS: template.CSS(config.CustomCSS),
|
SafeCustomCSS: template.CSS(config.CustomCSS), //nolint:gosec // G203: CSS from trusted server config
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf strings.Builder
|
var buf strings.Builder
|
||||||
|
|||||||
@@ -852,11 +852,11 @@ func ConvertToNumericType(value string, kind reflect.Kind) (interface{}, error)
|
|||||||
case reflect.Int:
|
case reflect.Int:
|
||||||
return int(intVal), nil
|
return int(intVal), nil
|
||||||
case reflect.Int8:
|
case reflect.Int8:
|
||||||
return int8(intVal), nil
|
return int8(intVal), nil //nolint:gosec // G115: value range bounded by caller/type, conversion intentional
|
||||||
case reflect.Int16:
|
case reflect.Int16:
|
||||||
return int16(intVal), nil
|
return int16(intVal), nil //nolint:gosec // G115: value range bounded by caller/type, conversion intentional
|
||||||
case reflect.Int32:
|
case reflect.Int32:
|
||||||
return int32(intVal), nil
|
return int32(intVal), nil //nolint:gosec // G115: value range bounded by caller/type, conversion intentional
|
||||||
case reflect.Int64:
|
case reflect.Int64:
|
||||||
return intVal, nil
|
return intVal, nil
|
||||||
}
|
}
|
||||||
@@ -883,11 +883,11 @@ func ConvertToNumericType(value string, kind reflect.Kind) (interface{}, error)
|
|||||||
case reflect.Uint:
|
case reflect.Uint:
|
||||||
return uint(uintVal), nil
|
return uint(uintVal), nil
|
||||||
case reflect.Uint8:
|
case reflect.Uint8:
|
||||||
return uint8(uintVal), nil
|
return uint8(uintVal), nil //nolint:gosec // G115: value range bounded by caller/type, conversion intentional
|
||||||
case reflect.Uint16:
|
case reflect.Uint16:
|
||||||
return uint16(uintVal), nil
|
return uint16(uintVal), nil //nolint:gosec // G115: value range bounded by caller/type, conversion intentional
|
||||||
case reflect.Uint32:
|
case reflect.Uint32:
|
||||||
return uint32(uintVal), nil
|
return uint32(uintVal), nil //nolint:gosec // G115: value range bounded by caller/type, conversion intentional
|
||||||
case reflect.Uint64:
|
case reflect.Uint64:
|
||||||
return uintVal, nil
|
return uintVal, nil
|
||||||
}
|
}
|
||||||
@@ -1546,7 +1546,7 @@ func convertToInt64(value interface{}) (int64, bool) {
|
|||||||
case int64:
|
case int64:
|
||||||
return v, true
|
return v, true
|
||||||
case uint:
|
case uint:
|
||||||
return int64(v), true
|
return int64(v), true //nolint:gosec // G115: value range bounded by caller/type, conversion intentional
|
||||||
case uint8:
|
case uint8:
|
||||||
return int64(v), true
|
return int64(v), true
|
||||||
case uint16:
|
case uint16:
|
||||||
@@ -1554,7 +1554,7 @@ func convertToInt64(value interface{}) (int64, bool) {
|
|||||||
case uint32:
|
case uint32:
|
||||||
return int64(v), true
|
return int64(v), true
|
||||||
case uint64:
|
case uint64:
|
||||||
return int64(v), true
|
return int64(v), true //nolint:gosec // G115: value range bounded by caller/type, conversion intentional
|
||||||
case float32:
|
case float32:
|
||||||
return int64(v), true
|
return int64(v), true
|
||||||
case float64:
|
case float64:
|
||||||
@@ -1571,15 +1571,15 @@ func convertToInt64(value interface{}) (int64, bool) {
|
|||||||
func convertToUint64(value interface{}) (uint64, bool) {
|
func convertToUint64(value interface{}) (uint64, bool) {
|
||||||
switch v := value.(type) {
|
switch v := value.(type) {
|
||||||
case int:
|
case int:
|
||||||
return uint64(v), true
|
return uint64(v), true //nolint:gosec // G115: value range bounded by caller/type, conversion intentional
|
||||||
case int8:
|
case int8:
|
||||||
return uint64(v), true
|
return uint64(v), true //nolint:gosec // G115: value range bounded by caller/type, conversion intentional
|
||||||
case int16:
|
case int16:
|
||||||
return uint64(v), true
|
return uint64(v), true //nolint:gosec // G115: value range bounded by caller/type, conversion intentional
|
||||||
case int32:
|
case int32:
|
||||||
return uint64(v), true
|
return uint64(v), true //nolint:gosec // G115: value range bounded by caller/type, conversion intentional
|
||||||
case int64:
|
case int64:
|
||||||
return uint64(v), true
|
return uint64(v), true //nolint:gosec // G115: value range bounded by caller/type, conversion intentional
|
||||||
case uint:
|
case uint:
|
||||||
return uint64(v), true
|
return uint64(v), true
|
||||||
case uint8:
|
case uint8:
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ func OAuth2CallbackHandler(auth *security.DatabaseAuthenticator, providerName, a
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
json.NewEncoder(w).Encode(loginResp) //nolint:errcheck
|
json.NewEncoder(w).Encode(loginResp) //nolint:errcheck,gosec // G104: best-effort write, error intentionally ignored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -529,7 +529,7 @@ func ExampleBunRouterWithBunDB(bunDB *bun.DB) {
|
|||||||
SetupBunRouterRoutes(bunRouter, handler, nil)
|
SetupBunRouterRoutes(bunRouter, handler, nil)
|
||||||
|
|
||||||
// Start server
|
// Start server
|
||||||
if err := http.ListenAndServe(":8080", bunRouter); err != nil {
|
if err := http.ListenAndServe(":8080", bunRouter); err != nil { //nolint:gosec // G114: example code only
|
||||||
logger.Error("Server failed to start: %v", err)
|
logger.Error("Server failed to start: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -549,7 +549,7 @@ func ExampleBunRouterWithGroup(bunDB *bun.DB) {
|
|||||||
SetupBunRouterRoutes(apiGroup, handler, nil)
|
SetupBunRouterRoutes(apiGroup, handler, nil)
|
||||||
|
|
||||||
// Start server
|
// Start server
|
||||||
if err := http.ListenAndServe(":8080", bunRouter); err != nil {
|
if err := http.ListenAndServe(":8080", bunRouter); err != nil { //nolint:gosec // G114: example code only
|
||||||
logger.Error("Server failed to start: %v", err)
|
logger.Error("Server failed to start: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -520,7 +520,7 @@ func SetSessionCookie(w http.ResponseWriter, loginResp *LoginResponse, opts ...S
|
|||||||
maxAge = int(loginResp.ExpiresIn)
|
maxAge = int(loginResp.ExpiresIn)
|
||||||
}
|
}
|
||||||
|
|
||||||
http.SetCookie(w, &http.Cookie{
|
http.SetCookie(w, &http.Cookie{ //nolint:gosec // G124: Secure/HttpOnly/SameSite set from options with secure defaults
|
||||||
Name: o.name(),
|
Name: o.name(),
|
||||||
Value: loginResp.Token,
|
Value: loginResp.Token,
|
||||||
Path: o.path(),
|
Path: o.path(),
|
||||||
@@ -563,7 +563,7 @@ func ClearSessionCookie(w http.ResponseWriter, opts ...SessionCookieOptions) {
|
|||||||
o = opts[0]
|
o = opts[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
http.SetCookie(w, &http.Cookie{
|
http.SetCookie(w, &http.Cookie{ //nolint:gosec // G124: Secure/HttpOnly/SameSite set from options with secure defaults
|
||||||
Name: o.name(),
|
Name: o.name(),
|
||||||
Value: "",
|
Value: "",
|
||||||
Path: o.path(),
|
Path: o.path(),
|
||||||
|
|||||||
@@ -54,10 +54,10 @@ func ExampleOAuth2Google() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Return user info as JSON
|
// Return user info as JSON
|
||||||
_ = json.NewEncoder(w).Encode(loginResp)
|
_ = json.NewEncoder(w).Encode(loginResp) //nolint:gosec // G117: intentional: field must be serialized
|
||||||
})
|
})
|
||||||
|
|
||||||
_ = http.ListenAndServe(":8080", router)
|
_ = http.ListenAndServe(":8080", router) //nolint:gosec // G114: example code only
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example: OAuth2 Authentication with GitHub
|
// Example: OAuth2 Authentication with GitHub
|
||||||
@@ -89,10 +89,10 @@ func ExampleOAuth2GitHub() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = json.NewEncoder(w).Encode(loginResp)
|
_ = json.NewEncoder(w).Encode(loginResp) //nolint:gosec // G117: intentional: field must be serialized
|
||||||
})
|
})
|
||||||
|
|
||||||
_ = http.ListenAndServe(":8080", router)
|
_ = http.ListenAndServe(":8080", router) //nolint:gosec // G114: example code only
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example: Custom OAuth2 Provider
|
// Example: Custom OAuth2 Provider
|
||||||
@@ -100,7 +100,7 @@ func ExampleOAuth2Custom() {
|
|||||||
db, _ := sql.Open("postgres", "connection-string")
|
db, _ := sql.Open("postgres", "connection-string")
|
||||||
|
|
||||||
// Custom OAuth2 provider configuration
|
// Custom OAuth2 provider configuration
|
||||||
oauth2Auth := NewDatabaseAuthenticator(db).WithOAuth2(OAuth2Config{
|
oauth2Auth := NewDatabaseAuthenticator(db).WithOAuth2(OAuth2Config{ //nolint:gosec // G101: false positive: identifier/example, not a credential
|
||||||
ClientID: "your-client-id",
|
ClientID: "your-client-id",
|
||||||
ClientSecret: "your-client-secret",
|
ClientSecret: "your-client-secret",
|
||||||
RedirectURL: "http://localhost:8080/auth/callback",
|
RedirectURL: "http://localhost:8080/auth/callback",
|
||||||
@@ -142,10 +142,10 @@ func ExampleOAuth2Custom() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = json.NewEncoder(w).Encode(loginResp)
|
_ = json.NewEncoder(w).Encode(loginResp) //nolint:gosec // G117: intentional: field must be serialized
|
||||||
})
|
})
|
||||||
|
|
||||||
_ = http.ListenAndServe(":8080", router)
|
_ = http.ListenAndServe(":8080", router) //nolint:gosec // G114: example code only
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example: Multi-Provider OAuth2 with Security Integration
|
// Example: Multi-Provider OAuth2 with Security Integration
|
||||||
@@ -190,7 +190,7 @@ func ExampleOAuth2MultiProvider() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
http.SetCookie(w, &http.Cookie{
|
http.SetCookie(w, &http.Cookie{ //nolint:gosec // G124: Secure/HttpOnly/SameSite set from options with secure defaults
|
||||||
Name: "session_token",
|
Name: "session_token",
|
||||||
Value: loginResp.Token,
|
Value: loginResp.Token,
|
||||||
Path: "/",
|
Path: "/",
|
||||||
@@ -218,7 +218,7 @@ func ExampleOAuth2MultiProvider() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
http.SetCookie(w, &http.Cookie{
|
http.SetCookie(w, &http.Cookie{ //nolint:gosec // G124: Secure/HttpOnly/SameSite set from options with secure defaults
|
||||||
Name: "session_token",
|
Name: "session_token",
|
||||||
Value: loginResp.Token,
|
Value: loginResp.Token,
|
||||||
Path: "/",
|
Path: "/",
|
||||||
@@ -243,7 +243,7 @@ func ExampleOAuth2MultiProvider() {
|
|||||||
_ = json.NewEncoder(w).Encode(userCtx)
|
_ = json.NewEncoder(w).Encode(userCtx)
|
||||||
})
|
})
|
||||||
|
|
||||||
_ = http.ListenAndServe(":8080", router)
|
_ = http.ListenAndServe(":8080", router) //nolint:gosec // G114: example code only
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example: OAuth2 with Token Refresh
|
// Example: OAuth2 with Token Refresh
|
||||||
@@ -294,10 +294,10 @@ func ExampleOAuth2TokenRefresh() {
|
|||||||
SameSite: http.SameSiteLaxMode,
|
SameSite: http.SameSiteLaxMode,
|
||||||
})
|
})
|
||||||
|
|
||||||
_ = json.NewEncoder(w).Encode(loginResp)
|
_ = json.NewEncoder(w).Encode(loginResp) //nolint:gosec // G117: intentional: field must be serialized
|
||||||
})
|
})
|
||||||
|
|
||||||
_ = http.ListenAndServe(":8080", router)
|
_ = http.ListenAndServe(":8080", router) //nolint:gosec // G114: example code only
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example: OAuth2 Logout
|
// Example: OAuth2 Logout
|
||||||
@@ -334,7 +334,7 @@ func ExampleOAuth2Logout() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Clear cookie
|
// Clear cookie
|
||||||
http.SetCookie(w, &http.Cookie{
|
http.SetCookie(w, &http.Cookie{ //nolint:gosec // G124: Secure/HttpOnly/SameSite set from options with secure defaults
|
||||||
Name: "session_token",
|
Name: "session_token",
|
||||||
Value: "",
|
Value: "",
|
||||||
Path: "/",
|
Path: "/",
|
||||||
@@ -346,7 +346,7 @@ func ExampleOAuth2Logout() {
|
|||||||
_, _ = w.Write([]byte("Logged out successfully"))
|
_, _ = w.Write([]byte("Logged out successfully"))
|
||||||
})
|
})
|
||||||
|
|
||||||
_ = http.ListenAndServe(":8080", router)
|
_ = http.ListenAndServe(":8080", router) //nolint:gosec // G114: example code only
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example: Complete OAuth2 Integration with Database Setup
|
// Example: Complete OAuth2 Integration with Database Setup
|
||||||
@@ -393,7 +393,7 @@ func ExampleOAuth2Complete() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
http.SetCookie(w, &http.Cookie{
|
http.SetCookie(w, &http.Cookie{ //nolint:gosec // G124: Secure/HttpOnly/SameSite set from options with secure defaults
|
||||||
Name: "session_token",
|
Name: "session_token",
|
||||||
Value: loginResp.Token,
|
Value: loginResp.Token,
|
||||||
Path: "/",
|
Path: "/",
|
||||||
@@ -426,7 +426,7 @@ func ExampleOAuth2Complete() {
|
|||||||
UserID: userCtx.UserID,
|
UserID: userCtx.UserID,
|
||||||
})
|
})
|
||||||
|
|
||||||
http.SetCookie(w, &http.Cookie{
|
http.SetCookie(w, &http.Cookie{ //nolint:gosec // G124: Secure/HttpOnly/SameSite set from options with secure defaults
|
||||||
Name: "session_token",
|
Name: "session_token",
|
||||||
Value: "",
|
Value: "",
|
||||||
Path: "/",
|
Path: "/",
|
||||||
@@ -437,7 +437,7 @@ func ExampleOAuth2Complete() {
|
|||||||
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
|
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
|
||||||
})
|
})
|
||||||
|
|
||||||
_ = http.ListenAndServe(":8080", router)
|
_ = http.ListenAndServe(":8080", router) //nolint:gosec // G114: example code only
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupOAuth2Tables(db *sql.DB) {
|
func setupOAuth2Tables(db *sql.DB) {
|
||||||
@@ -488,7 +488,7 @@ func ExampleOAuth2AllProviders() {
|
|||||||
|
|
||||||
// Create authenticator with ALL OAuth2 providers
|
// Create authenticator with ALL OAuth2 providers
|
||||||
auth := NewDatabaseAuthenticator(db).
|
auth := NewDatabaseAuthenticator(db).
|
||||||
WithOAuth2(OAuth2Config{
|
WithOAuth2(OAuth2Config{ //nolint:gosec // G101: false positive: identifier/example, not a credential
|
||||||
ClientID: "google-client-id",
|
ClientID: "google-client-id",
|
||||||
ClientSecret: "google-client-secret",
|
ClientSecret: "google-client-secret",
|
||||||
RedirectURL: "http://localhost:8080/auth/google/callback",
|
RedirectURL: "http://localhost:8080/auth/google/callback",
|
||||||
@@ -498,7 +498,7 @@ func ExampleOAuth2AllProviders() {
|
|||||||
UserInfoURL: "https://www.googleapis.com/oauth2/v2/userinfo",
|
UserInfoURL: "https://www.googleapis.com/oauth2/v2/userinfo",
|
||||||
ProviderName: "google",
|
ProviderName: "google",
|
||||||
}).
|
}).
|
||||||
WithOAuth2(OAuth2Config{
|
WithOAuth2(OAuth2Config{ //nolint:gosec // G101: false positive: identifier/example, not a credential
|
||||||
ClientID: "github-client-id",
|
ClientID: "github-client-id",
|
||||||
ClientSecret: "github-client-secret",
|
ClientSecret: "github-client-secret",
|
||||||
RedirectURL: "http://localhost:8080/auth/github/callback",
|
RedirectURL: "http://localhost:8080/auth/github/callback",
|
||||||
@@ -508,7 +508,7 @@ func ExampleOAuth2AllProviders() {
|
|||||||
UserInfoURL: "https://api.github.com/user",
|
UserInfoURL: "https://api.github.com/user",
|
||||||
ProviderName: "github",
|
ProviderName: "github",
|
||||||
}).
|
}).
|
||||||
WithOAuth2(OAuth2Config{
|
WithOAuth2(OAuth2Config{ //nolint:gosec // G101: false positive: identifier/example, not a credential
|
||||||
ClientID: "microsoft-client-id",
|
ClientID: "microsoft-client-id",
|
||||||
ClientSecret: "microsoft-client-secret",
|
ClientSecret: "microsoft-client-secret",
|
||||||
RedirectURL: "http://localhost:8080/auth/microsoft/callback",
|
RedirectURL: "http://localhost:8080/auth/microsoft/callback",
|
||||||
@@ -518,7 +518,7 @@ func ExampleOAuth2AllProviders() {
|
|||||||
UserInfoURL: "https://graph.microsoft.com/v1.0/me",
|
UserInfoURL: "https://graph.microsoft.com/v1.0/me",
|
||||||
ProviderName: "microsoft",
|
ProviderName: "microsoft",
|
||||||
}).
|
}).
|
||||||
WithOAuth2(OAuth2Config{
|
WithOAuth2(OAuth2Config{ //nolint:gosec // G101: false positive: identifier/example, not a credential
|
||||||
ClientID: "facebook-client-id",
|
ClientID: "facebook-client-id",
|
||||||
ClientSecret: "facebook-client-secret",
|
ClientSecret: "facebook-client-secret",
|
||||||
RedirectURL: "http://localhost:8080/auth/facebook/callback",
|
RedirectURL: "http://localhost:8080/auth/facebook/callback",
|
||||||
@@ -547,7 +547,7 @@ func ExampleOAuth2AllProviders() {
|
|||||||
http.Error(w, err.Error(), http.StatusUnauthorized)
|
http.Error(w, err.Error(), http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = json.NewEncoder(w).Encode(loginResp)
|
_ = json.NewEncoder(w).Encode(loginResp) //nolint:gosec // G117: intentional: field must be serialized
|
||||||
})
|
})
|
||||||
|
|
||||||
// GitHub routes
|
// GitHub routes
|
||||||
@@ -562,7 +562,7 @@ func ExampleOAuth2AllProviders() {
|
|||||||
http.Error(w, err.Error(), http.StatusUnauthorized)
|
http.Error(w, err.Error(), http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = json.NewEncoder(w).Encode(loginResp)
|
_ = json.NewEncoder(w).Encode(loginResp) //nolint:gosec // G117: intentional: field must be serialized
|
||||||
})
|
})
|
||||||
|
|
||||||
// Microsoft routes
|
// Microsoft routes
|
||||||
@@ -577,7 +577,7 @@ func ExampleOAuth2AllProviders() {
|
|||||||
http.Error(w, err.Error(), http.StatusUnauthorized)
|
http.Error(w, err.Error(), http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = json.NewEncoder(w).Encode(loginResp)
|
_ = json.NewEncoder(w).Encode(loginResp) //nolint:gosec // G117: intentional: field must be serialized
|
||||||
})
|
})
|
||||||
|
|
||||||
// Facebook routes
|
// Facebook routes
|
||||||
@@ -592,7 +592,7 @@ func ExampleOAuth2AllProviders() {
|
|||||||
http.Error(w, err.Error(), http.StatusUnauthorized)
|
http.Error(w, err.Error(), http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = json.NewEncoder(w).Encode(loginResp)
|
_ = json.NewEncoder(w).Encode(loginResp) //nolint:gosec // G117: intentional: field must be serialized
|
||||||
})
|
})
|
||||||
|
|
||||||
// Create security list for protected routes
|
// Create security list for protected routes
|
||||||
@@ -611,5 +611,5 @@ func ExampleOAuth2AllProviders() {
|
|||||||
_ = json.NewEncoder(w).Encode(userCtx)
|
_ = json.NewEncoder(w).Encode(userCtx)
|
||||||
})
|
})
|
||||||
|
|
||||||
_ = http.ListenAndServe(":8080", router)
|
_ = http.ListenAndServe(":8080", router) //nolint:gosec // G114: example code only
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -441,7 +441,7 @@ func (a *DatabaseAuthenticator) OAuth2RefreshToken(ctx context.Context, refreshT
|
|||||||
// NewGoogleAuthenticator creates a DatabaseAuthenticator configured for Google OAuth2
|
// NewGoogleAuthenticator creates a DatabaseAuthenticator configured for Google OAuth2
|
||||||
func NewGoogleAuthenticator(clientID, clientSecret, redirectURL string, db *sql.DB) *DatabaseAuthenticator {
|
func NewGoogleAuthenticator(clientID, clientSecret, redirectURL string, db *sql.DB) *DatabaseAuthenticator {
|
||||||
auth := NewDatabaseAuthenticator(db)
|
auth := NewDatabaseAuthenticator(db)
|
||||||
return auth.WithOAuth2(OAuth2Config{
|
return auth.WithOAuth2(OAuth2Config{ //nolint:gosec // G101: false positive: identifier/example, not a credential
|
||||||
ClientID: clientID,
|
ClientID: clientID,
|
||||||
ClientSecret: clientSecret,
|
ClientSecret: clientSecret,
|
||||||
RedirectURL: redirectURL,
|
RedirectURL: redirectURL,
|
||||||
@@ -456,7 +456,7 @@ func NewGoogleAuthenticator(clientID, clientSecret, redirectURL string, db *sql.
|
|||||||
// NewGitHubAuthenticator creates a DatabaseAuthenticator configured for GitHub OAuth2
|
// NewGitHubAuthenticator creates a DatabaseAuthenticator configured for GitHub OAuth2
|
||||||
func NewGitHubAuthenticator(clientID, clientSecret, redirectURL string, db *sql.DB) *DatabaseAuthenticator {
|
func NewGitHubAuthenticator(clientID, clientSecret, redirectURL string, db *sql.DB) *DatabaseAuthenticator {
|
||||||
auth := NewDatabaseAuthenticator(db)
|
auth := NewDatabaseAuthenticator(db)
|
||||||
return auth.WithOAuth2(OAuth2Config{
|
return auth.WithOAuth2(OAuth2Config{ //nolint:gosec // G101: false positive: identifier/example, not a credential
|
||||||
ClientID: clientID,
|
ClientID: clientID,
|
||||||
ClientSecret: clientSecret,
|
ClientSecret: clientSecret,
|
||||||
RedirectURL: redirectURL,
|
RedirectURL: redirectURL,
|
||||||
@@ -471,7 +471,7 @@ func NewGitHubAuthenticator(clientID, clientSecret, redirectURL string, db *sql.
|
|||||||
// NewMicrosoftAuthenticator creates a DatabaseAuthenticator configured for Microsoft OAuth2
|
// NewMicrosoftAuthenticator creates a DatabaseAuthenticator configured for Microsoft OAuth2
|
||||||
func NewMicrosoftAuthenticator(clientID, clientSecret, redirectURL string, db *sql.DB) *DatabaseAuthenticator {
|
func NewMicrosoftAuthenticator(clientID, clientSecret, redirectURL string, db *sql.DB) *DatabaseAuthenticator {
|
||||||
auth := NewDatabaseAuthenticator(db)
|
auth := NewDatabaseAuthenticator(db)
|
||||||
return auth.WithOAuth2(OAuth2Config{
|
return auth.WithOAuth2(OAuth2Config{ //nolint:gosec // G101: false positive: identifier/example, not a credential
|
||||||
ClientID: clientID,
|
ClientID: clientID,
|
||||||
ClientSecret: clientSecret,
|
ClientSecret: clientSecret,
|
||||||
RedirectURL: redirectURL,
|
RedirectURL: redirectURL,
|
||||||
@@ -486,7 +486,7 @@ func NewMicrosoftAuthenticator(clientID, clientSecret, redirectURL string, db *s
|
|||||||
// NewFacebookAuthenticator creates a DatabaseAuthenticator configured for Facebook OAuth2
|
// NewFacebookAuthenticator creates a DatabaseAuthenticator configured for Facebook OAuth2
|
||||||
func NewFacebookAuthenticator(clientID, clientSecret, redirectURL string, db *sql.DB) *DatabaseAuthenticator {
|
func NewFacebookAuthenticator(clientID, clientSecret, redirectURL string, db *sql.DB) *DatabaseAuthenticator {
|
||||||
auth := NewDatabaseAuthenticator(db)
|
auth := NewDatabaseAuthenticator(db)
|
||||||
return auth.WithOAuth2(OAuth2Config{
|
return auth.WithOAuth2(OAuth2Config{ //nolint:gosec // G101: false positive: identifier/example, not a credential
|
||||||
ClientID: clientID,
|
ClientID: clientID,
|
||||||
ClientSecret: clientSecret,
|
ClientSecret: clientSecret,
|
||||||
RedirectURL: redirectURL,
|
RedirectURL: redirectURL,
|
||||||
|
|||||||
@@ -305,7 +305,7 @@ func (s *OAuthServer) serverMetadata() map[string]interface{} {
|
|||||||
|
|
||||||
func (s *OAuthServer) metadataHandler(w http.ResponseWriter, r *http.Request) {
|
func (s *OAuthServer) metadataHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
json.NewEncoder(w).Encode(s.serverMetadata()) //nolint:errcheck
|
json.NewEncoder(w).Encode(s.serverMetadata()) //nolint:errcheck,gosec // G104: best-effort write, error intentionally ignored
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
@@ -318,7 +318,7 @@ func (s *OAuthServer) openIDConfigurationHandler(w http.ResponseWriter, r *http.
|
|||||||
meta["id_token_signing_alg_values_supported"] = []string{"RS256"}
|
meta["id_token_signing_alg_values_supported"] = []string{"RS256"}
|
||||||
meta["claims_supported"] = []string{"sub", "iss", "aud", "exp", "iat", "email", "preferred_username"}
|
meta["claims_supported"] = []string{"sub", "iss", "aud", "exp", "iat", "email", "preferred_username"}
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
json.NewEncoder(w).Encode(meta) //nolint:errcheck
|
json.NewEncoder(w).Encode(meta) //nolint:errcheck,gosec // G104: best-effort write, error intentionally ignored
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
@@ -333,7 +333,7 @@ func (s *OAuthServer) protectedResourceHandler(w http.ResponseWriter, r *http.Re
|
|||||||
"bearer_methods_supported": []string{"header"},
|
"bearer_methods_supported": []string{"header"},
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
json.NewEncoder(w).Encode(meta) //nolint:errcheck
|
json.NewEncoder(w).Encode(meta) //nolint:errcheck,gosec // G104: best-effort write, error intentionally ignored
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
@@ -343,7 +343,7 @@ func (s *OAuthServer) protectedResourceHandler(w http.ResponseWriter, r *http.Re
|
|||||||
func (s *OAuthServer) jwksHandler(w http.ResponseWriter, r *http.Request) {
|
func (s *OAuthServer) jwksHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
if s.signingKey == nil {
|
if s.signingKey == nil {
|
||||||
json.NewEncoder(w).Encode(map[string]interface{}{"keys": []interface{}{}}) //nolint:errcheck
|
json.NewEncoder(w).Encode(map[string]interface{}{"keys": []interface{}{}}) //nolint:errcheck,gosec // G104: best-effort write, error intentionally ignored
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pub := s.signingKey.PublicKey
|
pub := s.signingKey.PublicKey
|
||||||
@@ -355,7 +355,7 @@ func (s *OAuthServer) jwksHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
"n": base64.RawURLEncoding.EncodeToString(pub.N.Bytes()),
|
"n": base64.RawURLEncoding.EncodeToString(pub.N.Bytes()),
|
||||||
"e": base64.RawURLEncoding.EncodeToString(bigEndianBytes(pub.E)),
|
"e": base64.RawURLEncoding.EncodeToString(bigEndianBytes(pub.E)),
|
||||||
}
|
}
|
||||||
json.NewEncoder(w).Encode(map[string]interface{}{"keys": []interface{}{jwk}}) //nolint:errcheck
|
json.NewEncoder(w).Encode(map[string]interface{}{"keys": []interface{}{jwk}}) //nolint:errcheck,gosec // G104: best-effort write, error intentionally ignored
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
@@ -392,7 +392,7 @@ func (s *OAuthServer) userinfoHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
json.NewEncoder(w).Encode(map[string]interface{}{ //nolint:errcheck
|
json.NewEncoder(w).Encode(map[string]interface{}{ //nolint:errcheck,gosec // G104: best-effort write, error intentionally ignored
|
||||||
"sub": info.Sub,
|
"sub": info.Sub,
|
||||||
"preferred_username": info.Username,
|
"preferred_username": info.Username,
|
||||||
"email": info.Email,
|
"email": info.Email,
|
||||||
@@ -507,7 +507,7 @@ func (s *OAuthServer) registerHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
w.WriteHeader(http.StatusCreated)
|
w.WriteHeader(http.StatusCreated)
|
||||||
json.NewEncoder(w).Encode(resp) //nolint:errcheck
|
json.NewEncoder(w).Encode(resp) //nolint:errcheck,gosec // G104: best-effort write, error intentionally ignored
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
@@ -995,7 +995,7 @@ func (s *OAuthServer) revokeHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if s.auth != nil {
|
if s.auth != nil {
|
||||||
s.auth.OAuthRevokeToken(r.Context(), token) //nolint:errcheck
|
s.auth.OAuthRevokeToken(r.Context(), token) //nolint:errcheck,gosec // G104: best-effort write, error intentionally ignored
|
||||||
} else {
|
} else {
|
||||||
// In external-provider-only mode, attempt revocation via the first provider's auth.
|
// In external-provider-only mode, attempt revocation via the first provider's auth.
|
||||||
s.mu.RLock()
|
s.mu.RLock()
|
||||||
@@ -1005,7 +1005,7 @@ func (s *OAuthServer) revokeHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
s.mu.RUnlock()
|
s.mu.RUnlock()
|
||||||
if providerAuth != nil {
|
if providerAuth != nil {
|
||||||
providerAuth.OAuthRevokeToken(r.Context(), token) //nolint:errcheck
|
providerAuth.OAuthRevokeToken(r.Context(), token) //nolint:errcheck,gosec // G104: best-effort write, error intentionally ignored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
@@ -1022,14 +1022,14 @@ func (s *OAuthServer) introspectHandler(w http.ResponseWriter, r *http.Request)
|
|||||||
}
|
}
|
||||||
if err := r.ParseForm(); err != nil {
|
if err := r.ParseForm(); err != nil {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
w.Write([]byte(`{"active":false}`)) //nolint:errcheck
|
w.Write([]byte(`{"active":false}`)) //nolint:errcheck,gosec // G104: best-effort write, error intentionally ignored
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
token := r.FormValue("token")
|
token := r.FormValue("token")
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
if token == "" {
|
if token == "" {
|
||||||
w.Write([]byte(`{"active":false}`)) //nolint:errcheck
|
w.Write([]byte(`{"active":false}`)) //nolint:errcheck,gosec // G104: best-effort write, error intentionally ignored
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1043,16 +1043,16 @@ func (s *OAuthServer) introspectHandler(w http.ResponseWriter, r *http.Request)
|
|||||||
s.mu.RUnlock()
|
s.mu.RUnlock()
|
||||||
}
|
}
|
||||||
if authToUse == nil {
|
if authToUse == nil {
|
||||||
w.Write([]byte(`{"active":false}`)) //nolint:errcheck
|
w.Write([]byte(`{"active":false}`)) //nolint:errcheck,gosec // G104: best-effort write, error intentionally ignored
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
info, err := authToUse.OAuthIntrospectToken(r.Context(), token)
|
info, err := authToUse.OAuthIntrospectToken(r.Context(), token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.Write([]byte(`{"active":false}`)) //nolint:errcheck
|
w.Write([]byte(`{"active":false}`)) //nolint:errcheck,gosec // G104: best-effort write, error intentionally ignored
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
json.NewEncoder(w).Encode(info) //nolint:errcheck
|
json.NewEncoder(w).Encode(info) //nolint:errcheck,gosec // G104: best-effort write, error intentionally ignored
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
@@ -1063,13 +1063,13 @@ func (s *OAuthServer) renderLoginForm(w http.ResponseWriter, r *http.Request, cl
|
|||||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
errHTML := ""
|
errHTML := ""
|
||||||
if errMsg != "" {
|
if errMsg != "" {
|
||||||
errHTML = `<p style="color:red">` + errMsg + `</p>`
|
errHTML = `<p style="color:red">` + htmlEscape(errMsg) + `</p>`
|
||||||
}
|
}
|
||||||
fmt.Fprintf(w, loginFormHTML,
|
fmt.Fprintf(w, loginFormHTML, //nolint:gosec // G705: output is HTML-escaped
|
||||||
s.cfg.LoginTitle,
|
htmlEscape(s.cfg.LoginTitle),
|
||||||
s.cfg.LoginTitle,
|
htmlEscape(s.cfg.LoginTitle),
|
||||||
errHTML,
|
errHTML,
|
||||||
clientID,
|
htmlEscape(clientID),
|
||||||
htmlEscape(redirectURI),
|
htmlEscape(redirectURI),
|
||||||
htmlEscape(clientState),
|
htmlEscape(clientState),
|
||||||
htmlEscape(codeChallenge),
|
htmlEscape(codeChallenge),
|
||||||
@@ -1195,7 +1195,7 @@ func (s *OAuthServer) writeOAuthToken(w http.ResponseWriter, r *http.Request, ac
|
|||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
w.Header().Set("Cache-Control", "no-store")
|
w.Header().Set("Cache-Control", "no-store")
|
||||||
w.Header().Set("Pragma", "no-cache")
|
w.Header().Set("Pragma", "no-cache")
|
||||||
json.NewEncoder(w).Encode(resp) //nolint:errcheck
|
json.NewEncoder(w).Encode(resp) //nolint:errcheck,gosec // G104: best-effort write, error intentionally ignored
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildIDToken issues an OIDC id_token for the just-issued access token by reusing the
|
// buildIDToken issues an OIDC id_token for the just-issued access token by reusing the
|
||||||
@@ -1294,7 +1294,7 @@ func writeOAuthError(w http.ResponseWriter, errCode, description string, status
|
|||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
w.WriteHeader(status)
|
w.WriteHeader(status)
|
||||||
json.NewEncoder(w).Encode(resp) //nolint:errcheck
|
json.NewEncoder(w).Encode(resp) //nolint:errcheck,gosec // G104: best-effort write, error intentionally ignored
|
||||||
}
|
}
|
||||||
|
|
||||||
func htmlEscape(s string) string {
|
func htmlEscape(s string) string {
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ func (a *DatabaseAuthenticator) OAuthSaveCode(ctx context.Context, code *OAuthCo
|
|||||||
return a.oauthSaveCodeDirect(ctx, code)
|
return a.oauthSaveCodeDirect(ctx, code)
|
||||||
}
|
}
|
||||||
|
|
||||||
input, err := json.Marshal(code)
|
input, err := json.Marshal(code) //nolint:gosec // G117: intentional: field must be serialized
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to marshal code: %w", err)
|
return fmt.Errorf("failed to marshal code: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -239,7 +239,7 @@ func PasskeyHTTPHandlersExample(auth *DatabaseAuthenticator) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
_ = json.NewEncoder(w).Encode(loginResponse)
|
_ = json.NewEncoder(w).Encode(loginResponse) //nolint:gosec // G117: intentional: field must be serialized
|
||||||
})
|
})
|
||||||
|
|
||||||
// List credentials endpoint
|
// List credentials endpoint
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ func (a *DatabaseAuthenticator) Login(ctx context.Context, req LoginRequest) (*L
|
|||||||
return a.loginDirect(ctx, req)
|
return a.loginDirect(ctx, req)
|
||||||
}
|
}
|
||||||
// Convert LoginRequest to JSON
|
// Convert LoginRequest to JSON
|
||||||
reqJSON, err := json.Marshal(req)
|
reqJSON, err := json.Marshal(req) //nolint:gosec // G117: intentional: field must be serialized
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to marshal login request: %w", err)
|
return nil, fmt.Errorf("failed to marshal login request: %w", err)
|
||||||
}
|
}
|
||||||
@@ -254,7 +254,7 @@ func (a *DatabaseAuthenticator) Register(ctx context.Context, req RegisterReques
|
|||||||
return a.registerDirect(ctx, req)
|
return a.registerDirect(ctx, req)
|
||||||
}
|
}
|
||||||
// Convert RegisterRequest to JSON
|
// Convert RegisterRequest to JSON
|
||||||
reqJSON, err := json.Marshal(req)
|
reqJSON, err := json.Marshal(req) //nolint:gosec // G117: intentional: field must be serialized
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to marshal register request: %w", err)
|
return nil, fmt.Errorf("failed to marshal register request: %w", err)
|
||||||
}
|
}
|
||||||
@@ -414,7 +414,7 @@ func (a *DatabaseAuthenticator) Authenticate(r *http.Request) (*UserContext, err
|
|||||||
|
|
||||||
err := a.runDBOpWithReconnect(func(db *sql.DB) error {
|
err := a.runDBOpWithReconnect(func(db *sql.DB) error {
|
||||||
query := fmt.Sprintf(`SELECT p_success, p_error, p_user::text FROM %s($1, $2)`, a.sqlNames.Session)
|
query := fmt.Sprintf(`SELECT p_success, p_error, p_user::text FROM %s($1, $2)`, a.sqlNames.Session)
|
||||||
return db.QueryRowContext(r.Context(), query, token, reference).Scan(&success, &errorMsg, &userJSON)
|
return db.QueryRowContext(r.Context(), query, token, reference).Scan(&success, &errorMsg, &userJSON) //nolint:gosec // G701: identifier comes from trusted config, values are bound parameters
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("session query failed: %w", err)
|
return nil, fmt.Errorf("session query failed: %w", err)
|
||||||
@@ -505,7 +505,7 @@ func (a *DatabaseAuthenticator) updateSessionActivity(ctx context.Context, sessi
|
|||||||
|
|
||||||
_ = a.runDBOpWithReconnect(func(db *sql.DB) error {
|
_ = a.runDBOpWithReconnect(func(db *sql.DB) error {
|
||||||
query := fmt.Sprintf(`SELECT p_success, p_error, p_user::text FROM %s($1, $2::jsonb)`, a.sqlNames.SessionUpdate)
|
query := fmt.Sprintf(`SELECT p_success, p_error, p_user::text FROM %s($1, $2::jsonb)`, a.sqlNames.SessionUpdate)
|
||||||
return db.QueryRowContext(ctx, query, sessionToken, string(userJSON)).Scan(&success, &errorMsg, &updatedUserJSON)
|
return db.QueryRowContext(ctx, query, sessionToken, string(userJSON)).Scan(&success, &errorMsg, &updatedUserJSON) //nolint:gosec // G701: identifier comes from trusted config, values are bound parameters
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -218,7 +218,7 @@ func (a *DatabaseAuthenticator) sessionDirect(ctx context.Context, token string)
|
|||||||
FROM %s s JOIN %s u ON s.user_id = u.id
|
FROM %s s JOIN %s u ON s.user_id = u.id
|
||||||
WHERE s.session_token = ? AND s.expires_at > ? AND u.is_active = ?`,
|
WHERE s.session_token = ? AND s.expires_at > ? AND u.is_active = ?`,
|
||||||
a.tableNames.UserSessions, a.tableNames.Users))
|
a.tableNames.UserSessions, a.tableNames.Users))
|
||||||
return db.QueryRowContext(ctx, query, token, time.Now(), true).Scan(&userID, &username, &email, &userLevel, &roles, &programUserID, &programUserTable)
|
return db.QueryRowContext(ctx, query, token, time.Now(), true).Scan(&userID, &username, &email, &userLevel, &roles, &programUserID, &programUserTable) //nolint:gosec // G701: identifier comes from trusted config, values are bound parameters
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, sql.ErrNoRows) {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
@@ -242,7 +242,7 @@ func (a *DatabaseAuthenticator) sessionDirect(ctx context.Context, token string)
|
|||||||
func (a *DatabaseAuthenticator) updateSessionActivityDirect(ctx context.Context, sessionToken string) error {
|
func (a *DatabaseAuthenticator) updateSessionActivityDirect(ctx context.Context, sessionToken string) error {
|
||||||
return a.runDBOpWithReconnect(func(db *sql.DB) error {
|
return a.runDBOpWithReconnect(func(db *sql.DB) error {
|
||||||
query := rewritePlaceholders(db, fmt.Sprintf(`UPDATE %s SET last_activity_at = ? WHERE session_token = ? AND expires_at > ?`, a.tableNames.UserSessions))
|
query := rewritePlaceholders(db, fmt.Sprintf(`UPDATE %s SET last_activity_at = ? WHERE session_token = ? AND expires_at > ?`, a.tableNames.UserSessions))
|
||||||
_, err := db.ExecContext(ctx, query, time.Now(), sessionToken, time.Now())
|
_, err := db.ExecContext(ctx, query, time.Now(), sessionToken, time.Now()) //nolint:gosec // G701: identifier comes from trusted config, values are bound parameters
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ type SQLNames struct {
|
|||||||
|
|
||||||
// DefaultSQLNames returns an SQLNames with all default resolvespec_* values.
|
// DefaultSQLNames returns an SQLNames with all default resolvespec_* values.
|
||||||
func DefaultSQLNames() *SQLNames {
|
func DefaultSQLNames() *SQLNames {
|
||||||
return &SQLNames{
|
return &SQLNames{ //nolint:gosec // G101: false positive: identifier/example, not a credential
|
||||||
Login: "resolvespec_login",
|
Login: "resolvespec_login",
|
||||||
Register: "resolvespec_register",
|
Register: "resolvespec_register",
|
||||||
Logout: "resolvespec_logout",
|
Logout: "resolvespec_logout",
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ type TableNames struct {
|
|||||||
|
|
||||||
// DefaultTableNames returns a TableNames with all default table names.
|
// DefaultTableNames returns a TableNames with all default table names.
|
||||||
func DefaultTableNames() *TableNames {
|
func DefaultTableNames() *TableNames {
|
||||||
return &TableNames{
|
return &TableNames{ //nolint:gosec // G101: false positive: identifier/example, not a credential
|
||||||
Users: "users",
|
Users: "users",
|
||||||
UserSessions: "user_sessions",
|
UserSessions: "user_sessions",
|
||||||
TokenBlacklist: "token_blacklist",
|
TokenBlacklist: "token_blacklist",
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package security
|
|||||||
import (
|
import (
|
||||||
"crypto/hmac"
|
"crypto/hmac"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/sha1"
|
"crypto/sha1" //nolint:gosec // G505: SHA-1 is required by RFC 6238/4226 HMAC-TOTP
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"crypto/sha512"
|
"crypto/sha512"
|
||||||
"encoding/base32"
|
"encoding/base32"
|
||||||
@@ -117,7 +117,7 @@ func (t *TOTPGenerator) GenerateCode(secret string, timestamp time.Time) (string
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calculate counter (time steps since Unix epoch)
|
// Calculate counter (time steps since Unix epoch)
|
||||||
counter := uint64(timestamp.Unix()) / uint64(t.config.Period)
|
counter := uint64(timestamp.Unix()) / uint64(t.config.Period) //nolint:gosec // G115: value range bounded by caller/type, conversion intentional
|
||||||
|
|
||||||
// Generate HMAC
|
// Generate HMAC
|
||||||
h := t.getHashFunc()
|
h := t.getHashFunc()
|
||||||
|
|||||||
@@ -493,9 +493,9 @@ func newInstance(cfg Config) (*serverInstance, error) {
|
|||||||
if cfg.HTTP2 {
|
if cfg.HTTP2 {
|
||||||
if existing := os.Getenv("GODEBUG"); !strings.Contains(existing, "http2xconnect=1") {
|
if existing := os.Getenv("GODEBUG"); !strings.Contains(existing, "http2xconnect=1") {
|
||||||
if existing == "" {
|
if existing == "" {
|
||||||
os.Setenv("GODEBUG", "http2xconnect=1")
|
os.Setenv("GODEBUG", "http2xconnect=1") //nolint:gosec // G104: best-effort call, error intentionally ignored
|
||||||
} else {
|
} else {
|
||||||
os.Setenv("GODEBUG", existing+",http2xconnect=1")
|
os.Setenv("GODEBUG", existing+",http2xconnect=1") //nolint:gosec // G104: best-effort call, error intentionally ignored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if httpServer.HTTP2 == nil {
|
if httpServer.HTTP2 == nil {
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ func (s *Service) Handler(fallback http.Handler) http.Handler {
|
|||||||
// attempt fails; see ErrorHandler above.
|
// attempt fails; see ErrorHandler above.
|
||||||
if r.Body != nil && r.Body != http.NoBody {
|
if r.Body != nil && r.Body != http.NoBody {
|
||||||
bodyBytes, err := io.ReadAll(r.Body)
|
bodyBytes, err := io.ReadAll(r.Body)
|
||||||
r.Body.Close()
|
r.Body.Close() //nolint:gosec // G104: best-effort call, error intentionally ignored
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "failed to read request body", http.StatusInternalServerError)
|
http.Error(w, "failed to read request body", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
|
|||||||
+1
-1
@@ -116,7 +116,7 @@ func getCertDirectory() (string, error) {
|
|||||||
// isCertificateValid checks if a certificate file exists and is not expired.
|
// isCertificateValid checks if a certificate file exists and is not expired.
|
||||||
func isCertificateValid(certFile string) bool {
|
func isCertificateValid(certFile string) bool {
|
||||||
// Check if file exists
|
// Check if file exists
|
||||||
certData, err := os.ReadFile(certFile)
|
certData, err := os.ReadFile(certFile) //nolint:gosec // G304: path from trusted server config
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ func (f *ZipFile) Read(b []byte) (int, error) {
|
|||||||
n, err := f.rc.Read(b)
|
n, err := f.rc.Read(b)
|
||||||
f.offset += int64(n)
|
f.offset += int64(n)
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
f.rc.Close()
|
f.rc.Close() //nolint:gosec // G104: best-effort call, error intentionally ignored
|
||||||
f.rc = nil
|
f.rc = nil
|
||||||
}
|
}
|
||||||
return n, err
|
return n, err
|
||||||
@@ -68,7 +68,7 @@ func (f *ZipFile) Read(b []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
func (f *ZipFile) Seek(offset int64, whence int) (int64, error) {
|
func (f *ZipFile) Seek(offset int64, whence int) (int64, error) {
|
||||||
if f.rc != nil {
|
if f.rc != nil {
|
||||||
f.rc.Close()
|
f.rc.Close() //nolint:gosec // G104: best-effort call, error intentionally ignored
|
||||||
f.rc = nil
|
f.rc = nil
|
||||||
}
|
}
|
||||||
switch whence {
|
switch whence {
|
||||||
@@ -83,7 +83,7 @@ func (f *ZipFile) Seek(offset int64, whence int) (int64, error) {
|
|||||||
}
|
}
|
||||||
f.offset += offset
|
f.offset += offset
|
||||||
case io.SeekEnd:
|
case io.SeekEnd:
|
||||||
size := int64(f.UncompressedSize64)
|
size := int64(f.UncompressedSize64) //nolint:gosec // G115: value range bounded by caller/type, conversion intentional
|
||||||
if size+offset < 0 {
|
if size+offset < 0 {
|
||||||
return 0, &fs.PathError{Op: "seek", Path: f.Name, Err: fmt.Errorf("negative position")}
|
return 0, &fs.PathError{Op: "seek", Path: f.Name, Err: fmt.Errorf("negative position")}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,7 +254,7 @@ func (n SqlNull[T]) Int64() int64 {
|
|||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
return v.Int()
|
return v.Int()
|
||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||||
return int64(v.Uint())
|
return int64(v.Uint()) //nolint:gosec // G115: value range bounded by caller/type, conversion intentional
|
||||||
case reflect.Float32, reflect.Float64:
|
case reflect.Float32, reflect.Float64:
|
||||||
return int64(v.Float())
|
return int64(v.Float())
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
@@ -556,7 +556,7 @@ func TryIfInt64(v any, def int64) int64 {
|
|||||||
case int64:
|
case int64:
|
||||||
return val
|
return val
|
||||||
case uint:
|
case uint:
|
||||||
return int64(val)
|
return int64(val) //nolint:gosec // G115: value range bounded by caller/type, conversion intentional
|
||||||
case uint8:
|
case uint8:
|
||||||
return int64(val)
|
return int64(val)
|
||||||
case uint16:
|
case uint16:
|
||||||
@@ -564,7 +564,7 @@ func TryIfInt64(v any, def int64) int64 {
|
|||||||
case uint32:
|
case uint32:
|
||||||
return int64(val)
|
return int64(val)
|
||||||
case uint64:
|
case uint64:
|
||||||
return int64(val)
|
return int64(val) //nolint:gosec // G115: value range bounded by caller/type, conversion intentional
|
||||||
case float32:
|
case float32:
|
||||||
return int64(val)
|
return int64(val)
|
||||||
case float64:
|
case float64:
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ func (v *SqlSparseVector) Scan(value any) error {
|
|||||||
if len(kv) != 2 {
|
if len(kv) != 2 {
|
||||||
return fmt.Errorf("SqlSparseVector: bad pair %q", pair)
|
return fmt.Errorf("SqlSparseVector: bad pair %q", pair)
|
||||||
}
|
}
|
||||||
k, err := strconv.Atoi(strings.TrimSpace(kv[0]))
|
k, err := strconv.ParseInt(strings.TrimSpace(kv[0]), 10, 32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("SqlSparseVector: bad index %q: %w", kv[0], err)
|
return fmt.Errorf("SqlSparseVector: bad index %q: %w", kv[0], err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -304,7 +304,7 @@ func (c *Connection) Close() {
|
|||||||
c.cancel()
|
c.cancel()
|
||||||
}
|
}
|
||||||
if c.ws != nil {
|
if c.ws != nil {
|
||||||
c.ws.Close()
|
c.ws.Close() //nolint:gosec // G104: best-effort call, error intentionally ignored
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up subscriptions
|
// Clean up subscriptions
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ func (h *Handler) HandleWebSocket(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
if err := h.hooks.Execute(BeforeConnect, hookCtx); err != nil {
|
if err := h.hooks.Execute(BeforeConnect, hookCtx); err != nil {
|
||||||
logger.Error("[WebSocketSpec] BeforeConnect hook failed: %v", err)
|
logger.Error("[WebSocketSpec] BeforeConnect hook failed: %v", err)
|
||||||
ws.Close()
|
ws.Close() //nolint:gosec // G104: best-effort call, error intentionally ignored
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user