Strider report

Strider corpus: sftpgo

703 msformat1902 mscheck 11564total 2905errors 4202warnings 4457notes

Showing 1000 of 11564 detailed findings. The summary includes all 11564 findings.

examples/OTP/authy/keyint/main.go1

99:13add-constantstring literal "%v\n" appears more than twice; define a constant

examples/OTP/authy/keyint/main.go:99:13

98 q, _ = json.Marshal(checkTokenQuestion)
99 fmt.Printf("%v\n", string(q))
100 scanner.Scan()

examples/OTP/authy/checkpwd/main.go1

57:6cognitive-complexityfunction has cognitive complexity 25; maximum is 7

examples/OTP/authy/checkpwd/main.go:57:6

56
57func main() {
58 // get credentials from env vars

internal/common/common.go1

667:2confusing-namingname proxyAllowed differs from ProxyAllowed only by capitalization

internal/common/common.go:667:2

666 rateLimitersList *dataprovider.IPList
667 proxyAllowed []func(net.IP) bool
668 proxySkipped []func(net.IP) bool

internal/command/command.go1

128:64confusing-resultsadjacent unnamed results of the same type should be named

internal/command/command.go:128:64

127// GetConfig returns the configuration for the specified command
128func GetConfig(command, hook string) (time.Duration, []string, []string) {
129 env := []string{}

internal/common/httpauth.go1

56:6constructor-interface-returnNewBasicAuthProvider returns interface HTTPAuthProvider although its concrete result is consistently *basicAuthProvider; return the concrete type

internal/common/httpauth.go:56:6

55// NewBasicAuthProvider returns an HTTPAuthProvider implementing Basic Auth
56func NewBasicAuthProvider(authUserFile string) (HTTPAuthProvider, error) {
57 basicAuthProvider := basicAuthProvider{

internal/dataprovider/sqlcommon.go1

1014:3context-cancel-in-loopcancellation deferred inside a loop runs only when the surrounding function returns; cancel before the iteration ends

internal/dataprovider/sqlcommon.go:1014:3

1013 ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
1014 defer cancel()
1015

examples/OTP/authy/keyint/main.go1

52:6cyclomatic-complexityfunction complexity is 13; maximum is 10

examples/OTP/authy/keyint/main.go:52:6

51
52func main() {
53 // get credentials from env vars

examples/OTP/authy/checkpwd/main.go1

51:3deep-exitprocess-exit calls should be confined to main or init

examples/OTP/authy/checkpwd/main.go:51:3

50 if status > 0 {
51 os.Exit(0)
52 } else {

internal/dataprovider/configs.go1

35:53deprecated-api-usagegolang.org/x/crypto/ssh.InsecureKeyAlgoDSA is deprecated: DSA is only supported at insecure key sizes, and was removed from major implementations.

internal/dataprovider/configs.go:35:53

34 supportedHostKeyAlgos = []string{ssh.KeyAlgoRSA}
35 supportedPublicKeyAlgos = []string{ssh.KeyAlgoRSA, ssh.InsecureKeyAlgoDSA} //nolint:staticcheck
36 supportedKexAlgos = []string{

internal/cmd/portable.go1

117:23discarded-error-resulterror result returned by filepath.Abs is discarded

internal/cmd/portable.go:117:23

116 if fsProvider == sdk.LocalFilesystemProvider {
117 portableDir, _ = filepath.Abs(portableDir)
118 } else {

examples/ldapauthserver/config/config.go1

14:2doc-comment-perioddocumentation comment should end with punctuation

examples/ldapauthserver/config/config.go:14:2

13 // This is the file name without extension, we use viper and so we
14 // support all the config files format supported by viper
15 DefaultConfigName = "ldapauth"

internal/common/common.go1

461:35duration-multiplied-by-durationmultiplying two time.Duration values produces squared time units; multiply a duration by a unitless count

internal/common/common.go:461:35

460 ratio := idleTimeoutCheckInterval / periodicTimeoutCheckInterval
461 spec = fmt.Sprintf("@every %s", duration*ratio)
462 _, err = eventScheduler.AddFunc(spec, Connections.checkIdles)

internal/common/connection.go1

460:3early-returninvert the condition and return early to reduce nesting

internal/common/connection.go:460:3

459 if err := fs.Remove(fsPath, false); err != nil {
460 if status > 0 && fs.IsNotExist(err) {
461 // file removed in the pre-action, if the file was deleted from the EventManager the quota is already updated

internal/common/tlsutils.go1

86:22error-stringserror string should not be capitalized or end with punctuation

internal/common/tlsutils.go:86:22

85 if keyPair.ID == "" {
86 return errors.New("TLS certificate without ID")
87 }

examples/ldapauth/main.go1

123:3excessive-blank-identifiersassignment discards three or more results; name meaningful results or simplify the return contract

examples/ldapauth/main.go:123:3

122 // check public key
123 userKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(publickey))
124 if err != nil {

examples/ldapauthserver/cmd/root.go1

69:6exported-declaration-commentexported function or method should have a comment beginning with its name

examples/ldapauthserver/cmd/root.go:69:6

68// This is called by main.main(). It only needs to happen once to the rootCmd.
69func Execute() {
70 if err := rootCmd.Execute(); err != nil {

internal/acme/acme.go2

1:1file-length-limitfile has 860 lines; maximum is 500

internal/acme/acme.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//
145:52flag-parameterboolean parameter checkRenew controls function flow

internal/acme/acme.go:145:52

144// Initialize validates and set the configuration
145func Initialize(c Configuration, configDir string, checkRenew bool) error {
146 config = nil

examples/OTP/authy/extauth/main.go1

1:1formatfile is not formatted

examples/OTP/authy/extauth/main.go:1:1

1package main
2
  • Fix (safe): run `strider fmt examples/OTP/authy/extauth/main.go`

examples/OTP/authy/keyint/main.go1

52:6function-lengthfunction has 47 statements and 86 lines; maximum is 50 statements or 75 lines

examples/OTP/authy/keyint/main.go:52:6

51
52func main() {
53 // get credentials from env vars

internal/common/eventmanager.go1

973:6function-result-limitfunction returns 5 values; maximum is 3

internal/common/eventmanager.go:973:6

972
973func getFileWriter(conn *BaseConnection, virtualPath string, expectedSize int64) (io.WriteCloser, int, int64, func(), error) {
974 fs, fsPath, err := conn.GetFsAndResolvedPath(virtualPath)

internal/config/config.go1

862:6get-function-return-valueGet-prefixed function should return a value

internal/config/config.go:862:6

861
862func getTOTPFromEnv(idx int) {
863 totpConfig := defaultTOTP

internal/httpd/api_utils.go1

127:2identical-switch-branchesswitch repeats a case body

internal/httpd/api_utils.go:127:2

126 statusCode = http.StatusForbidden
127 case errors.Is(err, common.ErrReadQuotaExceeded):
128 statusCode = http.StatusForbidden

examples/ldapauthserver/httpd/httpd.go1

87:3import-shadowingidentifier config shadows an imported package

examples/ldapauthserver/httpd/httpd.go:87:3

86 }
87 config := &tls.Config{
88 GetCertificate: certMgr.GetCertificateFunc(),

internal/sftpd/cryptfs_test.go1

250:3increment-decrementuse ++ or -- instead of assigning an addition or subtraction of one

internal/sftpd/cryptfs_test.go:250:3

249 assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
250 expectedQuotaFiles = expectedQuotaFiles + 1
251 expectedQuotaSize = expectedQuotaSize + encryptedFileSize

internal/common/clientsmap.go1

46:3inefficient-map-lookupreuse the map value obtained by the comma-ok lookup

internal/common/clientsmap.go:46:3

45 c.totalConnections.Add(-1)
46 c.clients[source]--
47 if val > 1 {

internal/acme/acme.go1

314:14inefficient-sprintffmt.Sprintf is unnecessary for this conversion; use strconv.FormatInt with base 10

internal/acme/acme.go:314:14

313func (c *Configuration) setLockTime() error {
314 lockTime := fmt.Sprintf("%v", util.GetTimeAsMsSinceEpoch(time.Now()))
315 err := os.WriteFile(c.lockPath, []byte(lockTime), 0600)

internal/cmd/ping.go1

39:11insecure-url-schemeURL uses insecure http scheme

internal/cmd/ping.go:39:11

38 } else {
39 url = "http://"
40 }

internal/common/common.go1

469:21interface-method-limitinterface has 14 methods, exceeding the configured design limit of 10

internal/common/common.go:469:21

468// ActiveTransfer defines the interface for the current active transfers
469type ActiveTransfer interface {
470 GetID() int64

internal/config/config.go1

738:7max-control-nestingcontrol-flow nesting exceeds 5 levels

internal/config/config.go:738:7

737 if oidc, ok := val.(map[string]any); ok {
738 if _, ok := oidc["scopes"]; ok {
739 globalConf.HTTPDConfig.Bindings[0].OIDC.Scopes = nil

internal/common/actions.go1

132:6max-parametersfunction has 11 parameters; maximum is 8

internal/common/actions.go:132:6

131// ExecuteActionNotification executes the defined hook, if any, for the specified action
132func ExecuteActionNotification(conn *BaseConnection, operation, filePath, virtualPath, target, virtualTarget, sshCmd string,
133 fileSize int64, err error, elapsed int64, metadata map[string]string,

examples/ldapauthserver/httpd/models.go1

66:6max-public-structsfile declares more than 5 exported structs

examples/ldapauthserver/httpd/models.go:66:6

65// SFTPGoUser defines an SFTPGo user
66type SFTPGoUser struct {
67 // Database unique identifier

examples/ldapauthserver/httpd/ldapauth.go1

52:2modifies-parameterassignment modifies parameter r

examples/ldapauthserver/httpd/ldapauth.go:52:2

51func checkSFTPGoUserAuth(w http.ResponseWriter, r *http.Request) {
52 r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
53 var authReq externalAuthRequest

internal/command/command.go1

105:4modifies-value-receiverassignment modifies value receiver c

internal/command/command.go:105:4

104 if cmd.Timeout == 0 {
105 c.Commands[idx].Timeout = c.Timeout
106 } else {

internal/common/actions.go1

45:39nested-structsmove nested anonymous struct types to named declarations

internal/common/actions.go:45:39

44 errUnexpectedHTTResponse = errors.New("unexpected HTTP hook response code")
45 hooksConcurrencyGuard = make(chan struct{}, 150)
46 activeHooks atomic.Int32

internal/acme/acme.go1

329:4nil-error-returnthis branch proves an error is non-nil but returns nil in an error result

internal/acme/acme.go:329:4

328 acmeLog(logger.LevelDebug, "lock file %q not found", c.lockPath)
329 return time.Time{}, nil
330 }

internal/common/common.go1

379:3nil-value-with-nil-errornil payload is returned with a nil error; return a meaningful value or a descriptive error

internal/common/common.go:379:3

378 if Config.defender == nil {
379 return nil, nil
380 }

examples/OTP/authy/checkpwd/main.go1

85:4no-defer-in-loopdefer inside a loop runs at function exit, not iteration exit

examples/OTP/authy/checkpwd/main.go:85:4

84 }
85 defer resp.Body.Close()
86 if resp.StatusCode != http.StatusOK {

internal/common/connection.go1

1798:4no-else-after-returnremove else and unindent its body after the return

internal/common/connection.go:1798:4

1797 return c.GetNotExistError()
1798 } else if fs.IsPermission(err) {
1799 return c.GetPermissionDeniedError()

examples/OTP/authy/checkpwd/main.go1

31:6no-initreplace init with explicit initialization

examples/OTP/authy/checkpwd/main.go:31:6

30
31func init() {
32 // this is for demo only, you probably want to get this mapping dynamically, for example using a database query

internal/dataprovider/sqlcommon.go1

1220:2no-naked-returnreturn values must be explicit

internal/dataprovider/sqlcommon.go:1220:2

1219 err = dbHandle.PingContext(ctx)
1220 return
1221}

examples/OTP/authy/checkpwd/main.go2

28:2no-package-varpackage variables introduce mutable global state

examples/OTP/authy/checkpwd/main.go:28:2

27var (
28 mapping []userMapping
29)
1:9package-commentspackage should have a documentation comment

examples/OTP/authy/checkpwd/main.go:1:9

1package main
2

internal/common/common_test.go1

2023:25range-value-addresstaking the address of range value i can be misleading

internal/common/common_test.go:2023:25

2022 for i := range 100 {
2023 conns = append(conns, &fakeConnection{
2024 BaseConnection: NewBaseConnection(fmt.Sprintf("id%d", i), ProtocolSFTP, "", "", dataprovider.User{

internal/common/clientsmap_test.go1

30:18redundant-conversionconversion from int32 to the identical type is redundant

internal/common/clientsmap_test.go:30:18

29 m.add(ip1)
30 assert.Equal(t, int32(1), m.getTotal())
31 assert.Equal(t, 1, m.getTotalFrom(ip1))

internal/common/eventmanager.go2

617:3single-case-switchswitch with one case can be replaced by an if statement

internal/common/eventmanager.go:617:3

616 for k, v := range *customFields {
617 switch val := v.(type) {
618 case string:
460:7slice-preallocationpreallocate ruleNames with capacity len(range source) before appending once per iteration

internal/common/eventmanager.go:460:7

459 if len(rulesWithSyncActions) > 1 {
460 var ruleNames []string
461 for _, r := range rulesWithSyncActions {

internal/common/defenderdb.go1

149:3task-commentFIXME comment should be resolved or linked to an owned work item

internal/common/defenderdb.go:149:3

148 if lastCleanup.IsZero() || lastCleanup.Add(time.Duration(d.config.ObservationTime)*time.Minute*3).Before(time.Now()) {
149 // FIXME: this could be racy in rare cases but it is better than acquire the lock for the cleanup duration
150 // or to always acquire a read/write lock.

internal/common/httpauth.go1

73:26time-value-equalitycompare time.Time values with Time.Equal instead of == or !=

internal/common/httpauth.go:73:26

72
73 return p.Info == nil || p.Info.ModTime() != info.ModTime() || p.Info.Size() != info.Size()
74}

examples/OTP/authy/checkpwd/main.go2

27:1top-level-declaration-ordertop-level declarations should be ordered as const, var, type, then func

examples/OTP/authy/checkpwd/main.go:27:1

26
27var (
28 mapping []userMapping
99:31unchecked-type-assertionuse the checked two-result form of the type assertion

examples/OTP/authy/checkpwd/main.go:99:31

98 }
99 if authyResponse["success"].(string) == "true" {
100 printResponse(2, pwd)

internal/common/transferschecker.go1

280:55unexported-returnexported function returns an unexported type

internal/common/transferschecker.go:280:55

279
280func (t *transfersCheckerMem) GetOverquotaTransfers() []overquotaTransfer {
281 t.RLock()

internal/cmd/install_windows.go1

64:5unnecessary-formatformatting call has no formatting directive

internal/cmd/install_windows.go:64:5

63 } else {
64 fmt.Printf("Service installed!\r\n")
65 }

internal/util/util.go1

676:49unsafe-formatted-url-host-portformatted host and port may be invalid for IPv6; build the address with net.JoinHostPort

internal/util/util.go:676:49

675 CheckTCP4Port(port)
676 listener, err = net.Listen("tcp", fmt.Sprintf("%s:%d", address, port))
677 }

examples/ldapauthserver/logger/request_logger.go1

53:58unused-parameterparameter header is unused

examples/ldapauthserver/logger/request_logger.go:53:58

52// Write logs a new entry at the end of the HTTP request
53func (l *StructuredLoggerEntry) Write(status, bytes int, header http.Header, elapsed time.Duration, extra interface{}) {
54 l.Logger.Info().

internal/acme/acme.go1

562:7unused-receiverreceiver c is unused

internal/acme/acme.go:562:7

561
562func (c *Configuration) register(client *lego.Client) (*registration.Resource, error) {
563 return client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})

examples/OTP/authy/checkpwd/main.go1

90:33use-anyuse any instead of interface{}

examples/OTP/authy/checkpwd/main.go:90:33

89 }
90 var authyResponse map[string]interface{}
91 respBody, err := io.ReadAll(resp.Body)

internal/acme/acme.go1

187:11use-errors-newreplace fmt.Errorf with errors.New for a static message

internal/acme/acme.go:187:11

186 if !filepath.IsAbs(c.WebRoot) {
187 return fmt.Errorf("invalid HTTP-01 challenge web root, please set an absolute path")
188 }

internal/dataprovider/bolt.go1

2515:3use-slices-sortuse slices.Sort or slices.SortFunc when possible

internal/dataprovider/bolt.go:2515:3

2514 }
2515 sort.Slice(rule.Actions, func(i, j int) bool {
2516 return rule.Actions[i].Order < rule.Actions[j].Order

internal/dataprovider/dataprovider.go1

3727:8weak-cryptographydeprecated cryptographic primitive crypto/md5.New should not protect new data

internal/dataprovider/dataprovider.go:3727:8

3726 if strings.HasPrefix(user.Password, md5DigestPwdPrefix) {
3727 h := md5.New()
3728 h.Write([]byte(password))

examples/ldapauth/main.go1

63:13add-constantstring literal "%v\n" appears more than twice; define a constant

examples/ldapauth/main.go:63:13

62 log.Printf("%v\n", string(resp))
63 fmt.Printf("%v\n", string(resp))
64 os.Exit(0)

examples/OTP/authy/extauth/main.go1

59:6cognitive-complexityfunction has cognitive complexity 23; maximum is 7

examples/OTP/authy/extauth/main.go:59:6

58
59func main() {
60 // get credentials from env vars

internal/common/common.go1

668:2confusing-namingname proxySkipped differs from ProxySkipped only by capitalization

internal/common/common.go:668:2

667 proxyAllowed []func(net.IP) bool
668 proxySkipped []func(net.IP) bool
669}

internal/config/config.go1

2258:47confusing-resultsadjacent unnamed results of the same type should be named

internal/config/config.go:2258:47

2257
2258func lookupBoolFromEnv(envName string) (bool, bool) {
2259 value, ok := os.LookupEnv(envName)

internal/kms/local.go1

38:6constructor-interface-returnNewLocalSecret returns interface SecretProvider although its concrete result is consistently *localSecret; return the concrete type

internal/kms/local.go:38:6

37// NewLocalSecret returns a SecretProvider that use a locally provided symmetric key
38func NewLocalSecret(base BaseSecret, _, masterKey string) SecretProvider {
39 return &localSecret{

internal/vfs/azblobfs.go1

554:3context-cancel-in-loopcancellation deferred inside a loop runs only when the surrounding function returns; cancel before the iteration ends

internal/vfs/azblobfs.go:554:3

553 ctx, cancelFn := context.WithDeadline(context.Background(), time.Now().Add(fs.ctxTimeout))
554 defer cancelFn()
555

examples/ldapauth/main.go1

67:6cyclomatic-complexityfunction complexity is 18; maximum is 10

examples/ldapauth/main.go:67:6

66
67func main() {
68 logWriter, err := syslog.New(syslog.LOG_NOTICE, "sftpgo")

examples/OTP/authy/checkpwd/main.go1

53:3deep-exitprocess-exit calls should be confined to main or init

examples/OTP/authy/checkpwd/main.go:53:3

52 } else {
53 os.Exit(1)
54 }

internal/dataprovider/dataprovider.go1

2990:20deprecated-api-usagegolang.org/x/crypto/ssh.InsecureKeyAlgoDSA is deprecated: DSA is only supported at insecure key sizes, and was removed from major implementations.

internal/dataprovider/dataprovider.go:2990:20

2989 }
2990 if out.Type() == ssh.InsecureKeyAlgoDSA { //nolint:staticcheck
2991 providerLog(logger.LevelError, "dsa public key not accepted, position: %d", idx)

internal/cmd/portable.go1

128:6discarded-error-resulterror result returned by fmt.Printf is discarded

internal/cmd/portable.go:128:6

127 if err != nil {
128 fmt.Printf("Unable to get GCS credentials: %v\n", err)
129 os.Exit(1)

examples/ldapauthserver/config/config.go1

20:1doc-comment-perioddocumentation comment should end with punctuation

examples/ldapauthserver/config/config.go:20:1

19
20// HTTPDConfig defines configuration for the HTTPD server
21type HTTPDConfig struct {

internal/common/transfer.go1

547:15duration-multiplied-by-durationmultiplying two time.Duration values produces squared time units; multiply a duration by a unitless count

internal/common/transfer.go:547:15

546 toSleep := time.Duration(wantedElapsed - realElapsed)
547 time.Sleep(toSleep * time.Millisecond)
548 }

internal/common/connection.go1

1633:3early-returninvert the condition and return early to reduce nesting

internal/common/connection.go:1633:3

1632 numFiles = 1
1633 if fi, err := fs.Stat(targetPath); err == nil {
1634 if fi.Mode().IsDir() {

internal/common/tlsutils.go1

96:22error-stringserror string should not be capitalized or end with punctuation

internal/common/tlsutils.go:96:22

95 logger.Error(m.logSender, "", "TLS certificate with id %q is duplicated", keyPair.ID)
96 return fmt.Errorf("TLS certificate with id %q is duplicated", keyPair.ID)
97 }

examples/ldapauth/main.go1

130:4excessive-blank-identifiersassignment discards three or more results; name meaningful results or simplify the return contract

examples/ldapauth/main.go:130:4

129 for _, k := range sr.Entries[0].GetAttributeValues("nsSshPublicKey") {
130 key, _, _, _, err := ssh.ParseAuthorizedKey([]byte(k))
131 // we skip an invalid public key stored inside the LDAP server

examples/ldapauthserver/config/config.go1

15:2exported-declaration-commentexported declaration should have a comment beginning with its name

examples/ldapauthserver/config/config.go:15:2

14 // support all the config files format supported by viper
15 DefaultConfigName = "ldapauth"
16 // ConfigEnvPrefix defines a prefix that ENVIRONMENT variables will use

internal/cmd/portable.go1

1:1file-length-limitfile has 546 lines; maximum is 500

internal/cmd/portable.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//

internal/acme/acme.go1

833:17flag-parameterboolean parameter checkRenew controls function flow

internal/acme/acme.go:833:17

832
833func setLogMode(checkRenew bool) {
834 if checkRenew {

examples/OTP/authy/keyint/main.go1

1:1formatfile is not formatted

examples/OTP/authy/keyint/main.go:1:1

1package main
2
  • Fix (safe): run `strider fmt examples/OTP/authy/keyint/main.go`

examples/ldapauth/main.go1

67:6function-lengthfunction has 65 statements and 109 lines; maximum is 50 statements or 75 lines

examples/ldapauth/main.go:67:6

66
67func main() {
68 logWriter, err := syslog.New(syslog.LOG_NOTICE, "sftpgo")

internal/dataprovider/bolt.go1

390:24function-result-limitfunction returns 5 values; maximum is 3

internal/dataprovider/bolt.go:390:24

389
390func (p *BoltProvider) getUsedQuota(username string) (int, int64, int64, int64, error) {
391 user, err := p.userExists(username, "")

internal/config/config.go1

897:6get-function-return-valueGet-prefixed function should return a value

internal/config/config.go:897:6

896
897func getRateLimitersFromEnv(idx int) {
898 rtlConfig := defaultRateLimiter

internal/logger/slog.go1

55:2identical-switch-branchesswitch repeats a case body

internal/logger/slog.go:55:2

54 ev = logger.Error()
55 default:
56 ev = logger.Debug()

internal/cmd/initprovider.go1

106:5import-shadowingidentifier service shadows an imported package

internal/cmd/initprovider.go:106:5

105 }
106 service := service.Service{
107 LoadDataFrom: loadDataFrom,

internal/common/common.go1

995:3inefficient-map-lookupreuse the map value obtained by the comma-ok lookup

internal/common/common.go:995:3

994 if val, ok := conns.perUserConns[username]; ok {
995 conns.perUserConns[username]--
996 if val > 1 {

internal/acme/acme.go1

534:51inefficient-sprintffmt.Sprintf is unnecessary for this conversion; use strconv.Itoa

internal/acme/acme.go:534:51

533 acmeLog(logger.LevelDebug, "configuring HTTP-01 challenge, port %d", c.HTTP01Challenge.Port)
534 providerServer := http01.NewProviderServer("", fmt.Sprintf("%d", c.HTTP01Challenge.Port))
535 if c.HTTP01Challenge.ProxyHeader != "" {

internal/cmd/ping.go1

82:13insecure-url-schemeURL uses insecure http scheme

internal/cmd/ping.go:82:13

81 } else {
82 url += "http://"
83 }

internal/common/common.go1

487:23interface-method-limitinterface has 18 methods, exceeding the configured design limit of 10

internal/common/common.go:487:23

486// ActiveConnection defines the interface for the current active connections
487type ActiveConnection interface {
488 GetID() string

internal/dataprovider/user.go1

1357:7max-control-nestingcontrol-flow nesting exceeds 5 levels

internal/dataprovider/user.go:1357:7

1356 if err == nil {
1357 if ipNet.Contains(ip) {
1358 logger.Debug(logSender, connectionID, "override bandwidth limit for ip %q, upload limit: %v KB/s, download limit: %v KB/s",

internal/common/actions.go1

197:6max-parametersfunction has 16 parameters; maximum is 8

internal/common/actions.go:197:6

196
197func newActionNotification(
198 user *dataprovider.User,

internal/common/common.go1

927:6max-public-structsfile declares more than 5 exported structs

internal/common/common.go:927:6

926// Each SSH connection can open several channels for SFTP or SSH commands
927type SSHConnection struct {
928 id string

internal/acme/acme.go1

120:2modifies-parameterassignment modifies parameter config

internal/acme/acme.go:120:2

119func mergeConfig(config Configuration, c *dataprovider.ACMEConfigs) Configuration {
120 config.Domains = []string{c.Domain}
121 config.Email = c.Email

internal/common/defendermem.go1

354:39modifies-value-receiverassignment modifies value receiver p

internal/common/defendermem.go:354:39

353func (p kvList) Less(i, j int) bool { return p[i].Value < p[j].Value }
354func (p kvList) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
355

internal/common/actions.go1

51:27nested-structsmove nested anonymous struct types to named declarations

internal/common/actions.go:51:27

50 activeHooks.Add(1)
51 hooksConcurrencyGuard <- struct{}{}
52}

internal/acme/acme.go1

645:4nil-error-returnthis branch proves an error is non-nil but returns nil in an error result

internal/acme/acme.go:645:4

644 if os.IsNotExist(err) {
645 return false, nil
646 }

internal/common/defenderdb.go1

132:3nil-value-with-nil-errornil payload is returned with a nil error; return a meaningful value or a descriptive error

internal/common/defenderdb.go:132:3

131 if host.BanTime.IsZero() {
132 return nil, nil
133 }

examples/OTP/authy/extauth/main.go1

85:4no-defer-in-loopdefer inside a loop runs at function exit, not iteration exit

examples/OTP/authy/extauth/main.go:85:4

84 }
85 defer resp.Body.Close()
86 if resp.StatusCode != http.StatusOK {

internal/common/connection.go1

1800:4no-else-after-returnremove else and unindent its body after the return

internal/common/connection.go:1800:4

1799 return c.GetPermissionDeniedError()
1800 } else if fs.IsNotSupported(err) {
1801 return c.GetOpUnsupportedError()

examples/OTP/authy/extauth/main.go1

33:6no-initreplace init with explicit initialization

examples/OTP/authy/extauth/main.go:33:6

32
33func init() {
34 // this is for demo only, you probably want to get this mapping dynamically, for example using a database query

internal/ftpd/transfer.go1

69:3no-naked-returnreturn values must be explicit

internal/ftpd/transfer.go:69:3

68 err = t.ConvertError(err)
69 return
70 }

examples/OTP/authy/extauth/main.go2

30:2no-package-varpackage variables introduce mutable global state

examples/OTP/authy/extauth/main.go:30:2

29var (
30 mapping []userMapping
31)
1:9package-commentspackage should have a documentation comment

examples/OTP/authy/extauth/main.go:1:9

1package main
2

internal/common/eventmanager.go1

389:26range-value-addresstaking the address of range value rule can be misleading

internal/common/eventmanager.go:389:26

388 for _, rule := range r.FsEvents {
389 if r.checkFsEventMatch(&rule.Conditions, &params) {
390 if err := rule.CheckActionsConsistency(""); err != nil {

internal/common/clientsmap_test.go1

36:18redundant-conversionconversion from int32 to the identical type is redundant

internal/common/clientsmap_test.go:36:18

35 m.add(ip2)
36 assert.Equal(t, int32(3), m.getTotal())
37 assert.Equal(t, 2, m.getTotalFrom(ip1))

internal/dataprovider/dataprovider.go1

3665:3single-case-switchswitch with one case can be replaced by an if statement

internal/dataprovider/dataprovider.go:3665:3

3664 if user.Filters.TOTPConfig.Enabled {
3665 switch protocol {
3666 case protocolFTP:

internal/common/eventmanager.go1

1174:6slice-preallocationpreallocate files with capacity len(range source) before appending once per iteration

internal/common/eventmanager.go:1174:6

1173func getMailAttachments(conn *BaseConnection, attachments []string, replacer *strings.Replacer) ([]*mail.File, error) {
1174 var files []*mail.File
1175 totalSize := int64(0)

internal/dataprovider/admin.go1

185:1task-commentTODO comment should be resolved or linked to an owned work item

internal/dataprovider/admin.go:185:1

184// AdminFilters defines additional restrictions for SFTPGo admins
185// TODO: rename to AdminOptions in v3
186type AdminFilters struct {

internal/common/tlsutils.go1

282:43time-value-equalitycompare time.Time values with Time.Equal instead of == or !=

internal/common/tlsutils.go:282:43

281 if ok {
282 if newInfo.Size() != oldInfo.Size() || newInfo.ModTime() != oldInfo.ModTime() {
283 logger.Debug(m.logSender, "", "change detected for certificate %q, reload required", k)

examples/OTP/authy/extauth/main.go2

29:1top-level-declaration-ordertop-level declarations should be ordered as const, var, type, then func

examples/OTP/authy/extauth/main.go:29:1

28
29var (
30 mapping []userMapping
99:31unchecked-type-assertionuse the checked two-result form of the type assertion

examples/OTP/authy/extauth/main.go:99:31

98 }
99 if authyResponse["success"].(string) == "true" {
100 printResponse(username)

internal/common/transferschecker.go1

308:54unexported-returnexported function returns an unexported type

internal/common/transferschecker.go:308:54

307
308func (t *transfersCheckerDB) GetOverquotaTransfers() []overquotaTransfer {
309 if t.lastCleanup.IsZero() || t.lastCleanup.Add(periodicTimeoutCheckInterval*15).Before(time.Now()) {

internal/cmd/reload_windows.go1

41:5unnecessary-formatformatting call has no formatting directive

internal/cmd/reload_windows.go:41:5

40 } else {
41 fmt.Printf("Reload signal sent!\r\n")
42 }

internal/webdavd/webdavd_test.go1

3035:58unsafe-formatted-url-host-portformatted host and port may be invalid for IPv6; build the address with net.JoinHostPort

internal/webdavd/webdavd_test.go:3035:58

3034
3035 resp, err = getTLSHTTPClient(tlsConfig).Get(fmt.Sprintf("https://%v:%v@%v/", tlsClient2Username, defaultPassword,
3036 webDavTLSServerAddr))

examples/ldapauthserver/logger/request_logger.go1

53:101unused-parameterparameter extra is unused

examples/ldapauthserver/logger/request_logger.go:53:101

52// Write logs a new entry at the end of the HTTP request
53func (l *StructuredLoggerEntry) Write(status, bytes int, header http.Header, elapsed time.Duration, extra interface{}) {
54 l.Logger.Info().

internal/common/actions.go1

272:7unused-receiverreceiver h is unused

internal/common/actions.go:272:7

271
272func (h *defaultActionHandler) handleHTTP(event *notifier.FsEvent) error {
273 u, err := url.Parse(Config.Actions.Hook)

examples/OTP/authy/extauth/main.go1

90:33use-anyuse any instead of interface{}

examples/OTP/authy/extauth/main.go:90:33

89 }
90 var authyResponse map[string]interface{}
91 respBody, err := io.ReadAll(resp.Body)

internal/acme/acme.go1

291:10use-errors-newreplace fmt.Errorf with errors.New for a static message

internal/acme/acme.go:291:10

290 if !c.HTTP01Challenge.isEnabled() && !c.TLSALPN01Challenge.isEnabled() {
291 return fmt.Errorf("no challenge type defined")
292 }

internal/dataprovider/bolt.go1

2568:3use-slices-sortuse slices.Sort or slices.SortFunc when possible

internal/dataprovider/bolt.go:2568:3

2567 }
2568 sort.Slice(rule.Actions, func(i, j int) bool {
2569 return rule.Actions[i].Order < rule.Actions[j].Order

internal/sftpd/ssh_cmd.go1

157:7weak-cryptographydeprecated cryptographic primitive crypto/md5.New should not protect new data

internal/sftpd/ssh_cmd.go:157:7

156 case "md5sum":
157 h = md5.New()
158 case "sha1sum":

examples/ldapauthserver/logger/logger.go1

86:7add-constantstring literal "sender" appears more than twice; define a constant

examples/ldapauthserver/logger/logger.go:86:7

85 Timestamp().
86 Str("sender", prefix).
87 Str("request_id", requestID).

examples/OTP/authy/keyint/main.go1

52:6cognitive-complexityfunction has cognitive complexity 14; maximum is 7

examples/OTP/authy/keyint/main.go:52:6

51
52func main() {
53 // get credentials from env vars

internal/config/config.go1

201:6confusing-namingname Init differs from init only by capitalization

internal/config/config.go:201:6

200// It is exported to minimize refactoring efforts. Will eventually disappear.
201func Init() {
202 // create a default configuration to use if no config file is provided

internal/dataprovider/bolt.go1

390:67confusing-resultsadjacent unnamed results of the same type should be named

internal/dataprovider/bolt.go:390:67

389
390func (p *BoltProvider) getUsedQuota(username string) (int, int64, int64, int64, error) {
391 user, err := p.userExists(username, "")

internal/vfs/cryptfs.go1

48:6constructor-interface-returnNewCryptFs returns interface Fs although its concrete result is consistently *CryptFs; return the concrete type

internal/vfs/cryptfs.go:48:6

47// NewCryptFs returns a CryptFs object
48func NewCryptFs(connectionID, rootDir, mountPath string, config CryptFsConfig) (Fs, error) {
49 if err := config.validate(); err != nil {

internal/vfs/azblobfs.go1

622:3context-cancel-in-loopcancellation deferred inside a loop runs only when the surrounding function returns; cancel before the iteration ends

internal/vfs/azblobfs.go:622:3

621 ctx, cancelFn := context.WithDeadline(context.Background(), time.Now().Add(fs.ctxTimeout))
622 defer cancelFn()
623

examples/ldapauthserver/httpd/ldapauth.go1

51:6cyclomatic-complexityfunction complexity is 14; maximum is 10

examples/ldapauthserver/httpd/ldapauth.go:51:6

50
51func checkSFTPGoUserAuth(w http.ResponseWriter, r *http.Request) {
52 r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)

examples/OTP/authy/extauth/main.go1

53:3deep-exitprocess-exit calls should be confined to main or init

examples/OTP/authy/extauth/main.go:53:3

52 if len(username) > 0 {
53 os.Exit(0)
54 } else {

internal/httpd/httpd_test.go1

8895:29deprecated-api-usagegolang.org/x/crypto/ssh.InsecureKeyAlgoDSA is deprecated: DSA is only supported at insecure key sizes, and was removed from major implementations.

internal/httpd/httpd_test.go:8895:29

8894 HostKeyAlgos: []string{ssh.KeyAlgoRSA, ssh.CertAlgoRSAv01},
8895 PublicKeyAlgos: []string{ssh.InsecureKeyAlgoDSA}, //nolint:staticcheck
8896 },

internal/cmd/portable.go1

138:6discarded-error-resulterror result returned by fmt.Printf is discarded

internal/cmd/portable.go:138:6

137 if err != nil {
138 fmt.Printf("Unable to get SFTP private key: %v\n", err)
139 os.Exit(1)

examples/ldapauthserver/config/config.go1

29:1doc-comment-perioddocumentation comment should end with punctuation

examples/ldapauthserver/config/config.go:29:1

28
29// LDAPConfig defines the configuration parameters for LDAP connections and searches
30type LDAPConfig struct {

internal/httpd/handler.go1

376:15duration-multiplied-by-durationmultiplying two time.Duration values produces squared time units; multiply a duration by a unitless count

internal/httpd/handler.go:376:15

375 toSleep := time.Duration(wantedElapsed - elapsed)
376 time.Sleep(toSleep * time.Millisecond)
377 }

internal/common/eventmanager.go1

1245:4early-returninvert the condition and return early to reduce nesting

internal/common/eventmanager.go:1245:4

1244 if p.InverseMatch {
1245 if checkEventConditionPattern(p, name) {
1246 matches = true

internal/dataprovider/apikey.go1

188:21error-stringserror string should not be capitalized or end with punctuation

internal/dataprovider/apikey.go:188:21

187 if k.ExpiresAt > 0 && k.ExpiresAt < util.GetTimeAsMsSinceEpoch(time.Now()) {
188 return fmt.Errorf("API key %q is expired, expiration timestamp: %v current timestamp: %v", k.KeyID,
189 k.ExpiresAt, util.GetTimeAsMsSinceEpoch(time.Now()))

examples/ldapauthserver/httpd/ldapauth.go1

100:3excessive-blank-identifiersassignment discards three or more results; name meaningful results or simplify the return contract

examples/ldapauthserver/httpd/ldapauth.go:100:3

99 if len(authReq.PublicKey) > 0 {
100 userKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(authReq.PublicKey))
101 if err != nil {

examples/ldapauthserver/httpd/tlsutils.go1

30:23exported-declaration-commentexported function or method should have a comment beginning with its name

examples/ldapauthserver/httpd/tlsutils.go:30:23

29
30func (m *certManager) GetCertificateFunc() func(*tls.ClientHelloInfo) (*tls.Certificate, error) {
31 return func(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {

internal/common/common.go1

1:1file-length-limitfile has 1563 lines; maximum is 500

internal/common/common.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//

internal/common/connection.go1

386:62flag-parameterboolean parameter isNewFile controls function flow

internal/common/connection.go:386:62

385// GetCreateChecks returns the checks for creating new files
386func (c *BaseConnection) GetCreateChecks(virtualPath string, isNewFile bool, isResume bool) int {
387 result := 0

examples/ldapauth/main.go1

1:1formatfile is not formatted

examples/ldapauth/main.go:1:1

1package main
2
  • Fix (safe): run `strider fmt examples/ldapauth/main.go`

examples/ldapauthserver/httpd/ldapauth.go1

51:6function-lengthfunction has 58 statements and 93 lines; maximum is 50 statements or 75 lines

examples/ldapauthserver/httpd/ldapauth.go:51:6

50
51func checkSFTPGoUserAuth(w http.ResponseWriter, r *http.Request) {
52 r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)

internal/dataprovider/dataprovider.go1

1605:6function-result-limitfunction returns 5 values; maximum is 3

internal/dataprovider/dataprovider.go:1605:6

1604// GetUsedQuota returns the used quota for the given SFTPGo user.
1605func GetUsedQuota(username string) (int, int64, int64, int64, error) {
1606 if config.TrackQuota == 0 {

internal/config/config.go1

1043:6get-function-return-valueGet-prefixed function should return a value

internal/config/config.go:1043:6

1042
1043func getPluginsFromEnv(idx int) {
1044 pluginConfig := plugin.Config{}

internal/util/util.go1

209:3identical-switch-branchesswitch repeats a case body

internal/util/util.go:209:3

208 return false
209 case ':', '*', '?', '"', '<', '>', '|':
210 return false

internal/cmd/portable.go1

201:4import-shadowingidentifier service shadows an imported package

internal/cmd/portable.go:201:4

200 service.SetGraceTime(graceTime)
201 service := service.Service{
202 ConfigDir: util.CleanDirInput(configDir),

internal/common/defendermem.go1

142:4inefficient-map-lookupreuse the map value obtained by the comma-ok lookup

internal/common/defendermem.go:142:4

141 d.Lock()
142 d.banned[ip] = banTime.Add(time.Duration(increment) * time.Minute)
143 d.Unlock()

internal/acme/acme.go1

550:80inefficient-sprintffmt.Sprintf is unnecessary for this conversion; use strconv.Itoa

internal/acme/acme.go:550:80

549 acmeLog(logger.LevelDebug, "configuring TLSALPN-01 challenge, port %d", c.TLSALPN01Challenge.Port)
550 err := client.Challenge.SetTLSALPN01Provider(tlsalpn01.NewProviderServer("", fmt.Sprintf("%d", c.TLSALPN01Challenge.Port)))
551 if err != nil {

internal/common/actions_test.go1

131:26insecure-url-schemeURL uses insecure http scheme

internal/common/actions_test.go:131:26

130 ExecuteOn: []string{operationDownload},
131 Hook: fmt.Sprintf("http://%v", httpAddr),
132 }

internal/dataprovider/dataprovider.go1

768:15interface-method-limitinterface has 122 methods, exceeding the configured design limit of 10

internal/dataprovider/dataprovider.go:768:15

767// Provider defines the interface that data providers must implement.
768type Provider interface {
769 validateUserAndPass(username, password, ip, protocol string) (User, error)

internal/ftpd/ftpd.go1

206:7max-control-nestingcontrol-flow nesting exceeds 5 levels

internal/ftpd/ftpd.go:206:7

205 if fn(clientIP) {
206 if override.IP == "" {
207 return strings.Split(cc.LocalAddr().String(), ":")[0], nil

internal/common/eventmanager.go1

892:6max-parametersfunction has 9 parameters; maximum is 8

internal/common/eventmanager.go:892:6

891
892func closeWriterAndUpdateQuota(w io.WriteCloser, conn *BaseConnection, virtualSourcePath, virtualTargetPath string,
893 numFiles int, truncatedSize int64, errTransfer error, operation string, startTime time.Time,

internal/common/common.go1

964:6max-public-structsfile declares more than 5 exported structs

internal/common/common.go:964:6

963// ActiveConnections holds the currect active connections with the associated transfers
964type ActiveConnections struct {
965 // clients contains both authenticated and estabilished connections and the ones waiting

internal/acme/acme.go1

121:2modifies-parameterassignment modifies parameter config

internal/acme/acme.go:121:2

120 config.Domains = []string{c.Domain}
121 config.Email = c.Email
122 config.HTTP01Challenge.Port = c.HTTP01Challenge.Port

internal/common/defendermem.go1

354:45modifies-value-receiverassignment modifies value receiver p

internal/common/defendermem.go:354:45

353func (p kvList) Less(i, j int) bool { return p[i].Value < p[j].Value }
354func (p kvList) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
355

internal/common/connection_test.go1

1285:13nested-structsmove nested anonymous struct types to named declarations

internal/common/connection_test.go:1285:13

1284
1285 tests := []struct {
1286 name string

internal/acme/acme.go1

651:4nil-error-returnthis branch proves an error is non-nil but returns nil in an error result

internal/acme/acme.go:651:4

650 if os.IsNotExist(err) {
651 return false, nil
652 }

internal/common/defendermem.go1

261:2nil-value-with-nil-errornil payload is returned with a nil error; return a meaningful value or a descriptive error

internal/common/defendermem.go:261:2

260
261 return nil, nil
262}

internal/common/common.go1

1173:5no-defer-in-loopdefer inside a loop runs at function exit, not iteration exit

internal/common/common.go:1173:5

1172 if toClose {
1173 defer func(c *SSHConnection) {
1174 err := c.Close()

internal/common/connection.go1

1802:4no-else-after-returnremove else and unindent its body after the return

internal/common/connection.go:1802:4

1801 return c.GetOpUnsupportedError()
1802 } else if err != nil {
1803 return c.GetGenericError(err)

examples/OTP/authy/keyint/main.go1

31:6no-initreplace init with explicit initialization

examples/OTP/authy/keyint/main.go:31:6

30
31func init() {
32 // this is for demo only, you probably want to get this mapping dynamically, for example using a database query

internal/ftpd/transfer.go1

72:2no-naked-returnreturn values must be explicit

internal/ftpd/transfer.go:72:2

71 t.HandleThrottle()
72 return
73}

examples/OTP/authy/keyint/main.go2

28:2no-package-varpackage variables introduce mutable global state

examples/OTP/authy/keyint/main.go:28:2

27var (
28 mapping []userMapping
29)
1:9package-commentspackage should have a documentation comment

examples/OTP/authy/keyint/main.go:1:9

1package main
2

internal/common/eventmanager.go1

431:32range-value-addresstaking the address of range value rule can be misleading

internal/common/eventmanager.go:431:32

430 for _, rule := range r.IPDLoginEvents {
431 if r.checkIPDLoginEventMatch(&rule.Conditions, &params) {
432 if err := rule.CheckActionsConsistency(""); err != nil {

internal/common/clientsmap_test.go1

43:18redundant-conversionconversion from int32 to the identical type is redundant

internal/common/clientsmap_test.go:43:18

42 m.add(ip2)
43 assert.Equal(t, int32(6), m.getTotal())
44 assert.Equal(t, 4, m.getTotalFrom(ip1))

internal/httpd/api_eventrule.go1

123:2single-case-switchswitch with one case can be replaced by an if statement

internal/httpd/api_eventrule.go:123:2

122
123 switch updatedAction.Type {
124 case dataprovider.ActionTypeHTTP:

internal/common/eventmanager.go1

1956:6slice-preallocationpreallocate parentDirs with capacity len(range source) before appending once per iteration

internal/common/eventmanager.go:1956:6

1955func getArchiveBaseDir(paths []string) string {
1956 var parentDirs []string
1957 for _, p := range paths {

internal/dataprovider/cacheduser.go1

79:1task-commentFIXME comment should be resolved or linked to an owned work item

internal/dataprovider/cacheduser.go:79:1

78// preserving the lock fs if possible
79// FIXME: this could be racy in rare cases
80func (cache *usersCache) swap(userRef *User, plainPassword string) {

examples/OTP/authy/keyint/main.go2

27:1top-level-declaration-ordertop-level declarations should be ordered as const, var, type, then func

examples/OTP/authy/keyint/main.go:27:1

26
27var (
28 mapping []userMapping
133:29unchecked-type-assertionuse the checked two-result form of the type assertion

examples/OTP/authy/keyint/main.go:133:29

132 }
133 if authyResponse["success"].(string) == "true" {
134 printAuthResponse(1)

internal/httpd/resetcode.go1

77:52unexported-returnexported function returns an unexported type

internal/httpd/resetcode.go:77:52

76
77func (m *memoryResetCodeManager) Get(code string) (*resetCode, error) {
78 c, ok := m.resetCodes.Load(code)

internal/cmd/resetpwd.go1

93:4unnecessary-formatformatting call has no formatting directive

internal/cmd/resetpwd.go:93:4

92 }
93 fmt.Printf("Enter Password: ")
94 pwd, err := term.ReadPassword(int(os.Stdin.Fd()))

internal/webdavd/webdavd_test.go1

3147:59unsafe-formatted-url-host-portformatted host and port may be invalid for IPv6; build the address with net.JoinHostPort

internal/webdavd/webdavd_test.go:3147:59

3146
3147 resp, err := getTLSHTTPClient(tlsConfig).Get(fmt.Sprintf("https://%v:%v@%v/", tlsClient2Username, defaultPassword,
3148 webDavTLSServerAddr))

internal/httpd/internal_test.go1

312:34unused-parameterparameter payload is unused

internal/httpd/internal_test.go:312:34

311
312func (s *failingJoseSigner) Sign(payload []byte) (*jose.JSONWebSignature, error) {
313 return nil, errors.New("sign test error")

internal/common/actions.go1

302:7unused-receiverreceiver h is unused

internal/common/actions.go:302:7

301
302func (h *defaultActionHandler) handleCommand(event *notifier.FsEvent) error {
303 if !filepath.IsAbs(Config.Actions.Hook) {

examples/OTP/authy/keyint/main.go1

124:31use-anyuse any instead of interface{}

examples/OTP/authy/keyint/main.go:124:31

123 }
124 var authyResponse map[string]interface{}
125 respBody, err := io.ReadAll(resp.Body)

internal/common/defender.go1

214:10use-errors-newreplace fmt.Errorf with errors.New for a static message

internal/common/defender.go:214:10

213 if c.ScoreInvalid == 0 && c.ScoreValid == 0 && c.ScoreLimitExceeded == 0 && c.ScoreNoAuth == 0 {
214 return fmt.Errorf("invalid defender configuration: all scores are disabled")
215 }

internal/dataprovider/cachedpassword.go1

158:2use-slices-sortuse slices.Sort or slices.SortFunc when possible

internal/dataprovider/cachedpassword.go:158:2

157 }
158 sort.Slice(credentials, func(i, j int) bool {
159 return credentials[i].usedAt.Load() < credentials[j].usedAt.Load()

internal/sftpd/ssh_cmd.go1

159:7weak-cryptographydeprecated cryptographic primitive crypto/sha1.New should not protect new data

internal/sftpd/ssh_cmd.go:159:7

158 case "sha1sum":
159 h = sha1.New()
160 case "sha256sum":

examples/ldapauthserver/logger/logger.go1

87:7add-constantstring literal "request_id" appears more than twice; define a constant

examples/ldapauthserver/logger/logger.go:87:7

86 Str("sender", prefix).
87 Str("request_id", requestID).
88 Msg(fmt.Sprintf(format, v...))

examples/ldapauth/main.go1

67:6cognitive-complexityfunction has cognitive complexity 27; maximum is 7

examples/ldapauth/main.go:67:6

66
67func main() {
68 logWriter, err := syslog.New(syslog.LOG_NOTICE, "sftpgo")

internal/dataprovider/dataprovider.go1

3608:6confusing-namingname checkUserAndPass differs from CheckUserAndPass only by capitalization

internal/dataprovider/dataprovider.go:3608:6

3607
3608func checkUserAndPass(user *User, password, ip, protocol string) (User, error) {
3609 err := user.LoadAndApplyGroupSettings()

internal/dataprovider/bolt.go1

390:74confusing-resultsadjacent unnamed results of the same type should be named

internal/dataprovider/bolt.go:390:74

389
390func (p *BoltProvider) getUsedQuota(username string) (int, int64, int64, int64, error) {
391 user, err := p.userExists(username, "")

internal/vfs/gcsfs.go1

71:6constructor-interface-returnNewGCSFs returns interface Fs although its concrete result is consistently *GCSFs; return the concrete type

internal/vfs/gcsfs.go:71:6

70// NewGCSFs returns an GCSFs object that allows to interact with Google Cloud Storage
71func NewGCSFs(connectionID, localTempDir, mountPath string, config GCSFsConfig) (Fs, error) {
72 if localTempDir == "" {

internal/vfs/s3fs.go1

510:3context-cancel-in-loopcancellation deferred inside a loop runs only when the surrounding function returns; cancel before the iteration ends

internal/vfs/s3fs.go:510:3

509 ctx, cancelFn := context.WithDeadline(context.Background(), time.Now().Add(fs.ctxTimeout))
510 defer cancelFn()
511

internal/acme/acme.go1

239:25cyclomatic-complexityfunction complexity is 12; maximum is 10

internal/acme/acme.go:239:25

238// Initialize validates and initialize the configuration
239func (c *Configuration) Initialize(configDir string) error {
240 c.checkDomains()

examples/OTP/authy/extauth/main.go1

55:3deep-exitprocess-exit calls should be confined to main or init

examples/OTP/authy/extauth/main.go:55:3

54 } else {
55 os.Exit(1)
56 }

internal/httpd/httpd_test.go1

8962:27deprecated-api-usagegolang.org/x/crypto/ssh.InsecureKeyAlgoDSA is deprecated: DSA is only supported at insecure key sizes, and was removed from major implementations.

internal/httpd/httpd_test.go:8962:27

8961 assert.Equal(t, []string{ssh.KeyAlgoRSA}, configsGet.SFTPD.HostKeyAlgos)
8962 assert.Equal(t, []string{ssh.InsecureKeyAlgoDSA}, configsGet.SFTPD.PublicKeyAlgos) //nolint:staticcheck
8963 assert.Len(t, configsGet.SFTPD.KexAlgorithms, 0)

internal/cmd/portable.go1

154:6discarded-error-resulterror result returned by fmt.Printf is discarded

internal/cmd/portable.go:154:6

153 if err != nil {
154 fmt.Printf("Unable to load FTPS key pair, cert file %q key file %q error: %v\n",
155 portableFTPSCert, portableFTPSKey, err)

examples/ldapauthserver/config/config.go1

90:1doc-comment-perioddocumentation comment should end with punctuation

examples/ldapauthserver/config/config.go:90:1

89
90// GetHomeDirectory returns the configured name for the LDAP field to use as home directory
91func (l *LDAPConfig) GetHomeDirectory() string {

internal/util/util.go1

249:7duration-multiplied-by-durationmultiplying two time.Duration values produces squared time units; multiply a duration by a unitless count

internal/util/util.go:249:7

248 h := d / time.Hour
249 d -= h * time.Hour
250 m := d / time.Minute

internal/common/eventmanager.go1

1266:5early-returninvert the condition and return early to reduce nesting

internal/common/eventmanager.go:1266:5

1265 if p.InverseMatch {
1266 if checkEventConditionPattern(p, group.Name) {
1267 matches = true

internal/dataprovider/bolt.go1

114:27error-stringserror string should not be capitalized or end with punctuation

internal/dataprovider/bolt.go:114:27

113 if tlsCert == nil {
114 return user, errors.New("TLS certificate cannot be null or empty")
115 }

examples/ldapauthserver/httpd/ldapauth.go1

108:4excessive-blank-identifiersassignment discards three or more results; name meaningful results or simplify the return contract

examples/ldapauthserver/httpd/ldapauth.go:108:4

107 for _, k := range sr.Entries[0].GetAttributeValues(ldapConfig.GetPublicKey()) {
108 key, _, _, _, err := ssh.ParseAuthorizedKey([]byte(k))
109 // we skip an invalid public key stored inside the LDAP server

examples/ldapauthserver/logger/logger.go1

50:6exported-declaration-commentexported function or method should have a comment beginning with its name

examples/ldapauthserver/logger/logger.go:50:6

49// ConsoleLogger will not be affected
50func DisableLogger() {
51 logger = zerolog.Nop()

internal/common/common_test.go1

1:1file-length-limitfile has 2068 lines; maximum is 500

internal/common/common_test.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//

internal/common/connection.go1

386:78flag-parameterboolean parameter isResume controls function flow

internal/common/connection.go:386:78

385// GetCreateChecks returns the checks for creating new files
386func (c *BaseConnection) GetCreateChecks(virtualPath string, isNewFile bool, isResume bool) int {
387 result := 0

examples/ldapauthserver/cmd/root.go1

1:1formatfile is not formatted

examples/ldapauthserver/cmd/root.go:1:1

1package cmd
2
  • Fix (safe): run `strider fmt examples/ldapauthserver/cmd/root.go`

internal/cmd/portable.go1

305:6function-lengthfunction has 67 statements and 152 lines; maximum is 50 statements or 75 lines

internal/cmd/portable.go:305:6

304
305func init() {
306 version.AddFeature("+portable")

internal/dataprovider/dataprovider.go1

4714:6function-result-limitfunction returns 4 values; maximum is 3

internal/dataprovider/dataprovider.go:4714:6

4713
4714func getUserAndJSONForHook(username string, oidcTokenFields *map[string]any) (User, User, []byte, error) {
4715 u, mergedUser, err := getUserForHook(username, oidcTokenFields)

internal/config/config.go1

1114:6get-function-return-valueGet-prefixed function should return a value

internal/config/config.go:1114:6

1113
1114func getSFTPDBindindFromEnv(idx int) {
1115 binding := defaultSFTPDBinding

internal/cmd/serve.go1

48:4import-shadowingidentifier service shadows an imported package

internal/cmd/serve.go:48:4

47 service.SetGraceTime(graceTime)
48 service := service.Service{
49 ConfigDir: configDir,

internal/common/defendermem.go1

225:4inefficient-map-lookupreuse the map value obtained by the comma-ok lookup

internal/common/defendermem.go:225:4

224 } else {
225 d.hosts[ip] = hs
226 }

internal/common/eventmanager.go1

803:18inefficient-sprintffmt.Sprintf is unnecessary for this conversion; use strconv.Itoa

internal/common/eventmanager.go:803:18

802 "{{.Event}}", p.Event,
803 "{{.Status}}", fmt.Sprintf("%d", p.Status),
804 "{{.VirtualPath}}", p.getStringReplacement(p.VirtualPath, escapeMode),

internal/common/actions_test.go1

144:24insecure-url-schemeURL uses insecure http scheme

internal/common/actions_test.go:144:24

143
144 Config.Actions.Hook = "http://invalid:1234"
145 status, err = actionHandler.Handle(a)

internal/kms/kms.go1

33:21interface-method-limitinterface has 13 methods, exceeding the configured design limit of 10

internal/kms/kms.go:33:21

32// SecretProvider defines the interface for a KMS secrets provider
33type SecretProvider interface {
34 Name() string

internal/sftpd/server.go1

1038:7max-control-nestingcontrol-flow nesting exceeds 5 levels

internal/sftpd/server.go:1038:7

1037 if underlyingAlgo, ok := certKeyAlgoNames[algo]; ok {
1038 if slices.Contains(mas.Algorithms(), underlyingAlgo) {
1039 algos = append(algos, algo)

internal/common/transfer.go1

68:6max-parametersfunction has 14 parameters; maximum is 8

internal/common/transfer.go:68:6

67// NewBaseTransfer returns a new BaseTransfer and adds it to the given connection
68func NewBaseTransfer(file vfs.File, conn *BaseConnection, cancelFn func(), fsPath, effectiveFsPath, requestPath string,
69 transferType int, minWriteOffset, initialSize, maxWriteSize, truncatedSize int64, isNewFile bool, fs vfs.Fs,

internal/common/common.go1

1415:6max-public-structsfile declares more than 5 exported structs

internal/common/common.go:1415:6

1414// ConnectionStatus returns the status for an active connection
1415type ConnectionStatus struct {
1416 // Logged in username

internal/acme/acme.go1

122:2modifies-parameterassignment modifies parameter config

internal/acme/acme.go:122:2

121 config.Email = c.Email
122 config.HTTP01Challenge.Port = c.HTTP01Challenge.Port
123 config.TLSALPN01Challenge.Port = 0

internal/common/connection_test.go1

1482:13nested-structsmove nested anonymous struct types to named declarations

internal/common/connection_test.go:1482:13

1481
1482 tests := []struct {
1483 name string

internal/common/connection.go1

528:4nil-error-returnthis branch proves an error is non-nil but returns nil in an error result

internal/common/connection.go:528:4

527 if fs.IsNotExist(err) && fs.HasVirtualFolders() {
528 return nil
529 }

internal/ftpd/server.go1

244:3nil-value-with-nil-errornil payload is returned with a nil error; return a meaningful value or a descriptive error

internal/ftpd/server.go:244:3

243 if tlsConn == nil {
244 return nil, nil
245 }

internal/common/common.go1

1187:4no-defer-in-loopdefer inside a loop runs at function exit, not iteration exit

internal/common/common.go:1187:4

1186 if idleTime > Config.idleTimeoutAsDuration || (isUnauthenticatedFTPUser && idleTime > Config.idleLoginTimeout) {
1187 defer func(conn ActiveConnection) {
1188 err := conn.Disconnect()

internal/dataprovider/dataprovider.go1

1523:4no-else-after-returnremove else and unindent its body after the return

internal/dataprovider/dataprovider.go:1523:4

1522 return util.NewMethodDisabledError(trackQuotaDisabledError)
1523 } else if config.TrackQuota == 2 && !reset && !user.HasQuotaRestrictions() {
1524 return nil

examples/ldapauthserver/cmd/root.go1

59:6no-initreplace init with explicit initialization

examples/ldapauthserver/cmd/root.go:59:6

58
59func init() {
60 version := utils.GetAppVersion()

internal/ftpd/transfer.go1

88:3no-naked-returnreturn values must be explicit

internal/ftpd/transfer.go:88:3

87 err = t.ConvertError(err)
88 return
89 }

examples/ldapauthserver/cmd/root.go1

44:2no-package-varpackage variables introduce mutable global state

examples/ldapauthserver/cmd/root.go:44:2

43var (
44 configDir string
45 configFile string

examples/ldapauth/main.go1

1:9package-commentspackage should have a documentation comment

examples/ldapauth/main.go:1:9

1package main
2

internal/common/eventmanager.go1

485:32range-value-addresstaking the address of range value rule can be misleading

internal/common/eventmanager.go:485:32

484 for _, rule := range r.ProviderEvents {
485 if r.checkProviderEventMatch(&rule.Conditions, &params) {
486 if err := rule.CheckActionsConsistency(params.ObjectType); err == nil {

internal/common/clientsmap_test.go1

48:18redundant-conversionconversion from int32 to the identical type is redundant

internal/common/clientsmap_test.go:48:18

47 m.remove(ip2)
48 assert.Equal(t, int32(5), m.getTotal())
49 assert.Equal(t, 4, m.getTotalFrom(ip1))

internal/httpd/oidc.go1

875:3single-case-switchswitch with one case can be replaced by an if statement

internal/httpd/oidc.go:875:3

874 getStructValue := func(outer any, field string) (any, bool) {
875 switch v := outer.(type) {
876 case map[string]any:

internal/common/tlsutils.go1

166:6slice-preallocationpreallocate crls with capacity len(range source) before appending once per iteration

internal/common/tlsutils.go:166:6

165
166 var crls []*x509.RevocationList
167

internal/dataprovider/dataprovider.go1

3440:1task-commentFIXME comment should be resolved or linked to an owned work item

internal/dataprovider/dataprovider.go:3440:1

3439// ValidateFolder returns an error if the folder is not valid
3440// FIXME: this should be defined as Folder struct method
3441func ValidateFolder(folder *vfs.BaseVirtualFolder) error {

examples/ldapauthserver/config/config.go1

50:1top-level-declaration-ordertop-level declarations should be ordered as const, var, type, then func

examples/ldapauthserver/config/config.go:50:1

49
50var conf appConfig
51

internal/common/common_test.go1

1369:15unchecked-type-assertionuse the checked two-result form of the type assertion

internal/common/common_test.go:1369:15

1368 require.NoError(t, err)
1369 cryptFs := fs.(*vfs.CryptFs)
1370 info := vfs.NewFileInfo(name, true, 48, time.Now(), false)

internal/httpd/resetcode.go1

117:48unexported-returnexported function returns an unexported type

internal/httpd/resetcode.go:117:48

116
117func (m *dbResetCodeManager) Get(code string) (*resetCode, error) {
118 session, err := dataprovider.GetSharedSession(code, dataprovider.SessionTypeResetCode)

internal/cmd/resetpwd.go1

100:4unnecessary-formatformatting call has no formatting directive

internal/cmd/resetpwd.go:100:4

99 fmt.Println("")
100 fmt.Printf("Confirm Password: ")
101 confirmPwd, err := term.ReadPassword(int(os.Stdin.Fd()))

internal/jwt/jwt_test.go1

23:34unused-parameterparameter payload is unused

internal/jwt/jwt_test.go:23:34

22
23func (s *failingJoseSigner) Sign(payload []byte) (*jose.JSONWebSignature, error) {
24 return nil, errors.New("sign test error")

internal/common/common_test.go1

76:7unused-receiverreceiver c is unused

internal/common/common_test.go:76:7

75
76func (c *fakeConnection) GetClientVersion() string {
77 return ""

examples/ldapauthserver/logger/logger.go1

65:58use-anyuse any instead of interface{}

examples/ldapauthserver/logger/logger.go:65:58

64// Debug logs at debug level for the specified sender
65func Debug(prefix, requestID string, format string, v ...interface{}) {
66 logger.Debug().

internal/dataprovider/bolt.go1

3061:11use-errors-newreplace fmt.Errorf with errors.New for a static message

internal/dataprovider/bolt.go:3061:11

3060 if bucket == nil {
3061 return fmt.Errorf("unable to find configs bucket")
3062 }

internal/dataprovider/memory.go1

2381:2use-slices-sortuse slices.Sort or slices.SortFunc when possible

internal/dataprovider/memory.go:2381:2

2380 }
2381 sort.Slice(rule.Actions, func(i, j int) bool {
2382 return rule.Actions[i].Order < rule.Actions[j].Order

internal/vfs/s3fs.go1

134:20weak-cryptographydeprecated cryptographic primitive crypto/md5.Sum should not protect new data

internal/vfs/s3fs.go:134:20

133 if len(key) == 32 {
134 md5sumBinary := md5.Sum([]byte(key))
135 fs.sseCustomerKey = base64.StdEncoding.EncodeToString([]byte(key))

internal/acme/acme.go1

569:46add-constantstring literal "/" appears more than twice; define a constant

internal/acme/acme.go:569:46

568 config.CADirURL = c.CAEndpoint
569 config.UserAgent = version.GetServerVersion("/", false)
570

examples/ldapauthserver/httpd/auth.go1

60:29cognitive-complexityfunction has cognitive complexity 12; maximum is 7

examples/ldapauthserver/httpd/auth.go:60:29

59
60func (p *basicAuthProvider) loadUsers() error {
61 if !p.isEnabled() {

internal/dataprovider/dataprovider.go1

3697:6confusing-namingname checkUserAndPubKey differs from CheckUserAndPubKey only by capitalization

internal/dataprovider/dataprovider.go:3697:6

3696
3697func checkUserAndPubKey(user *User, pubKey []byte, isSSHCert bool) (User, string, error) {
3698 err := user.LoadAndApplyGroupSettings()

internal/dataprovider/cachedpassword.go1

52:70confusing-resultsadjacent unnamed results of the same type should be named

internal/dataprovider/cachedpassword.go:52:70

51// CheckCachedUserPassword is an utility method used only in test cases
52func CheckCachedUserPassword(username, password, hash string) (bool, bool) {
53 return cachedUserPasswords.Check(username, password, hash)

internal/vfs/httpfs.go1

207:6constructor-interface-returnNewHTTPFs returns interface Fs although its concrete result is consistently *HTTPFs; return the concrete type

internal/vfs/httpfs.go:207:6

206// NewHTTPFs returns an HTTPFs object that allows to interact with SFTPGo HTTP filesystem backends
207func NewHTTPFs(connectionID, localTempDir, mountPath string, config HTTPFsConfig) (Fs, error) {
208 if localTempDir == "" {

internal/vfs/s3fs.go1

574:3context-cancel-in-loopcancellation deferred inside a loop runs only when the surrounding function returns; cancel before the iteration ends

internal/vfs/s3fs.go:574:3

573 ctx, cancelFn := context.WithDeadline(context.Background(), time.Now().Add(fs.ctxTimeout))
574 defer cancelFn()
575

internal/acme/acme.go1

703:25cyclomatic-complexityfunction complexity is 13; maximum is 10

internal/acme/acme.go:703:25

702
703func (c *Configuration) renewCertificates() error {
704 lockTime, err := c.getLockTime()

examples/OTP/authy/keyint/main.go1

46:3deep-exitprocess-exit calls should be confined to main or init

examples/OTP/authy/keyint/main.go:46:3

45 if result == 1 {
46 os.Exit(0)
47 } else {

internal/httpd/httpd_test.go1

9392:70deprecated-api-usagegolang.org/x/crypto/ssh.InsecureKeyAlgoDSA is deprecated: DSA is only supported at insecure key sizes, and was removed from major implementations.

internal/httpd/httpd_test.go:9392:70

9391
9392 configs.SFTPD.PublicKeyAlgos = append(configs.SFTPD.PublicKeyAlgos, ssh.InsecureKeyAlgoDSA) //nolint:staticcheck
9393 err = dataprovider.UpdateConfigs(&configs, "", "", "")

internal/cmd/portable.go1

170:6discarded-error-resulterror result returned by fmt.Printf is discarded

internal/cmd/portable.go:170:6

169 if err != nil {
170 fmt.Printf("Unable to load WebDAV key pair, cert file %q key file %q error: %v\n",
171 portableWebDAVCert, portableWebDAVKey, err)

examples/ldapauthserver/config/config.go1

98:1doc-comment-perioddocumentation comment should end with punctuation

examples/ldapauthserver/config/config.go:98:1

97
98// GetUIDNumber returns the configured name for the LDAP field to use as UID
99func (l *LDAPConfig) GetUIDNumber() string {

internal/util/util.go1

251:7duration-multiplied-by-durationmultiplying two time.Duration values produces squared time units; multiply a duration by a unitless count

internal/util/util.go:251:7

250 m := d / time.Minute
251 d -= m * time.Minute
252 s := d / time.Second

internal/common/tlsutils.go1

236:3early-returninvert the condition and return early to reduce nesting

internal/common/tlsutils.go:236:3

235 }
236 if rootCAs.AppendCertsFromPEM(crt) {
237 logger.Debug(m.logSender, "", "TLS certificate authority %q successfully loaded", rootCA)

internal/dataprovider/bolt.go1

1655:22error-stringserror string should not be capitalized or end with punctuation

internal/dataprovider/bolt.go:1655:22

1654 if a := bucket.Get([]byte(apiKey.KeyID)); a != nil {
1655 return fmt.Errorf("API key %v already exists", apiKey.KeyID)
1656 }

internal/common/eventmanager_test.go1

1712:2excessive-blank-identifiersassignment discards three or more results; name meaningful results or simplify the return contract

internal/common/eventmanager_test.go:1712:2

1711 assert.Error(t, err)
1712 _, _, _, _, err = getFileWriter(conn, "/path.txt", -1) //nolint:dogsled
1713 assert.Error(t, err)

examples/ldapauthserver/logger/request_logger.go1

14:6exported-declaration-commentexported type should have a comment beginning with its name

examples/ldapauthserver/logger/request_logger.go:14:6

13// It implements chi.middleware.LogFormatter interface
14type StructuredLogger struct {
15 Logger *zerolog.Logger

internal/common/connection.go2

1:1file-length-limitfile has 1949 lines; maximum is 500

internal/common/connection.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//
402:56flag-parameterboolean parameter checkFilePatterns controls function flow

internal/common/connection.go:402:56

401// CreateDir creates a new directory at the specified fsPath
402func (c *BaseConnection) CreateDir(virtualPath string, checkFilePatterns bool) error {
403 if !c.User.HasPerm(dataprovider.PermCreateDirs, path.Dir(virtualPath)) {

examples/ldapauthserver/cmd/serve.go1

1:1formatfile is not formatted

examples/ldapauthserver/cmd/serve.go:1:1

1package cmd
2
  • Fix (safe): run `strider fmt examples/ldapauthserver/cmd/serve.go`

internal/cmd/root.go1

184:6function-lengthfunction has 38 statements and 100 lines; maximum is 50 statements or 75 lines

internal/cmd/root.go:184:6

183
184func addServeFlags(cmd *cobra.Command) {
185 addConfigFlags(cmd)

internal/dataprovider/memory.go1

332:26function-result-limitfunction returns 5 values; maximum is 3

internal/dataprovider/memory.go:332:26

331
332func (p *MemoryProvider) getUsedQuota(username string) (int, int64, int64, int64, error) {
333 p.dbHandle.Lock()

internal/config/config.go1

1248:6get-function-return-valueGet-prefixed function should return a value

internal/config/config.go:1248:6

1247
1248func getFTPDBindingFromEnv(idx int) {
1249 binding := getDefaultFTPDBinding(idx)

internal/common/common.go1

747:7import-shadowingidentifier url shadows an imported package

internal/common/common.go:747:7

746 if strings.HasPrefix(c.StartupHook, "http") {
747 var url *url.URL
748 url, err := url.Parse(c.StartupHook)

internal/common/transferschecker.go1

113:5inefficient-map-lookupreuse the map value obtained by the comma-ok lookup

internal/common/transferschecker.go:113:5

112 if _, ok := usersToFetch[transfer.Username]; !ok {
113 usersToFetch[transfer.Username] = false
114 }

internal/dataprovider/actions.go1

115:23inefficient-sprintffmt.Sprintf is unnecessary for this conversion; use strconv.FormatInt with base 10

internal/dataprovider/actions.go:115:23

114 }
115 q.Add("timestamp", fmt.Sprintf("%d", time.Now().UnixNano()))
116 url.RawQuery = q.Encode()

internal/common/actions_test.go1

149:36insecure-url-schemeURL uses insecure http scheme

internal/common/actions_test.go:149:36

148
149 Config.Actions.Hook = fmt.Sprintf("http://%v/404", httpAddr)
150 status, err = actionHandler.Handle(a)

internal/vfs/vfs.go1

142:9interface-method-limitinterface has 34 methods, exceeding the configured design limit of 10

internal/vfs/vfs.go:142:9

141// Fs defines the interface for filesystem backends
142type Fs interface {
143 Name() string

internal/vfs/cryptfs.go1

129:8max-control-nestingcontrol-flow nesting exceeds 5 levels

internal/vfs/cryptfs.go:129:8

128 if err != nil {
129 if err == io.EOF {
130 err = io.ErrUnexpectedEOF

internal/logger/logger.go1

203:6max-parametersfunction has 12 parameters; maximum is 8

internal/logger/logger.go:203:6

202// TransferLog logs uploads or downloads
203func TransferLog(operation, path, virtualPath string, elapsed int64, size int64, user, connectionID, protocol, localAddr,
204 remoteAddr, ftpMode string, err error,

internal/common/common.go1

1441:6max-public-structsfile declares more than 5 exported structs

internal/common/common.go:1441:6

1440// ActiveQuotaScan defines an active quota scan for a user
1441type ActiveQuotaScan struct {
1442 // Username to which the quota scan refers

internal/acme/acme.go1

123:2modifies-parameterassignment modifies parameter config

internal/acme/acme.go:123:2

122 config.HTTP01Challenge.Port = c.HTTP01Challenge.Port
123 config.TLSALPN01Challenge.Port = 0
124 return config

internal/common/eventmanager.go1

86:31nested-structsmove nested anonymous struct types to named declarations

internal/common/eventmanager.go:86:31

85 // each task could execute multiple actions
86 concurrencyGuard: make(chan struct{}, 200),
87 }

internal/common/connection.go1

1004:5nil-error-returnthis branch proves an error is non-nil but returns nil in an error result

internal/common/connection.go:1004:5

1003 if info, err := c.getInfoForOngoingUpload(fsPath); err == nil {
1004 return info, nil
1005 }

internal/ftpd/server.go1

254:3nil-value-with-nil-errornil payload is returned with a nil error; return a meaningful value or a descriptive error

internal/ftpd/server.go:254:3

253 if !s.binding.isMutualTLSEnabled() {
254 return nil, nil
255 }

internal/common/common.go1

1193:4no-defer-in-loopdefer inside a loop runs at function exit, not iteration exit

internal/common/common.go:1193:4

1192 } else if !isUnauthenticatedFTPUser && !c.isAccessAllowed() {
1193 defer func(conn ActiveConnection) {
1194 err := conn.Disconnect()

internal/dataprovider/dataprovider.go1

1572:4no-else-after-returnremove else and unindent its body after the return

internal/dataprovider/dataprovider.go:1572:4

1571 return util.NewMethodDisabledError(trackQuotaDisabledError)
1572 } else if config.TrackQuota == 2 && !reset && !user.HasTransferQuotaRestrictions() {
1573 return nil

examples/ldapauthserver/cmd/serve.go1

29:6no-initreplace init with explicit initialization

examples/ldapauthserver/cmd/serve.go:29:6

28
29func init() {
30 rootCmd.AddCommand(serveCmd)

internal/ftpd/transfer.go1

91:2no-naked-returnreturn values must be explicit

internal/ftpd/transfer.go:91:2

90 t.HandleThrottle()
91 return
92}

examples/ldapauthserver/cmd/root.go2

45:2no-package-varpackage variables introduce mutable global state

examples/ldapauthserver/cmd/root.go:45:2

44 configDir string
45 configFile string
46 logFilePath string
1:9package-commentspackage should have a documentation comment

examples/ldapauthserver/cmd/root.go:1:9

1package cmd
2

internal/common/eventmanager.go1

745:9range-value-addresstaking the address of range value check can be misleading

internal/common/eventmanager.go:745:9

744
745 fh := &zip.FileHeader{
746 Name: fmt.Sprintf("%s-%s.csv", check.ActionName, check.Username),

internal/common/clientsmap_test.go1

53:18redundant-conversionconversion from int32 to the identical type is redundant

internal/common/clientsmap_test.go:53:18

52 m.remove("unknown")
53 assert.Equal(t, int32(5), m.getTotal())
54 assert.Equal(t, 4, m.getTotalFrom(ip1))

internal/httpd/webadmin.go1

3969:2single-case-switchswitch with one case can be replaced by an if statement

internal/httpd/webadmin.go:3969:2

3968 updatedAction.Options.SetEmptySecretsIfNil()
3969 switch updatedAction.Type {
3970 case dataprovider.ActionTypeHTTP:

internal/common/transferschecker.go1

124:6slice-preallocationpreallocate keys with capacity len(range source) before appending once per iteration

internal/common/transferschecker.go:124:6

123 aggregations := make(map[int][]dataprovider.ActiveTransfer)
124 var keys []uploadAggregationKey
125

internal/dataprovider/dataprovider.go1

3473:1task-commentFIXME comment should be resolved or linked to an owned work item

internal/dataprovider/dataprovider.go:3473:1

3472// ValidateUser returns an error if the user is not valid
3473// FIXME: this should be defined as User struct method
3474func ValidateUser(user *User) error {

internal/acme/acme.go1

171:1top-level-declaration-ordertop-level declarations should be ordered as const, var, type, then func

internal/acme/acme.go:171:1

170// HTTP01Challenge defines the configuration for HTTP-01 challenge type
171type HTTP01Challenge struct {
172 Port int `json:"port" mapstructure:"port"`

internal/common/connection.go1

1013:12unchecked-type-assertionuse the checked two-result form of the type assertion

internal/common/connection.go:1013:12

1012 if convertResult && vfs.IsCryptOsFs(fs) {
1013 info = fs.(*vfs.CryptFs).ConvertFileInfo(info)
1014 }

internal/httpd/webtask.go1

65:45unexported-returnexported function returns an unexported type

internal/httpd/webtask.go:65:45

64
65func (m *memoryTaskManager) Get(ID string) (webTaskData, error) {
66 data, ok := m.tasks.Load(ID)

internal/cmd/rotatelogs_windows.go1

41:5unnecessary-formatformatting call has no formatting directive

internal/cmd/rotatelogs_windows.go:41:5

40 } else {
41 fmt.Printf("Rotate log file signal sent!\r\n")
42 }

internal/logger/slog.go1

39:31unused-parameterparameter ctx is unused

internal/logger/slog.go:39:31

38
39func (l *slogAdapter) Enabled(ctx context.Context, level slog.Level) bool {
40 // Log level is handled by our implementation

internal/common/common_test.go1

84:7unused-receiverreceiver c is unused

internal/common/common_test.go:84:7

83
84func (c *fakeConnection) GetLocalAddress() string {
85 return ""

examples/ldapauthserver/logger/logger.go1

74:57use-anyuse any instead of interface{}

examples/ldapauthserver/logger/logger.go:74:57

73// Info logs at info level for the specified sender
74func Info(prefix, requestID string, format string, v ...interface{}) {
75 logger.Info().

internal/dataprovider/bolt.go1

3079:11use-errors-newreplace fmt.Errorf with errors.New for a static message

internal/dataprovider/bolt.go:3079:11

3078 if bucket == nil {
3079 return fmt.Errorf("unable to find configs bucket")
3080 }

internal/dataprovider/memory.go1

2422:2use-slices-sortuse slices.Sort or slices.SortFunc when possible

internal/dataprovider/memory.go:2422:2

2421 rule.UpdatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
2422 sort.Slice(rule.Actions, func(i, j int) bool {
2423 return rule.Actions[i].Order < rule.Actions[j].Order

internal/vfs/s3fs.go1

139:20weak-cryptographydeprecated cryptographic primitive crypto/md5.Sum should not protect new data

internal/vfs/s3fs.go:139:20

138 keyHash := sha256.Sum256([]byte(key))
139 md5sumBinary := md5.Sum(keyHash[:])
140 fs.sseCustomerKey = base64.StdEncoding.EncodeToString(keyHash[:])

internal/acme/acme.go1

783:15add-constantstring literal "," appears more than twice; define a constant

internal/acme/acme.go:783:15

782
783 delimiter := ","
784 if !strings.Contains(domain, ",") && strings.Contains(domain, " ") {

examples/ldapauthserver/httpd/auth.go1

121:6cognitive-complexityfunction has cognitive complexity 10; maximum is 7

examples/ldapauthserver/httpd/auth.go:121:6

120
121func validateCredentials(r *http.Request) bool {
122 if !httpAuth.isEnabled() {

internal/ftpd/ftpd_test.go1

3246:6confusing-namingname TestSTAT differs from TestStat only by capitalization

internal/ftpd/ftpd_test.go:3246:6

3245
3246func TestSTAT(t *testing.T) {
3247 user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)

internal/dataprovider/cachedpassword.go1

101:74confusing-resultsadjacent unnamed results of the same type should be named

internal/dataprovider/cachedpassword.go:101:74

100// Check returns if the username is found and if the password match
101func (c *credentialsCache) Check(username, password, hash string) (bool, bool) {
102 if username == "" || password == "" || hash == "" {

internal/vfs/osfs.go1

77:6constructor-interface-returnNewOsFs returns interface Fs although its concrete result is consistently *OsFs; return the concrete type

internal/vfs/osfs.go:77:6

76// NewOsFs returns an OsFs object that allows to interact with local Os filesystem
77func NewOsFs(connectionID, rootDir, mountPath string, config *sdk.OSFsConfig) Fs {
78 var readBufferSize, writeBufferSize int

internal/cmd/install_windows.go1

75:6cyclomatic-complexityfunction complexity is 11; maximum is 10

internal/cmd/install_windows.go:75:6

74
75func getCustomServeFlags() []string {
76 result := []string{}

examples/OTP/authy/keyint/main.go1

48:3deep-exitprocess-exit calls should be confined to main or init

examples/OTP/authy/keyint/main.go:48:3

47 } else {
48 os.Exit(1)
49 }

internal/httpd/httpd_test.go1

14219:34deprecated-api-usagegolang.org/x/crypto/ssh.InsecureCertAlgoDSAv01 is deprecated: DSA is only supported at insecure key sizes, and was removed from major implementations.

internal/httpd/httpd_test.go:14219:34

14218 form.Set("sftp_host_key_algos", ssh.KeyAlgoRSA)
14219 form.Add("sftp_host_key_algos", ssh.InsecureCertAlgoDSAv01) //nolint:staticcheck
14220 form.Set("sftp_pub_key_algos", ssh.InsecureKeyAlgoDSA) //nolint:staticcheck

internal/cmd/portable.go1

186:6discarded-error-resulterror result returned by fmt.Printf is discarded

internal/cmd/portable.go:186:6

185 if err != nil {
186 fmt.Printf("Unable to load HTTPS key pair, cert file %q key file %q error: %v\n",
187 portableHTTPSCert, portableHTTPSKey, err)

examples/ldapauthserver/config/config.go1

106:1doc-comment-perioddocumentation comment should end with punctuation

examples/ldapauthserver/config/config.go:106:1

105
106// GetGIDNumber returns the configured name for the LDAP field to use as GID
107func (l *LDAPConfig) GetGIDNumber() string {

internal/config/config.go1

768:3early-returninvert the condition and return early to reduce nesting

internal/config/config.go:768:3

767 // to find sftpgo.{json,yaml, etc..} in any of the search paths
768 if errors.As(err, &viper.ConfigFileNotFoundError{}) {
769 logger.Debug(logSender, "", "no configuration file found")

internal/dataprovider/dataprovider.go1

3600:29error-stringserror string should not be capitalized or end with punctuation

internal/dataprovider/dataprovider.go:3600:29

3599 }
3600 return *user, fmt.Errorf("CN %q does not match username %q", tlsCert.Subject.CommonName, user.Username)
3601 }

internal/common/eventmanager_test.go1

2192:2excessive-blank-identifiersassignment discards three or more results; name meaningful results or simplify the return contract

internal/common/eventmanager_test.go:2192:2

2191 conn := NewBaseConnection("", ProtocolFTP, "", "", u)
2192 _, _, _, _, err = getFileWriter(conn, "/missing/path/file.txt", -1) //nolint:dogsled
2193 assert.Error(t, err)

examples/ldapauthserver/logger/request_logger.go1

26:6exported-declaration-commentexported function or method should have a comment beginning with its name

examples/ldapauthserver/logger/request_logger.go:26:6

25// This structured logger is called by the chi.middleware.Logger handler to log each HTTP request
26func NewStructuredLogger(logger *zerolog.Logger) func(next http.Handler) http.Handler {
27 return middleware.RequestLogger(&StructuredLogger{logger})

internal/common/connection_test.go1

1:1file-length-limitfile has 1598 lines; maximum is 500

internal/common/connection_test.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//

internal/common/connection.go1

697:2flag-parameterboolean parameter createTargetDir controls function flow

internal/common/connection.go:697:2

696func (c *BaseConnection) doRecursiveCopy(virtualSourcePath, virtualTargetPath string, srcInfo os.FileInfo,
697 createTargetDir bool, recursion int,
698) error {

examples/ldapauthserver/config/config.go1

1:1formatfile is not formatted

examples/ldapauthserver/config/config.go:1:1

1package config
2
  • Fix (safe): run `strider fmt examples/ldapauthserver/config/config.go`

internal/command/command_test.go1

25:6function-lengthfunction has 64 statements and 100 lines; maximum is 50 statements or 75 lines

internal/command/command_test.go:25:6

24
25func TestCommandConfig(t *testing.T) {
26 require.Equal(t, defaultTimeout, config.Timeout)

internal/dataprovider/mysql.go1

351:25function-result-limitfunction returns 5 values; maximum is 3

internal/dataprovider/mysql.go:351:25

350
351func (p *MySQLProvider) getUsedQuota(username string) (int, int64, int64, int64, error) {
352 return sqlCommonGetUsedQuota(username, p.dbHandle)

internal/config/config.go1

1410:6get-function-return-valueGet-prefixed function should return a value

internal/config/config.go:1410:6

1409
1410func getWebDAVDBindingFromEnv(idx int) {
1411 binding := defaultWebDAVDBinding

internal/common/common.go1

748:3import-shadowingidentifier url shadows an imported package

internal/common/common.go:748:3

747 var url *url.URL
748 url, err := url.Parse(c.StartupHook)
749 if err != nil {

internal/common/transferschecker.go1

151:6inefficient-map-lookupreuse the map value obtained by the comma-ok lookup

internal/common/transferschecker.go:151:6

150 if _, ok := usersToFetch[transfer.Username]; !ok {
151 usersToFetch[transfer.Username] = false
152 }

internal/ftpd/internal_test.go1

733:12inefficient-sprintffmt.Sprintf is unnecessary for this conversion; use strconv.FormatUint with base 10

internal/ftpd/internal_test.go:733:12

732 mockCC := &mockFTPClientContext{}
733 connID := fmt.Sprintf("%v", mockCC.ID())
734 connection := &Connection{

internal/common/actions_test.go1

222:24insecure-url-schemeURL uses insecure http scheme

internal/common/actions_test.go:222:24

221
222 Config.Actions.Hook = "http://foo\x7f.com/"
223 a.Action = operationUpload

internal/vfs/vfs.go1

180:19interface-method-limitinterface has 35 methods, exceeding the configured design limit of 10

internal/vfs/vfs.go:180:19

179// FsRealPather is a Fs that implements the RealPath method.
180type FsRealPather interface {
181 Fs

internal/logger/logger.go1

231:6max-parametersfunction has 18 parameters; maximum is 8

internal/logger/logger.go:231:6

230// CommandLog logs an SFTP/SCP/SSH command
231func CommandLog(command, path, target, virtualPath, virtualTarget, user, fileMode, connectionID, protocol string,
232 uid, gid int, atime, mtime, sshCommand string, size int64, localAddr, remoteAddr string, elapsed int64,

internal/common/common.go1

1450:6max-public-structsfile declares more than 5 exported structs

internal/common/common.go:1450:6

1449// ActiveVirtualFolderQuotaScan defines an active quota scan for a virtual folder
1450type ActiveVirtualFolderQuotaScan struct {
1451 // folder name to which the quota scan refers

internal/acme/acme.go1

454:2modifies-parameterassignment modifies parameter domain

internal/acme/acme.go:454:2

453func (c *Configuration) loadCertificatesForDomain(domain string) ([]*x509.Certificate, error) {
454 domain = util.SanitizeDomain(domain)
455 acmeLog(logger.LevelDebug, "loading certificates for domain %q", domain)

internal/common/eventmanager.go1

132:25nested-structsmove nested anonymous struct types to named declarations

internal/common/eventmanager.go:132:25

131 schedulesMapping map[string][]cron.EntryID
132 concurrencyGuard chan struct{}
133}

internal/common/connection.go1

1090:4nil-error-returnthis branch proves an error is non-nil but returns nil in an error result

internal/common/connection.go:1090:4

1089 if errors.Is(err, vfs.ErrVfsUnsupported) && Config.SetstatMode == 2 {
1090 return nil
1091 }

internal/ftpd/server.go1

293:2nil-value-with-nil-errornil payload is returned with a nil error; return a meaningful value or a descriptive error

internal/ftpd/server.go:293:2

292
293 return nil, nil
294}

internal/common/protocol_test.go1

722:4no-defer-in-loopdefer inside a loop runs at function exit, not iteration exit

internal/common/protocol_test.go:722:4

721 if assert.NoError(t, err) {
722 defer conn.Close()
723 defer client.Close()

internal/dataprovider/user.go1

935:5no-else-after-returnremove else and unindent its body after the return

internal/dataprovider/user.go:935:5

934 return true
935 } else if len(dir) > len(virtualPath) {
936 if strings.HasPrefix(dir, virtualPath+"/") {

examples/ldapauthserver/config/config.go1

52:6no-initreplace init with explicit initialization

examples/ldapauthserver/config/config.go:52:6

51
52func init() {
53 conf = appConfig{

internal/httpd/file.go1

69:3no-naked-returnreturn values must be explicit

internal/httpd/file.go:69:3

68 err = f.ConvertError(err)
69 return
70 }

examples/ldapauthserver/cmd/root.go1

46:2no-package-varpackage variables introduce mutable global state

examples/ldapauthserver/cmd/root.go:46:2

45 configFile string
46 logFilePath string
47 logMaxSize int

examples/ldapauthserver/cmd/serve.go1

1:9package-commentspackage should have a documentation comment

examples/ldapauthserver/cmd/serve.go:1:9

1package cmd
2

internal/common/eventmanager.go1

1189:25range-value-addresstaking the address of range value virtualPath can be misleading

internal/common/eventmanager.go:1189:25

1188 }
1189 files = append(files, &mail.File{
1190 Name: path.Base(virtualPath),

internal/common/clientsmap_test.go1

58:18redundant-conversionconversion from int32 to the identical type is redundant

internal/common/clientsmap_test.go:58:18

57 m.remove(ip2)
58 assert.Equal(t, int32(4), m.getTotal())
59 assert.Equal(t, 4, m.getTotalFrom(ip1))

internal/config/config.go1

670:7slice-preallocationpreallocate args with capacity len(range source) before appending once per iteration

internal/config/config.go:670:7

669 for _, plugin := range globalConf.PluginsConfig {
670 var args []string
671 for _, arg := range plugin.Args {

internal/dataprovider/eventrule.go1

196:1task-commentTODO comment should be resolved or linked to an owned work item

internal/dataprovider/eventrule.go:196:1

195
196// TODO: replace the copied strings with shared constants
197var (

internal/bundle/bundle.go1

33:1top-level-declaration-ordertop-level declarations should be ordered as const, var, type, then func

internal/bundle/bundle.go:33:1

32//go:embed templates/*
33var templatesFs embed.FS
34

internal/common/defender_test.go1

118:15unchecked-type-assertionuse the checked two-result form of the type assertion

internal/common/defender_test.go:118:15

117
118 defender := d.(*memoryDefender)
119 assert.True(t, defender.IsBanned("172.16.1.1", ProtocolSSH))

internal/httpd/webtask.go1

95:41unexported-returnexported function returns an unexported type

internal/httpd/webtask.go:95:41

94
95func (m *dbTaskManager) Get(ID string) (webTaskData, error) {
96 sess, err := dataprovider.GetSharedSession(ID, dataprovider.SessionTypeWebTask)

internal/cmd/start_windows.go1

59:5unnecessary-formatformatting call has no formatting directive

internal/cmd/start_windows.go:59:5

58 } else {
59 fmt.Printf("Service started!\r\n")
60 }

internal/logger/slog.go1

39:52unused-parameterparameter level is unused

internal/logger/slog.go:39:52

38
39func (l *slogAdapter) Enabled(ctx context.Context, level slog.Level) bool {
40 // Log level is handled by our implementation

internal/common/common_test.go1

88:7unused-receiverreceiver c is unused

internal/common/common_test.go:88:7

87
88func (c *fakeConnection) GetRemoteAddress() string {
89 return ""

examples/ldapauthserver/logger/logger.go1

83:57use-anyuse any instead of interface{}

examples/ldapauthserver/logger/logger.go:83:57

82// Warn logs at warn level for the specified sender
83func Warn(prefix, requestID string, format string, v ...interface{}) {
84 logger.Warn().

internal/dataprovider/bolt.go1

3869:9use-errors-newreplace fmt.Errorf with errors.New for a static message

internal/dataprovider/bolt.go:3869:9

3868 if bucket == nil {
3869 err = fmt.Errorf("unable to find groups bucket, bolt database structure not correcly defined")
3870 }

internal/httpd/webadmin.go1

2336:2use-slices-sortuse slices.Sort or slices.SortFunc when possible

internal/httpd/webadmin.go:2336:2

2335
2336 sort.Slice(result, func(i, j int) bool {
2337 return result[i].Order < result[j].Order

internal/cmd/install_windows.go1

87:27add-constantstring literal "--" appears more than twice; define a constant

internal/cmd/install_windows.go:87:27

86 if logFilePath != defaultLogFile {
87 result = append(result, "--"+logFilePathFlag)
88 result = append(result, logFilePath)

examples/ldapauthserver/httpd/ldapauth.go1

51:6cognitive-complexityfunction has cognitive complexity 23; maximum is 7

examples/ldapauthserver/httpd/ldapauth.go:51:6

50
51func checkSFTPGoUserAuth(w http.ResponseWriter, r *http.Request) {
52 r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)

internal/ftpd/internal_test.go1

378:20confusing-namingname IsAtomicUploadSupported differs from isAtomicUploadSupported only by capitalization

internal/ftpd/internal_test.go:378:20

377// IsAtomicUploadSupported returns true if atomic upload is supported
378func (fs MockOsFs) IsAtomicUploadSupported() bool {
379 return fs.isAtomicUploadSupported

internal/dataprovider/dataprovider.go1

1605:49confusing-resultsadjacent unnamed results of the same type should be named

internal/dataprovider/dataprovider.go:1605:49

1604// GetUsedQuota returns the used quota for the given SFTPGo user.
1605func GetUsedQuota(username string) (int, int64, int64, int64, error) {
1606 if config.TrackQuota == 0 {

internal/vfs/s3fs.go1

91:6constructor-interface-returnNewS3Fs returns interface Fs although its concrete result is consistently *S3Fs; return the concrete type

internal/vfs/s3fs.go:91:6

90// object storage
91func NewS3Fs(connectionID, localTempDir, mountPath string, s3Config S3FsConfig) (Fs, error) {
92 if localTempDir == "" {

internal/cmd/serve.go1

89:6cyclomatic-complexityfunction complexity is 22; maximum is 10

internal/cmd/serve.go:89:6

88
89func checkServeParamsFromEnvFiles(configDir string) { //nolint:gocyclo
90 // The logger is not yet initialized here, we have no way to report errors.

examples/ldapauth/main.go1

46:2deep-exitprocess-exit calls should be confined to main or init

examples/ldapauth/main.go:46:2

45 fmt.Printf("%v\n", string(resp))
46 os.Exit(1)
47}

internal/httpd/httpd_test.go1

14220:33deprecated-api-usagegolang.org/x/crypto/ssh.InsecureKeyAlgoDSA is deprecated: DSA is only supported at insecure key sizes, and was removed from major implementations.

internal/httpd/httpd_test.go:14220:33

14219 form.Add("sftp_host_key_algos", ssh.InsecureCertAlgoDSAv01) //nolint:staticcheck
14220 form.Set("sftp_pub_key_algos", ssh.InsecureKeyAlgoDSA) //nolint:staticcheck
14221 form.Set("form_action", "sftp_submit")

internal/cmd/portable.go1

195:6discarded-error-resulterror result returned by fmt.Printf is discarded

internal/cmd/portable.go:195:6

194 if err != nil {
195 fmt.Printf("Unable to read password file %q: %v", portablePasswordFile, err)
196 os.Exit(1)

examples/ldapauthserver/config/config.go1

114:1doc-comment-perioddocumentation comment should end with punctuation

examples/ldapauthserver/config/config.go:114:1

113
114// GetPublicKey returns the configured name for the LDAP field to use as public keys
115func (l *LDAPConfig) GetPublicKey() string {

internal/dataprovider/dataprovider.go3

3755:9early-returninvert the condition and return early to reduce nesting

internal/dataprovider/dataprovider.go:3755:9

3754 crypter = md5_crypt.New()
3755 } else if strings.HasPrefix(user.Password, md5cryptApr1PwdPrefix) {
3756 crypter = apr1_crypt.New()
3602:28error-stringserror string should not be capitalized or end with punctuation

internal/dataprovider/dataprovider.go:3602:28

3601 }
3602 return *user, errors.New("TLS certificate is not valid")
3603 default:
2983:3excessive-blank-identifiersassignment discards three or more results; name meaningful results or simplify the return contract

internal/dataprovider/dataprovider.go:2983:3

2982 }
2983 out, _, _, _, err := ssh.ParseAuthorizedKey([]byte(key))
2984 if err != nil {

examples/ldapauthserver/utils/utils.go1

11:6exported-declaration-commentexported function or method should have a comment beginning with its name

examples/ldapauthserver/utils/utils.go:11:6

10// user input, with a directory
11func IsFileInputValid(fileInput string) bool {
12 cleanInput := filepath.Clean(fileInput)

internal/common/defender_test.go1

1:1file-length-limitfile has 644 lines; maximum is 500

internal/common/defender_test.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//

internal/common/connection.go1

816:2flag-parameterboolean parameter checkParentDestination controls function flow

internal/common/connection.go:816:2

815func (c *BaseConnection) renameInternal(virtualSourcePath, virtualTargetPath string, //nolint:gocyclo
816 checkParentDestination bool, checks int,
817) error {

examples/ldapauthserver/httpd/auth.go1

1:1formatfile is not formatted

examples/ldapauthserver/httpd/auth.go:1:1

1package httpd
2
  • Fix (safe): run `strider fmt examples/ldapauthserver/httpd/auth.go`

internal/common/actions_test.go1

38:6function-lengthfunction has 45 statements and 87 lines; maximum is 50 statements or 75 lines

internal/common/actions_test.go:38:6

37
38func TestNewActionNotification(t *testing.T) {
39 user := dataprovider.User{

internal/dataprovider/pgsql.go1

398:25function-result-limitfunction returns 5 values; maximum is 3

internal/dataprovider/pgsql.go:398:25

397
398func (p *PGSQLProvider) getUsedQuota(username string) (int, int64, int64, int64, error) {
399 return sqlCommonGetUsedQuota(username, p.dbHandle)

internal/config/config.go1

1834:6get-function-return-valueGet-prefixed function should return a value

internal/config/config.go:1834:6

1833
1834func getHTTPDBindingFromEnv(idx int) { //nolint:gocyclo
1835 binding := getDefaultHTTPBinding(idx)

internal/common/common.go1

788:7import-shadowingidentifier url shadows an imported package

internal/common/common.go:788:7

787 if strings.HasPrefix(c.PostDisconnectHook, "http") {
788 var url *url.URL
789 url, err := url.Parse(c.PostDisconnectHook)

internal/dataprovider/cacheduser.go1

73:3inefficient-map-lookupreuse the map value obtained by the comma-ok lookup

internal/dataprovider/cacheduser.go:73:3

72 cachedUser.User.LastLogin = util.GetTimeAsMsSinceEpoch(time.Now())
73 cache.users[username] = cachedUser
74 }

internal/ftpd/internal_test.go1

795:12inefficient-sprintffmt.Sprintf is unnecessary for this conversion; use strconv.FormatUint with base 10

internal/ftpd/internal_test.go:795:12

794 mockCC := &mockFTPClientContext{}
795 connID := fmt.Sprintf("%v", mockCC.ID())
796 fs := vfs.NewOsFs(connID, user.HomeDir, "", nil)

internal/common/common_test.go1

1272:23insecure-url-schemeURL uses insecure http scheme

internal/common/common_test.go:1272:23

1271
1272 Config.StartupHook = "http://foo\x7f.com/startup"
1273 assert.Error(t, Config.ExecuteStartupHook())

internal/vfs/vfs.go1

186:19interface-method-limitinterface has 35 methods, exceeding the configured design limit of 10

internal/vfs/vfs.go:186:19

185// FsFileCopier is a Fs that implements the CopyFile method.
186type FsFileCopier interface {
187 Fs

internal/service/service_portable.go1

39:19max-parametersfunction has 11 parameters; maximum is 8

internal/service/service_portable.go:39:19

38// StartPortableMode starts the service in portable mode
39func (s *Service) StartPortableMode(sftpdPort, ftpPort, webdavPort, httpPort int, enabledSSHCommands []string,
40 ftpsCert, ftpsKey, webDavCert, webDavKey, httpsCert, httpsKey string) error {

internal/common/common.go1

1458:6max-public-structsfile declares more than 5 exported structs

internal/common/common.go:1458:6

1457// ActiveScans holds the active quota scans
1458type ActiveScans struct {
1459 sync.RWMutex

internal/acme/acme.go1

614:2modifies-parameterassignment modifies parameter domain

internal/acme/acme.go:614:2

613 }
614 domain = util.SanitizeDomain(domain)
615 err = os.WriteFile(c.getCrtPath(domain), cert.Certificate, 0600)

internal/common/eventmanager.go1

137:24nested-structsmove nested anonymous struct types to named declarations

internal/common/eventmanager.go:137:24

136 activeHooks.Add(1)
137 r.concurrencyGuard <- struct{}{}
138}

internal/common/dataretention.go1

197:4nil-error-returnthis branch proves an error is non-nil but returns nil in an error result

internal/common/dataretention.go:197:4

196 c.conn.Log(logger.LevelDebug, "folder %q does not exist, retention check skipped", folderPath)
197 return nil
198 }

internal/httpclient/httpclient.go1

122:3nil-value-with-nil-errornil payload is returned with a nil error; return a meaningful value or a descriptive error

internal/httpclient/httpclient.go:122:3

121 if len(c.CACertificates) == 0 {
122 return nil, nil
123 }

internal/common/protocol_test.go1

723:4no-defer-in-loopdefer inside a loop runs at function exit, not iteration exit

internal/common/protocol_test.go:723:4

722 defer conn.Close()
723 defer client.Close()
724

internal/httpd/webadmin.go1

3165:4no-else-after-returnremove else and unindent its body after the return

internal/httpd/webadmin.go:3165:4

3164 return
3165 } else if err != nil {
3166 s.renderInternalServerErrorPage(w, r, err)

examples/ldapauthserver/utils/version.go1

18:6no-initreplace init with explicit initialization

examples/ldapauthserver/utils/version.go:18:6

17
18func init() {
19 versionInfo = VersionInfo{

internal/httpd/file.go1

72:2no-naked-returnreturn values must be explicit

internal/httpd/file.go:72:2

71 f.HandleThrottle()
72 return
73}

examples/ldapauthserver/cmd/root.go1

47:2no-package-varpackage variables introduce mutable global state

examples/ldapauthserver/cmd/root.go:47:2

46 logFilePath string
47 logMaxSize int
48 logMaxBackups int

examples/ldapauthserver/config/config.go1

1:9package-commentspackage should have a documentation comment

examples/ldapauthserver/config/config.go:1:9

1package config
2

internal/common/eventmanager.go1

1721:34range-value-addresstaking the address of range value user can be misleading

internal/common/eventmanager.go:1721:34

1720 if params.sender == "" {
1721 if !checkUserConditionOptions(&user, &conditions) {
1722 eventManagerLog(logger.LevelDebug, "skipping fs delete for user %s, condition options don't match",

internal/common/clientsmap_test.go1

65:18redundant-conversionconversion from int32 to the identical type is redundant

internal/common/clientsmap_test.go:65:18

64 m.remove(ip1)
65 assert.Equal(t, int32(1), m.getTotal())
66 assert.Equal(t, 1, m.getTotalFrom(ip1))

internal/dataprovider/bolt.go1

914:9slice-preallocationpreallocate folders with capacity len(range source) before appending once per iteration

internal/dataprovider/bolt.go:914:9

913 if len(user.VirtualFolders) > 0 {
914 var folders []vfs.VirtualFolder
915 for idx := range user.VirtualFolders {

internal/dataprovider/iplist.go1

243:2task-commentTODO comment should be resolved or linked to an owned work item

internal/dataprovider/iplist.go:243:2

242 }
243 // TODO: to remove when the in memory ranger switch to netip
244 _, _, err = net.ParseCIDR(e.IPOrNet)

internal/cmd/ping.go1

54:1top-level-declaration-ordertop-level declarations should be ordered as const, var, type, then func

internal/cmd/ping.go:54:1

53
54var (
55 pingCmd = &cobra.Command{

internal/common/defender_test.go1

291:15unchecked-type-assertionuse the checked two-result form of the type assertion

internal/common/defender_test.go:291:15

290
291 defender := d.(*memoryDefender)
292

internal/logger/slog.go1

32:55unexported-returnexported function returns an unexported type

internal/logger/slog.go:32:55

31// NewSlogAdapter creates a slog.Handler adapter
32func NewSlogAdapter(sender string, attrs []slog.Attr) *slogAdapter {
33 return &slogAdapter{

internal/cmd/stop_windows.go1

41:5unnecessary-formatformatting call has no formatting directive

internal/cmd/stop_windows.go:41:5

40 } else {
41 fmt.Printf("Service stopped!\r\n")
42 }

internal/logger/slog.go1

44:30unused-parameterparameter ctx is unused

internal/logger/slog.go:44:30

43
44func (l *slogAdapter) Handle(ctx context.Context, r slog.Record) error {
45 var ev *zerolog.Event

internal/common/connection.go1

1031:7unused-receiverreceiver c is unused

internal/common/connection.go:1031:7

1030
1031func (c *BaseConnection) ignoreSetStat(fs vfs.Fs) bool {
1032 if Config.SetstatMode == 1 {

examples/ldapauthserver/logger/logger.go1

92:58use-anyuse any instead of interface{}

examples/ldapauthserver/logger/logger.go:92:58

91// Error logs at error level for the specified sender
92func Error(prefix, requestID string, format string, v ...interface{}) {
93 logger.Error().

internal/dataprovider/bolt.go1

3878:9use-errors-newreplace fmt.Errorf with errors.New for a static message

internal/dataprovider/bolt.go:3878:9

3877 if bucket == nil {
3878 err = fmt.Errorf("unable to find roles bucket, bolt database structure not correcly defined")
3879 }

internal/vfs/s3fs.go1

1107:2use-slices-sortuse slices.Sort or slices.SortFunc when possible

internal/vfs/s3fs.go:1107:2

1106
1107 sort.Slice(completedParts, func(i, j int) bool {
1108 getPartNumber := func(number *int32) int32 {

internal/cmd/portable.go1

319:69add-constantstring literal `0 means a random unprivileged port, < 0 disabled` appears more than twice; define a constant

internal/cmd/portable.go:319:69

318< 0 disabled`)
319 portableCmd.Flags().IntVar(&portableWebDAVPort, "webdav-port", -1, `0 means a random unprivileged port,
320< 0 disabled`)

internal/acme/acme.go1

181:27cognitive-complexityfunction has cognitive complexity 8; maximum is 7

internal/acme/acme.go:181:27

180
181func (c *HTTP01Challenge) validate() error {
182 if !c.isEnabled() {

internal/mfa/totp.go1

51:2confusing-namingname algo differs from Algo only by capitalization

internal/mfa/totp.go:51:2

50 Algo TOTPHMacAlgo `json:"algo" mapstructure:"algo"`
51 algo otp.Algorithm
52}

internal/dataprovider/dataprovider.go1

1605:56confusing-resultsadjacent unnamed results of the same type should be named

internal/dataprovider/dataprovider.go:1605:56

1604// GetUsedQuota returns the used quota for the given SFTPGo user.
1605func GetUsedQuota(username string) (int, int64, int64, int64, error) {
1606 if config.TrackQuota == 0 {

internal/vfs/sftpfs.go1

318:6constructor-interface-returnNewSFTPFs returns interface Fs although its concrete result is consistently *SFTPFs; return the concrete type

internal/vfs/sftpfs.go:318:6

317// NewSFTPFs returns an SFTPFs object that allows to interact with an SFTP server
318func NewSFTPFs(connectionID, mountPath, localTempDir string, forbiddenSelfUsernames []string, config SFTPFsConfig) (Fs, error) {
319 if localTempDir == "" {

internal/command/command.go1

91:17cyclomatic-complexityfunction complexity is 14; maximum is 10

internal/command/command.go:91:17

90// Initialize configures commands
91func (c Config) Initialize() error {
92 if c.Timeout < minTimeout || c.Timeout > maxTimeout {

examples/ldapauth/main.go1

64:2deep-exitprocess-exit calls should be confined to main or init

examples/ldapauth/main.go:64:2

63 fmt.Printf("%v\n", string(resp))
64 os.Exit(0)
65}

internal/httpd/httpd_test.go1

14233:33deprecated-api-usagegolang.org/x/crypto/ssh.InsecureKeyAlgoDSA is deprecated: DSA is only supported at insecure key sizes, and was removed from major implementations.

internal/httpd/httpd_test.go:14233:33

14232 form.Add("sftp_host_key_algos", ssh.CertAlgoRSAv01)
14233 form.Set("sftp_pub_key_algos", ssh.InsecureKeyAlgoDSA) //nolint:staticcheck
14234 form.Set("sftp_kex_algos", "diffie-hellman-group18-sha512")

internal/cmd/resetpwd.go1

93:4discarded-error-resulterror result returned by fmt.Printf is discarded

internal/cmd/resetpwd.go:93:4

92 }
93 fmt.Printf("Enter Password: ")
94 pwd, err := term.ReadPassword(int(os.Stdin.Fd()))

examples/ldapauthserver/config/config.go1

122:1doc-comment-perioddocumentation comment should end with punctuation

examples/ldapauthserver/config/config.go:122:1

121
122// GetHTTPDConfig returns the configuration for the HTTP server
123func GetHTTPDConfig() HTTPDConfig {

internal/dataprovider/dataprovider.go2

3793:9early-returninvert the condition and return early to reduce nesting

internal/dataprovider/dataprovider.go:3793:9

3792 hashFunc = sha512.New
3793 } else if strings.HasPrefix(hashedPassword, pbkdf2SHA1Prefix) {
3794 hashFunc = sha1.New
4019:32error-stringserror string should not be capitalized or end with punctuation

internal/dataprovider/dataprovider.go:4019:32

4018 user.Username)
4019 return answers, errors.New("TOTP not enabled for SSH protocol")
4020 }

internal/mfa/mfa_test.go1

80:2excessive-blank-identifiersassignment discards three or more results; name meaningful results or simplify the return contract

internal/mfa/mfa_test.go:80:2

79 // now generate some secrets and validate some passcodes
80 _, _, _, err = GenerateTOTPSecret("", "") //nolint:dogsled
81 assert.Error(t, err)

examples/ldapauthserver/utils/utils.go1

21:6exported-declaration-commentexported function or method should have a comment beginning with its name

examples/ldapauthserver/utils/utils.go:21:6

20// if a matching prefix is found
21func IsStringPrefixInSlice(obj string, list []string) bool {
22 for _, v := range list {

internal/common/eventmanager.go1

1:1file-length-limitfile has 2948 lines; maximum is 500

internal/common/eventmanager.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//

internal/common/connection.go1

965:71flag-parameterboolean parameter checkFilePatterns controls function flow

internal/common/connection.go:965:71

964
965func (c *BaseConnection) doStatInternal(virtualPath string, mode int, checkFilePatterns,
966 convertResult bool,

examples/ldapauthserver/httpd/httpd.go1

1:1formatfile is not formatted

examples/ldapauthserver/httpd/httpd.go:1:1

1package httpd
2
  • Fix (safe): run `strider fmt examples/ldapauthserver/httpd/httpd.go`

internal/common/common.go1

191:6function-lengthfunction has 59 statements and 77 lines; maximum is 50 statements or 75 lines

internal/common/common.go:191:6

190// Initialize sets the common configuration
191func Initialize(c Configuration, isShared int) error {
192 isShuttingDown.Store(false)

internal/dataprovider/sqlcommon.go1

1279:6function-result-limitfunction returns 5 values; maximum is 3

internal/dataprovider/sqlcommon.go:1279:6

1278
1279func sqlCommonGetUsedQuota(username string, dbHandle *sql.DB) (int, int64, int64, int64, error) {
1280 ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)

internal/config/config.go1

1967:6get-function-return-valueGet-prefixed function should return a value

internal/config/config.go:1967:6

1966
1967func getHTTPClientCertificatesFromEnv(idx int) {
1968 tlsCert := httpclient.TLSKeyPair{}

internal/common/common.go1

789:3import-shadowingidentifier url shadows an imported package

internal/common/common.go:789:3

788 var url *url.URL
789 url, err := url.Parse(c.PostDisconnectHook)
790 if err != nil {

internal/dataprovider/cacheduser.go1

110:4inefficient-map-lookupreuse the map value obtained by the comma-ok lookup

internal/dataprovider/cacheduser.go:110:4

109 cachedUser.User = user
110 cache.users[user.Username] = cachedUser
111 } else {

internal/ftpd/internal_test.go1

826:12inefficient-sprintffmt.Sprintf is unnecessary for this conversion; use strconv.FormatUint with base 10

internal/ftpd/internal_test.go:826:12

825 mockCC := &mockFTPClientContext{}
826 connID := fmt.Sprintf("%v", mockCC.ID())
827 connection := &Connection{

internal/common/common_test.go1

1275:23insecure-url-schemeURL uses insecure http scheme

internal/common/common_test.go:1275:23

1274
1275 Config.StartupHook = "http://invalid:5678/"
1276 assert.Error(t, Config.ExecuteStartupHook())

internal/vfs/vfs.go1

1310:6max-parametersfunction has 9 parameters; maximum is 8

internal/vfs/vfs.go:1310:6

1309
1310func moveAcrossRoots(fsSrc, fsDst Fs, source, target string, info os.FileInfo, checks, uid, gid, recursion int) (int, int64, error) { //nolint:gocyclo
1311 var numFiles int

internal/dataprovider/admin.go1

237:6max-public-structsfile declares more than 5 exported structs

internal/dataprovider/admin.go:237:6

236// Admin defines a SFTPGo admin
237type Admin struct {
238 // Database unique identifier

internal/acme/acme.go1

642:2modifies-parameterassignment modifies parameter domain

internal/acme/acme.go:642:2

641func (c *Configuration) hasCertificates(domain string) (bool, error) {
642 domain = util.SanitizeDomain(domain)
643 if _, err := os.Stat(c.getCrtPath(domain)); err != nil {

internal/dataprovider/actions.go1

60:38nested-structsmove nested anonymous struct types to named declarations

internal/dataprovider/actions.go:60:38

59var (
60 actionsConcurrencyGuard = make(chan struct{}, 100)
61 reservedUsers = []string{ActionExecutorSelf, ActionExecutorSystem}

internal/ftpd/ftpd.go1

351:4nil-error-returnthis branch proves an error is non-nil but returns nil in an error result

internal/ftpd/ftpd.go:351:4

350 logger.Error(logSender, "", "unable to load acme cert file %q: %v", crt, err)
351 return nil
352 }

internal/plugin/plugin.go1

111:2nil-value-with-nil-errornil payload is returned with a nil error; return a meaningful value or a descriptive error

internal/plugin/plugin.go:111:2

110 }
111 return nil, nil
112}

internal/common/protocol_test.go1

1318:4no-defer-in-loopdefer inside a loop runs at function exit, not iteration exit

internal/common/protocol_test.go:1318:4

1317 if assert.NoError(t, err) {
1318 defer conn.Close()
1319 defer client.Close()

internal/httpd/webadmin.go1

3519:4no-else-after-returnremove else and unindent its body after the return

internal/httpd/webadmin.go:3519:4

3518 return
3519 } else if err != nil {
3520 s.renderInternalServerErrorPage(w, r, err)

internal/bundle/bundle.go1

28:6no-initreplace init with explicit initialization

internal/bundle/bundle.go:28:6

27
28func init() {
29 version.AddFeature("+bundle")

internal/httpd/file.go1

94:3no-naked-returnreturn values must be explicit

internal/httpd/file.go:94:3

93 err = f.ConvertError(err)
94 return
95 }

examples/ldapauthserver/cmd/root.go1

48:2no-package-varpackage variables introduce mutable global state

examples/ldapauthserver/cmd/root.go:48:2

47 logMaxSize int
48 logMaxBackups int
49 logMaxAge int

examples/ldapauthserver/httpd/auth.go1

1:9package-commentspackage should have a documentation comment

examples/ldapauthserver/httpd/auth.go:1:9

1package httpd
2

internal/common/eventmanager.go1

1780:34range-value-addresstaking the address of range value user can be misleading

internal/common/eventmanager.go:1780:34

1779 if params.sender == "" {
1780 if !checkUserConditionOptions(&user, &conditions) {
1781 eventManagerLog(logger.LevelDebug, "skipping fs mkdir for user %s, condition options don't match",

internal/common/clientsmap_test.go1

70:18redundant-conversionconversion from int32 to the identical type is redundant

internal/common/clientsmap_test.go:70:18

69 m.remove(ip1)
70 assert.Equal(t, int32(0), m.getTotal())
71 assert.Equal(t, 0, m.getTotalFrom(ip1))

internal/dataprovider/bolt.go1

970:10slice-preallocationpreallocate folders with capacity len(range source) before appending once per iteration

internal/dataprovider/bolt.go:970:10

969 if needFolders && len(user.VirtualFolders) > 0 {
970 var folders []vfs.VirtualFolder
971 for idx := range user.VirtualFolders {

internal/dataprovider/user.go1

125:1task-commentTODO comment should be resolved or linked to an owned work item

internal/dataprovider/user.go:125:1

124// UserFilters defines additional restrictions for a user
125// TODO: rename to UserOptions in v3
126type UserFilters struct {

internal/common/actions.go1

60:1top-level-declaration-ordertop-level declarations should be ordered as const, var, type, then func

internal/common/actions.go:60:1

59// ProtocolActions defines the action to execute on file operations and SSH commands
60type ProtocolActions struct {
61 // Valid values are download, upload, pre-delete, delete, rename, ssh_cmd. Empty slice to disable

internal/common/defenderdb_test.go1

86:15unchecked-type-assertionuse the checked two-result form of the type assertion

internal/common/defenderdb_test.go:86:15

85 assert.NoError(t, err)
86 defender := d.(*dbDefender)
87 assert.True(t, defender.IsBanned("172.16.1.1", ProtocolFTP))

internal/vfs/sftpfs.go1

1186:77unexported-returnexported function returns an unexported type

internal/vfs/sftpfs.go:1186:77

1185
1186func (c *sftpConnectionsCache) Get(config *SFTPFsConfig, sessionID string) (*sftpConnection, error) {
1187 partition := 0

internal/cmd/uninstall_windows.go1

41:5unnecessary-formatformatting call has no formatting directive

internal/cmd/uninstall_windows.go:41:5

40 } else {
41 fmt.Printf("Service uninstalled\r\n")
42 }

internal/service/service_windows.go1

107:34unused-parameterparameter args is unused

internal/service/service_windows.go:107:34

106
107func (s *WindowsService) Execute(args []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (bool, uint32) {
108 changes <- svc.Status{State: svc.StartPending}

internal/common/connection.go1

1912:7unused-receiverreceiver l is unused

internal/common/connection.go:1912:7

1911
1912func (l *DirListerAt) convertError(err error) error {
1913 if errors.Is(err, io.EOF) {

examples/ldapauthserver/logger/logger.go1

101:41use-anyuse any instead of interface{}

examples/ldapauthserver/logger/logger.go:101:41

100// DebugToConsole logs at debug level to stdout
101func DebugToConsole(format string, v ...interface{}) {
102 consoleLogger.Debug().Msg(fmt.Sprintf(format, v...))

internal/dataprovider/bolt.go1

3887:9use-errors-newreplace fmt.Errorf with errors.New for a static message

internal/dataprovider/bolt.go:3887:9

3886 if bucket == nil {
3887 err = fmt.Errorf("unable to find IP lists bucket, bolt database structure not correcly defined")
3888 }

internal/vfs/s3fs.go1

1230:2use-slices-sortuse slices.Sort or slices.SortFunc when possible

internal/vfs/s3fs.go:1230:2

1229 }
1230 sort.Slice(completedParts, func(i, j int) bool {
1231 getPartNumber := func(number *int32) int32 {

internal/cmd/portable.go1

413:75add-constantstring literal `Allows to restrict access to the virtual folder identified by this prefix and its contents` appears more than twice; define a constant

internal/cmd/portable.go:413:75

412container setting`)
413 portableCmd.Flags().StringVar(&portableAzKeyPrefix, "az-key-prefix", "", `Allows to restrict access to the
414virtual folder identified by this

internal/acme/acme.go1

239:25cognitive-complexityfunction has cognitive complexity 10; maximum is 7

internal/acme/acme.go:239:25

238// Initialize validates and initialize the configuration
239func (c *Configuration) Initialize(configDir string) error {
240 c.checkDomains()

internal/sftpd/internal_test.go1

122:20confusing-namingname IsAtomicUploadSupported differs from isAtomicUploadSupported only by capitalization

internal/sftpd/internal_test.go:122:20

121// IsAtomicUploadSupported returns true if atomic upload is supported
122func (fs MockOsFs) IsAtomicUploadSupported() bool {
123 return fs.isAtomicUploadSupported

internal/dataprovider/dataprovider.go1

2137:52confusing-resultsadjacent unnamed results of the same type should be named

internal/dataprovider/dataprovider.go:2137:52

2136// group settings applied
2137func GetUserVariants(username, role string) (User, User, error) {
2138 username = config.convertName(username)

internal/vfs/vfs.go1

931:6constructor-interface-returnNewPipeWriter returns interface PipeWriter although its concrete result is consistently *pipeWriter; return the concrete type

internal/vfs/vfs.go:931:6

930// NewPipeWriter initializes a new PipeWriter
931func NewPipeWriter(w pipeWriterAt) PipeWriter {
932 return &pipeWriter{

internal/common/common.go1

191:6cyclomatic-complexityfunction complexity is 15; maximum is 10

internal/common/common.go:191:6

190// Initialize sets the common configuration
191func Initialize(c Configuration, isShared int) error {
192 isShuttingDown.Store(false)

examples/ldapauthserver/cmd/root.go1

72:3deep-exitprocess-exit calls should be confined to main or init

examples/ldapauthserver/cmd/root.go:72:3

71 fmt.Println(err)
72 os.Exit(1)
73 }

internal/httpd/httpd_test.go1

14251:51deprecated-api-usagegolang.org/x/crypto/ssh.InsecureKeyAlgoDSA is deprecated: DSA is only supported at insecure key sizes, and was removed from major implementations.

internal/httpd/httpd_test.go:14251:51

14250 assert.Len(t, configs.SFTPD.PublicKeyAlgos, 1)
14251 assert.Contains(t, configs.SFTPD.PublicKeyAlgos, ssh.InsecureKeyAlgoDSA) //nolint:staticcheck
14252 assert.Len(t, configs.SFTPD.KexAlgorithms, 1)

internal/cmd/resetpwd.go1

99:4discarded-error-resulterror result returned by fmt.Println is discarded

internal/cmd/resetpwd.go:99:4

98 }
99 fmt.Println("")
100 fmt.Printf("Confirm Password: ")

examples/ldapauthserver/config/config.go1

127:1doc-comment-perioddocumentation comment should end with punctuation

examples/ldapauthserver/config/config.go:127:1

126
127// GetLDAPConfig returns LDAP related settings
128func GetLDAPConfig() LDAPConfig {

internal/dataprovider/user.go1

224:3early-returninvert the condition and return early to reduce nesting

internal/dataprovider/user.go:224:3

223 }
224 if fs.IsNotExist(err) {
225 err = fs.Mkdir(fsPath)

internal/dataprovider/eventrule.go1

1831:23error-stringserror string should not be capitalized or end with punctuation

internal/dataprovider/eventrule.go:1831:23

1830 if r.Trigger != EventTriggerIDPLogin {
1831 return errors.New("IDP account check action is only supported for IDP login trigger")
1832 }

internal/sftpd/internal_test.go1

1861:2excessive-blank-identifiersassignment discards three or more results; name meaningful results or simplify the return contract

internal/sftpd/internal_test.go:1861:2

1860 sshCert := []byte(`ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg4+hKHVPKv183MU/Q7XD/mzDBFSc2YY3eraltxLMGJo0AAAADAQABAAABAQCe6jMoy1xCQgiZkZJ7gi6NLj4uRqz2OaUGK/OJYZTfBqK+SlS9iymAluHu9K+cc4+0qxx0gn7dRTJWINSgzvca6ayYe995EKgD1hE5krh9BH0bRrXB+hGqyslcZOgLNO+v8jYojClQbRtET2tS+xb4k33GCuL5wgla2790ZgOQgs7huQUjG0S8c1W+EYt6fI4cWE/DeEBnv9sqryS8rOb0PbM6WUd7XBadwySFWYQUX0ei56GNt12Z4gADEGlFQV/OnV0PvnTcAMGUl0rfToPgJ4jgogWKoTVWuZ9wyA/x+2LRLRvgm2a969ig937/AH0i0Wq+FzqfK7EXQ99Yf5K/AAAAAAAAAAAAAAACAAAAFGhvc3QuZXhhbXBsZS5jb20ta2V5AAAAFAAAABBob3N0LmV4YW1wbGUuY29tAAAAAGXEzYAAAAAAd8sP4wAAAAAAAAAAAAAAAAAAARcAAAAHc3NoLXJzYQAAAAMBAAEAAAEBAL4PXUPSERufZWCW/hhEnylk3IeMgaa+2HcNY5Cur77a8fYy6OYZAPF+vhJUT0akwGUpTeXAZumAgHECDrJlw1J+jo9ZVT0AKDo0wU77IzNzYxob7+dpB02NJ7DLAXmPauQ07Zc5pWJFVKtmuh7YH9pjYtNXSMOXye7k06PBGzX+ztIt7nPWvD9fR2mZeTSoljeBCGZHwdlnV2ESQlQbBoEI93RPxqxJh/UCDatQPhpDbyverr2ZvB9Y45rqsx6ZVmu5RXl3MfBU1U21W/4ia2di3PybyD4rSmVoam0efcqxo6cBKSHe26OFoTuS9zgdH0iCWL37vqOFmJ7eH91M3nMAAAEUAAAADHJzYS1zaGEyLTI1NgAAAQA/ByIegNZYJRRl413S/8LxGvTZnbxsPwaluoJ/54niGZV9P28THz7d9jXfSHPjalhH93jNPfTYXvI4opnDC37ua1Nu8KKfk40IWXnnDdZLWraUxEidIzhmfVtz8kGdGoFQ8H0EzubL7zKNOTlfSfOoDlmQVOuxT/+eh2mEp4ri0/+8J1mLfLBr8tREX0/iaNjK+RKdcyTMicKursAYMCDdu8vlaphxea+ocyHM9izSX/l33t44V13ueTqIOh2Zbl2UE2k+jk+0dc1CmV0SEoiWiIyt8TRM4yQry1vPlQLsrf28sYM/QMwnhCVhyZO3vs5F25aQWrB9d51VEzBW9/fd host.example.com`)
1861 key, _, _, _, err := ssh.ParseAuthorizedKey(sshCert) //nolint:dogsled
1862 require.NoError(t, err)

internal/acme/acme.go1

95:6exported-declaration-commentexported function or method should have a comment beginning with its name

internal/acme/acme.go:95:6

94// configuration override. This is a NOOP if we already have certificates
95func GetCertificatesForConfig(c *dataprovider.ACMEConfigs, configDir string) error {
96 if c.Domain == "" {

internal/common/eventmanager_test.go1

1:1file-length-limitfile has 2518 lines; maximum is 500

internal/common/eventmanager_test.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//

internal/common/connection.go1

966:2flag-parameterboolean parameter convertResult controls function flow

internal/common/connection.go:966:2

965func (c *BaseConnection) doStatInternal(virtualPath string, mode int, checkFilePatterns,
966 convertResult bool,
967) (os.FileInfo, error) {

examples/ldapauthserver/httpd/ldapauth.go1

1:1formatfile is not formatted

examples/ldapauthserver/httpd/ldapauth.go:1:1

1package httpd
2
  • Fix (safe): run `strider fmt examples/ldapauthserver/httpd/ldapauth.go`

internal/common/common_test.go1

104:6function-lengthfunction has 72 statements and 115 lines; maximum is 50 statements or 75 lines

internal/common/common_test.go:104:6

103
104func TestConnections(t *testing.T) {
105 c1 := &fakeConnection{

internal/dataprovider/sqlite.go1

319:26function-result-limitfunction returns 5 values; maximum is 3

internal/dataprovider/sqlite.go:319:26

318
319func (p *SQLiteProvider) getUsedQuota(username string) (int, int64, int64, int64, error) {
320 return sqlCommonGetUsedQuota(username, p.dbHandle)

internal/config/config.go1

1992:6get-function-return-valueGet-prefixed function should return a value

internal/config/config.go:1992:6

1991
1992func getHTTPClientHeadersFromEnv(idx int) {
1993 header := httpclient.Header{}

internal/common/common.go1

846:7import-shadowingidentifier url shadows an imported package

internal/common/common.go:846:7

845 if strings.HasPrefix(c.PostConnectHook, "http") {
846 var url *url.URL
847 url, err := url.Parse(c.PostConnectHook)

internal/dataprovider/user.go1

1840:4inefficient-map-lookupreuse the map value obtained by the comma-ok lookup

internal/dataprovider/user.go:1840:4

1839 if _, ok := u.Permissions[k]; !ok {
1840 u.Permissions[k] = v
1841 }

internal/ftpd/internal_test.go1

848:12inefficient-sprintffmt.Sprintf is unnecessary for this conversion; use strconv.FormatUint with base 10

internal/ftpd/internal_test.go:848:12

847 mockCC := &mockFTPClientContext{}
848 connID := fmt.Sprintf("%v", mockCC.ID())
849 fs := newMockOsFs(nil, nil, false, connID, user.GetHomeDir())

internal/common/common_test.go1

1278:35insecure-url-schemeURL uses insecure http scheme

internal/common/common_test.go:1278:35

1277
1278 Config.StartupHook = fmt.Sprintf("http://%v", httpAddr)
1279 assert.NoError(t, Config.ExecuteStartupHook())

internal/dataprovider/configs.go1

419:6max-public-structsfile declares more than 5 exported structs

internal/dataprovider/configs.go:419:6

418// BrandingConfig defines the branding configuration
419type BrandingConfig struct {
420 Name string `json:"name"`

internal/acme/acme.go1

687:3modifies-parameterassignment modifies parameter domain

internal/acme/acme.go:687:3

686 if domain == "" {
687 domain = strings.Join(c.Domains, ",")
688 }

internal/dataprovider/actions.go1

88:30nested-structsmove nested anonymous struct types to named declarations

internal/dataprovider/actions.go:88:30

87 go func() {
88 actionsConcurrencyGuard <- struct{}{}
89 defer func() {

internal/ftpd/ftpd.go1

355:4nil-error-returnthis branch proves an error is non-nil but returns nil in an error result

internal/ftpd/ftpd.go:355:4

354 logger.Error(logSender, "", "unable to load acme key file %q: %v", key, err)
355 return nil
356 }

internal/vfs/sftpfs.go1

76:3nil-value-with-nil-errornil payload is returned with a nil error; return a meaningful value or a descriptive error

internal/vfs/sftpfs.go:76:3

75 if privPayload == "" {
76 return nil, nil
77 }

internal/common/protocol_test.go1

1319:4no-defer-in-loopdefer inside a loop runs at function exit, not iteration exit

internal/common/protocol_test.go:1319:4

1318 defer conn.Close()
1319 defer client.Close()
1320 f, err := client.OpenFile(testFileName, os.O_WRONLY|os.O_CREATE)

internal/httpd/webadmin.go1

3655:4no-else-after-returnremove else and unindent its body after the return

internal/httpd/webadmin.go:3655:4

3654 return
3655 } else if err != nil {
3656 s.renderInternalServerErrorPage(w, r, err)

internal/cmd/acme.go1

95:6no-initreplace init with explicit initialization

internal/cmd/acme.go:95:6

94
95func init() {
96 addConfigFlags(acmeRunCmd)

internal/httpd/file.go1

97:2no-naked-returnreturn values must be explicit

internal/httpd/file.go:97:2

96 f.HandleThrottle()
97 return
98}

examples/ldapauthserver/cmd/root.go1

49:2no-package-varpackage variables introduce mutable global state

examples/ldapauthserver/cmd/root.go:49:2

48 logMaxBackups int
49 logMaxAge int
50 logCompress bool

examples/ldapauthserver/httpd/httpd.go1

1:9package-commentspackage should have a documentation comment

examples/ldapauthserver/httpd/httpd.go:1:9

1package httpd
2

internal/common/eventmanager.go1

1899:34range-value-addresstaking the address of range value user can be misleading

internal/common/eventmanager.go:1899:34

1898 if params.sender == "" {
1899 if !checkUserConditionOptions(&user, &conditions) {
1900 eventManagerLog(logger.LevelDebug, "skipping fs rename for user %s, condition options don't match",

internal/common/common_test.go1

679:18redundant-conversionconversion from int32 to the identical type is redundant

internal/common/common_test.go:679:18

678 Connections.transfers.remove(userTestUsername)
679 assert.Equal(t, int32(0), Connections.GetTotalTransfers())
680

internal/dataprovider/bolt.go1

2439:8slice-preallocationpreallocate actions with capacity len(range source) before appending once per iteration

internal/dataprovider/bolt.go:2439:8

2438 }
2439 var actions []EventAction
2440 for idx := range rule.Actions {

internal/vfs/filesystem.go1

261:2task-commentTODO comment should be resolved or linked to an owned work item

internal/vfs/filesystem.go:261:2

260func (f *Filesystem) HasRedactedSecret() bool {
261 // TODO move vfs specific code into each *FsConfig struct
262 switch f.Provider {

internal/common/actions_test.go1

321:1top-level-declaration-ordertop-level declarations should be ordered as const, var, type, then func

internal/common/actions_test.go:321:1

320
321type actionHandlerStub struct {
322 called bool

internal/common/defenderdb_test.go1

281:15unchecked-type-assertionuse the checked two-result form of the type assertion

internal/common/defenderdb_test.go:281:15

280 assert.NoError(t, err)
281 defender := d.(*dbDefender)
282 lastCleanup := defender.getLastCleanup()

internal/sftpd/internal_test.go1

1855:45unused-parameterparameter ctx is unused

internal/sftpd/internal_test.go:1855:45

1854
1855func (f mockCommandExecutor) CombinedOutput(ctx context.Context, name string, args ...string) ([]byte, error) {
1856 return f.Output, f.Err

internal/common/connection_test.go1

71:7unused-receiverreceiver fs is unused

internal/common/connection_test.go:71:7

70
71func (fs *MockOsFs) Chtimes(_ string, _, _ time.Time, _ bool) error {
72 return vfs.ErrVfsUnsupported

examples/ldapauthserver/logger/logger.go1

106:40use-anyuse any instead of interface{}

examples/ldapauthserver/logger/logger.go:106:40

105// InfoToConsole logs at info level to stdout
106func InfoToConsole(format string, v ...interface{}) {
107 consoleLogger.Info().Msg(fmt.Sprintf(format, v...))

internal/dataprovider/bolt.go1

3896:9use-errors-newreplace fmt.Errorf with errors.New for a static message

internal/dataprovider/bolt.go:3896:9

3895 if bucket == nil {
3896 err = fmt.Errorf("unable to find folders bucket, bolt database structure not correcly defined")
3897 }

internal/command/command_test.go1

70:26add-constantstring literal "a=b" appears more than twice; define a constant

internal/command/command_test.go:70:26

69 assert.Equal(t, time.Duration(config.Commands[0].Timeout)*time.Second, timeout)
70 assert.Contains(t, env, "a=b")
71 assert.Contains(t, env, "c=d")

internal/acme/acme.go1

355:25cognitive-complexityfunction has cognitive complexity 8; maximum is 7

internal/acme/acme.go:355:25

354
355func (c *Configuration) getAccount(privateKey crypto.PrivateKey) (account, error) {
356 _, err := os.Stat(c.accountConfigPath)

internal/vfs/httpfs.go1

732:19confusing-namingname walk differs from Walk only by capitalization

internal/vfs/httpfs.go:732:19

731// walk recursively descends path, calling walkFn.
732func (fs *HTTPFs) walk(filePath string, info fs.FileInfo, walkFn filepath.WalkFunc) error {
733 if !info.IsDir() {

internal/dataprovider/dataprovider.go1

4691:78confusing-resultsadjacent unnamed results of the same type should be named

internal/dataprovider/dataprovider.go:4691:78

4690
4691func getUserForHook(username string, oidcTokenFields *map[string]any) (User, User, error) {
4692 u, err := provider.userExists(username, "")

internal/vfs/vfs.go1

985:6constructor-interface-returnNewPipeReader returns interface PipeReader although its concrete result is consistently *pipeReader; return the concrete type

internal/vfs/vfs.go:985:6

984// NewPipeReader initializes a new PipeReader
985func NewPipeReader(r pipeReaderAt) PipeReader {
986 return &pipeReader{

internal/common/common.go1

1155:33cyclomatic-complexityfunction complexity is 14; maximum is 10

internal/common/common.go:1155:33

1154
1155func (conns *ActiveConnections) checkIdles() {
1156 conns.RLock()

internal/cmd/acme.go1

58:5deep-exitprocess-exit calls should be confined to main or init

internal/cmd/acme.go:58:5

57 logger.ErrorToConsole("unable to initialize KMS: %v", err)
58 os.Exit(1)
59 }

internal/httpd/httpd_test.go1

14304:51deprecated-api-usagegolang.org/x/crypto/ssh.InsecureKeyAlgoDSA is deprecated: DSA is only supported at insecure key sizes, and was removed from major implementations.

internal/httpd/httpd_test.go:14304:51

14303 assert.Len(t, configs.SFTPD.PublicKeyAlgos, 1)
14304 assert.Contains(t, configs.SFTPD.PublicKeyAlgos, ssh.InsecureKeyAlgoDSA) //nolint:staticcheck
14305 assert.Equal(t, "mail.example.net", configs.SMTP.Host)

internal/cmd/resetpwd.go1

100:4discarded-error-resulterror result returned by fmt.Printf is discarded

internal/cmd/resetpwd.go:100:4

99 fmt.Println("")
100 fmt.Printf("Confirm Password: ")
101 confirmPwd, err := term.ReadPassword(int(os.Stdin.Fd()))

examples/ldapauthserver/config/config.go1

137:1doc-comment-perioddocumentation comment should end with punctuation

examples/ldapauthserver/config/config.go:137:1

136
137// LoadConfig loads the configuration
138func LoadConfig(configDir, configName string) error {

internal/dataprovider/user.go1

1832:4early-returninvert the condition and return early to reduce nesting

internal/dataprovider/user.go:1832:4

1831 if k == "/" {
1832 if groupType == sdk.GroupTypePrimary {
1833 u.Permissions[k] = v

internal/dataprovider/eventrule.go1

1834:23error-stringserror string should not be capitalized or end with punctuation

internal/dataprovider/eventrule.go:1834:23

1833 if !action.Options.ExecuteSync {
1834 return errors.New("IDP account check must be a sync action")
1835 }

internal/sftpd/server.go1

1079:3excessive-blank-identifiersassignment discards three or more results; name meaningful results or simplify the return contract

internal/sftpd/server.go:1079:3

1078 }
1079 parsed, _, _, _, err := ssh.ParseAuthorizedKey(certBytes)
1080 if err != nil {

internal/cmd/root.go1

105:6exported-declaration-commentexported function or method should have a comment beginning with its name

internal/cmd/root.go:105:6

104// This is called by main.main(). It only needs to happen once to the rootCmd.
105func Execute() {
106 if err := rootCmd.Execute(); err != nil {

internal/common/protocol_test.go1

1:1file-length-limitfile has 10228 lines; maximum is 500

internal/common/protocol_test.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//

internal/common/connection.go1

1398:76flag-parameterboolean parameter isResume controls function flow

internal/common/connection.go:1398:76

1397// if no enough size is available for a resume/append
1398func (c *BaseConnection) GetMaxWriteSize(quotaResult vfs.QuotaCheckResult, isResume bool, fileSize int64,
1399 isUploadResumeSupported bool,

examples/ldapauthserver/logger/logger.go1

1:1formatfile is not formatted

examples/ldapauthserver/logger/logger.go:1:1

1package logger
2
  • Fix (safe): run `strider fmt examples/ldapauthserver/logger/logger.go`

internal/common/common_test.go1

337:6function-lengthfunction has 57 statements and 59 lines; maximum is 50 statements or 75 lines

internal/common/common_test.go:337:6

336
337func TestSSHConnections(t *testing.T) {
338 conn1, conn2 := net.Pipe()

internal/httpd/api_maintenance.go1

242:6function-result-limitfunction returns 4 values; maximum is 3

internal/httpd/api_maintenance.go:242:6

241
242func getLoaddataOptions(r *http.Request) (string, int, int, error) {
243 var inputFile string

internal/config/config.go1

2022:6get-function-return-valueGet-prefixed function should return a value

internal/config/config.go:2022:6

2021
2022func getCommandConfigsFromEnv(idx int) {
2023 cfg := command.Command{}

internal/common/common.go1

847:3import-shadowingidentifier url shadows an imported package

internal/common/common.go:847:3

846 var url *url.URL
847 url, err := url.Parse(c.PostConnectHook)
848 if err != nil {

internal/ftpd/internal_test.go1

904:12inefficient-sprintffmt.Sprintf is unnecessary for this conversion; use strconv.FormatUint with base 10

internal/ftpd/internal_test.go:904:12

903 mockCC := &mockFTPClientContext{}
904 connID := fmt.Sprintf("%v", mockCC.ID())
905 fs := newMockOsFs(nil, nil, false, connID, user.GetHomeDir())

internal/common/common_test.go1

1295:30insecure-url-schemeURL uses insecure http scheme

internal/common/common_test.go:1295:30

1294func TestPostDisconnectHook(t *testing.T) {
1295 Config.PostDisconnectHook = "http://127.0.0.1/"
1296

internal/dataprovider/configs.go1

518:6max-public-structsfile declares more than 5 exported structs

internal/dataprovider/configs.go:518:6

517// BrandingConfigs defines the branding configuration for WebAdmin and WebClient UI
518type BrandingConfigs struct {
519 WebAdmin BrandingConfig

internal/cmd/serve.go1

78:3modifies-parameterassignment modifies parameter receiver

internal/cmd/serve.go:78:3

77 if err == nil {
78 *receiver = converted
79 }

internal/dataprovider/dataprovider.go1

703:23nested-structsmove nested anonymous struct types to named declarations

internal/dataprovider/dataprovider.go:703:23

702func (d *DefenderEntry) MarshalJSON() ([]byte, error) {
703 return json.Marshal(&struct {
704 ID string `json:"id"`

internal/ftpd/handler.go1

174:4nil-error-returnthis branch proves an error is non-nil but returns nil in an error result

internal/ftpd/handler.go:174:4

173 c.doWildcardListDir = true
174 return vfs.NewFileInfo(name, true, 0, time.Unix(0, 0), false), nil
175 }

internal/common/protocol_test.go1

5279:4no-defer-in-loopdefer inside a loop runs at function exit, not iteration exit

internal/common/protocol_test.go:5279:4

5278 if assert.NoError(t, err) {
5279 defer conn.Close()
5280 defer client.Close()

internal/httpd/webadmin.go1

3828:4no-else-after-returnremove else and unindent its body after the return

internal/httpd/webadmin.go:3828:4

3827 return
3828 } else if err != nil {
3829 s.renderInternalServerErrorPage(w, r, err)

internal/cmd/gen.go1

24:6no-initreplace init with explicit initialization

internal/cmd/gen.go:24:6

23
24func init() {
25 rootCmd.AddCommand(genCmd)

internal/httpd/handler.go1

379:2no-naked-returnreturn values must be explicit

internal/httpd/handler.go:379:2

378 }
379 return
380}

examples/ldapauthserver/cmd/root.go1

50:2no-package-varpackage variables introduce mutable global state

examples/ldapauthserver/cmd/root.go:50:2

49 logMaxAge int
50 logCompress bool
51 logVerbose bool

examples/ldapauthserver/httpd/ldapauth.go1

1:9package-commentspackage should have a documentation comment

examples/ldapauthserver/httpd/ldapauth.go:1:9

1package httpd
2

internal/common/eventmanager.go1

1933:34range-value-addresstaking the address of range value user can be misleading

internal/common/eventmanager.go:1933:34

1932 if params.sender == "" {
1933 if !checkUserConditionOptions(&user, &conditions) {
1934 eventManagerLog(logger.LevelDebug, "skipping fs copy for user %s, condition options don't match",

internal/common/common_test.go1

762:18redundant-conversionconversion from int32 to the identical type is redundant

internal/common/common_test.go:762:18

761 Connections.transfers.remove(userM)
762 assert.Equal(t, int32(0), Connections.GetTotalTransfers())
763

internal/dataprovider/bolt.go1

3227:6slice-preallocationpreallocate actions with capacity len(range source) before appending once per iteration

internal/dataprovider/bolt.go:3227:6

3226 }
3227 var actions []EventAction
3228 for idx := range rule.Actions {

internal/common/common.go1

149:1top-level-declaration-ordertop-level declarations should be ordered as const, var, type, then func

internal/common/common.go:149:1

148// errors definitions
149var (
150 ErrPermissionDenied = errors.New("permission denied")

internal/dataprovider/eventrule.go1

443:37unchecked-type-assertionuse the checked two-result form of the type assertion

internal/dataprovider/eventrule.go:443:37

442 if c.SkipTLSVerify {
443 transport := http.DefaultTransport.(*http.Transport).Clone()
444 if transport.TLSClientConfig != nil {

internal/sftpd/internal_test.go1

1855:66unused-parameterparameter name is unused

internal/sftpd/internal_test.go:1855:66

1854
1855func (f mockCommandExecutor) CombinedOutput(ctx context.Context, name string, args ...string) ([]byte, error) {
1856 return f.Output, f.Err

internal/common/defender.go1

167:7unused-receiverreceiver d is unused

internal/common/defender.go:167:7

166// logBan logs a host's ban due to a too high host score
167func (d *baseDefender) logBan(ip, protocol string) {
168 logger.GetLogger().Info().

examples/ldapauthserver/logger/logger.go1

111:40use-anyuse any instead of interface{}

examples/ldapauthserver/logger/logger.go:111:40

110// WarnToConsole logs at info level to stdout
111func WarnToConsole(format string, v ...interface{}) {
112 consoleLogger.Warn().Msg(fmt.Sprintf(format, v...))

internal/dataprovider/bolt.go1

3905:9use-errors-newreplace fmt.Errorf with errors.New for a static message

internal/dataprovider/bolt.go:3905:9

3904 if bucket == nil {
3905 err = fmt.Errorf("unable to find event actions bucket, bolt database structure not correcly defined")
3906 }

internal/command/command_test.go1

81:29add-constantstring literal "c=d" appears more than twice; define a constant

internal/command/command_test.go:81:29

80 assert.Contains(t, env, "a=b")
81 assert.NotContains(t, env, "c=d")
82 assert.Contains(t, env, "e=f")

internal/acme/acme.go1

516:25cognitive-complexityfunction has cognitive complexity 18; maximum is 7

internal/acme/acme.go:516:25

515
516func (c *Configuration) setupChalleges(client *lego.Client) error {
517 client.Challenge.Remove(challenge.DNS01)

internal/webdavd/file.go1

116:22confusing-namingname ReadDir differs from Readdir only by capitalization

internal/webdavd/file.go:116:22

115// ReadDir implements the FileDirLister interface
116func (f *webDavFile) ReadDir() (webdav.DirLister, error) {
117 if !f.Connection.User.HasPerm(dataprovider.PermListItems, f.GetVirtualPath()) {

internal/dataprovider/dataprovider.go1

4714:85confusing-resultsadjacent unnamed results of the same type should be named

internal/dataprovider/dataprovider.go:4714:85

4713
4714func getUserAndJSONForHook(username string, oidcTokenFields *map[string]any) (User, User, []byte, error) {
4715 u, mergedUser, err := getUserForHook(username, oidcTokenFields)

internal/common/common.go1

1204:33cyclomatic-complexityfunction complexity is 13; maximum is 10

internal/common/common.go:1204:33

1203
1204func (conns *ActiveConnections) checkTransfers() {
1205 if conns.transfersCheckStatus.Load() {

internal/cmd/acme.go1

63:6deep-exitprocess-exit calls should be confined to main or init

internal/cmd/acme.go:63:6

62 logger.ErrorToConsole("unable to initialize plugin system: %v", err)
63 os.Exit(1)
64 }

internal/httpd/httpd_test.go1

14383:51deprecated-api-usagegolang.org/x/crypto/ssh.InsecureKeyAlgoDSA is deprecated: DSA is only supported at insecure key sizes, and was removed from major implementations.

internal/httpd/httpd_test.go:14383:51

14382 assert.Len(t, configs.SFTPD.PublicKeyAlgos, 1)
14383 assert.Contains(t, configs.SFTPD.PublicKeyAlgos, ssh.InsecureKeyAlgoDSA) //nolint:staticcheck
14384 assert.Equal(t, 80, configs.ACME.HTTP01Challenge.Port)

internal/cmd/resetpwd.go1

106:4discarded-error-resulterror result returned by fmt.Println is discarded

internal/cmd/resetpwd.go:106:4

105 }
106 fmt.Println("")
107 if !bytes.Equal(pwd, confirmPwd) {

examples/ldapauthserver/httpd/httpd.go1

35:1doc-comment-perioddocumentation comment should end with punctuation

examples/ldapauthserver/httpd/httpd.go:35:1

34
35// StartHTTPServer initializes and starts the HTTP Server
36func StartHTTPServer(configDir string, httpConfig config.HTTPDConfig) error {

internal/httpclient/httpclient.go1

140:3early-returninvert the condition and return early to reduce nesting

internal/httpclient/httpclient.go:140:3

139 }
140 if rootCAs.AppendCertsFromPEM(certs) {
141 logger.Debug(logSender, "", "CA certificate %q added to the trusted certificates", ca)

internal/dataprovider/eventrule.go1

1840:21error-stringserror string should not be capitalized or end with punctuation

internal/dataprovider/eventrule.go:1840:21

1839 if hasIDPAccountCheck && numSyncAction != 1 {
1840 return errors.New("IDP account check must be the only sync action")
1841 }

internal/sftpd/server.go1

1130:2excessive-blank-identifiersassignment discards three or more results; name meaningful results or simplify the return contract

internal/sftpd/server.go:1130:2

1129 }
1130 pubKey, _, _, _, err := ssh.ParseAuthorizedKey(out) //nolint:dogsled
1131 if err != nil {

internal/command/command.go1

33:2exported-declaration-commentexported declaration should have a comment beginning with its name

internal/command/command.go:33:2

32const (
33 HookFsActions = "fs_actions"
34 HookProviderActions = "provider_actions"

internal/common/tlsutils_test.go1

1:1file-length-limitfile has 527 lines; maximum is 500

internal/common/tlsutils_test.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//

internal/common/connection.go1

1399:2flag-parameterboolean parameter isUploadResumeSupported controls function flow

internal/common/connection.go:1399:2

1398func (c *BaseConnection) GetMaxWriteSize(quotaResult vfs.QuotaCheckResult, isResume bool, fileSize int64,
1399 isUploadResumeSupported bool,
1400) (int64, error) {

examples/ldapauthserver/logger/request_logger.go1

1:1formatfile is not formatted

examples/ldapauthserver/logger/request_logger.go:1:1

1package logger
2
  • Fix (safe): run `strider fmt examples/ldapauthserver/logger/request_logger.go`

internal/common/common_test.go1

397:6function-lengthfunction has 85 statements and 126 lines; maximum is 50 statements or 75 lines

internal/common/common_test.go:397:6

396
397func TestDefenderIntegration(t *testing.T) {
398 // by default defender is nil

internal/httpd/api_utils.go1

265:6function-result-limitfunction returns 4 values; maximum is 3

internal/httpd/api_utils.go:265:6

264
265func getSearchFilters(w http.ResponseWriter, r *http.Request) (int, int, string, error) {
266 var err error

internal/httpd/api_admin.go1

32:6get-function-return-valueGet-prefixed function should return a value

internal/httpd/api_admin.go:32:6

31
32func getAdmins(w http.ResponseWriter, r *http.Request) {
33 r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)

internal/common/connection.go1

338:2import-shadowingidentifier fs shadows an imported package

internal/common/connection.go:338:2

337 }
338 fs, fsPath, err := c.GetFsAndResolvedPath(virtualPath)
339 if err != nil {

internal/httpd/httpd_test.go1

24752:19inefficient-sprintffmt.Sprintf is unnecessary for this conversion; use strconv.Itoa

internal/httpd/httpd_test.go:24752:19

24751 assert.Contains(t, rr.Body.String(), util.I18nError500Message)
24752 form.Set("type", fmt.Sprintf("%d", action.Type))
24753 form.Set("http_timeout", "b")

internal/common/common_test.go1

1301:30insecure-url-schemeURL uses insecure http scheme

internal/common/common_test.go:1301:30

1300
1301 Config.PostDisconnectHook = "http://bar\x7f.com/"
1302 Config.executePostDisconnectHook(remoteAddr, ProtocolSFTP, "", "", time.Now())

internal/dataprovider/configs.go1

543:6max-public-structsfile declares more than 5 exported structs

internal/dataprovider/configs.go:543:6

542// modifying the config file or setting env vars
543type Configs struct {
544 SFTPD *SFTPDConfigs `json:"sftpd,omitempty"`

internal/cmd/serve.go1

85:3modifies-parameterassignment modifies parameter receiver

internal/cmd/serve.go:85:3

84 if err == nil {
85 *receiver = converted
86 }

internal/dataprovider/dataprovider.go1

4364:30nested-structsmove nested anonymous struct types to named declarations

internal/dataprovider/dataprovider.go:4364:30

4363 go func() {
4364 actionsConcurrencyGuard <- struct{}{}
4365 defer func() {

internal/httpd/api_utils.go1

839:4nil-error-returnthis branch proves an error is non-nil but returns nil in an error result

internal/httpd/api_utils.go:839:4

838 username, isAdmin, err)
839 return nil
840 }

internal/common/protocol_test.go1

5280:4no-defer-in-loopdefer inside a loop runs at function exit, not iteration exit

internal/common/protocol_test.go:5280:4

5279 defer conn.Close()
5280 defer client.Close()
5281

internal/httpd/webadmin.go1

3952:4no-else-after-returnremove else and unindent its body after the return

internal/httpd/webadmin.go:3952:4

3951 return
3952 } else if err != nil {
3953 s.renderInternalServerErrorPage(w, r, err)

internal/cmd/gencompletion.go1

126:6no-initreplace init with explicit initialization

internal/cmd/gencompletion.go:126:6

125
126func init() {
127 genCompletionCmd.AddCommand(genCompletionBashCmd)

internal/logger/logger.go1

316:2no-naked-returnreturn values must be explicit

internal/logger/logger.go:316:2

315 Log(LevelError, l.Sender, "", "%s", p)
316 return
317}

examples/ldapauthserver/cmd/root.go1

51:2no-package-varpackage variables introduce mutable global state

examples/ldapauthserver/cmd/root.go:51:2

50 logCompress bool
51 logVerbose bool
52

examples/ldapauthserver/httpd/models.go1

1:9package-commentspackage should have a documentation comment

examples/ldapauthserver/httpd/models.go:1:9

1package httpd
2

internal/common/eventmanager.go1

2095:34range-value-addresstaking the address of range value user can be misleading

internal/common/eventmanager.go:2095:34

2094 if params.sender == "" {
2095 if !checkUserConditionOptions(&user, &conditions) {
2096 eventManagerLog(logger.LevelDebug, "skipping fs exist for user %s, condition options don't match",

internal/common/common_test.go1

770:18redundant-conversionconversion from int32 to the identical type is redundant

internal/common/common_test.go:770:18

769 assert.NoError(t, Connections.IsNewTransferAllowed(newConn("cg", "user-a", "203.0.113.5", 0)))
770 assert.Equal(t, int32(0), Connections.GetTotalTransfers())
771 Config.MaxTotalConnections = 0

internal/dataprovider/bolt.go1

3254:7slice-preallocationpreallocate folders with capacity len(range source) before appending once per iteration

internal/dataprovider/bolt.go:3254:7

3253 if len(group.VirtualFolders) > 0 {
3254 var folders []vfs.VirtualFolder
3255 for idx := range group.VirtualFolders {

internal/common/common_test.go1

92:1top-level-declaration-ordertop-level declarations should be ordered as const, var, type, then func

internal/common/common_test.go:92:1

91
92type customNetConn struct {
93 net.Conn

internal/ftpd/internal_test.go1

870:17unchecked-type-assertionuse the checked two-result form of the type assertion

internal/ftpd/internal_test.go:870:17

869 if assert.NoError(t, err) {
870 transfer := tr.(*transfer)
871 transfers := connection.GetTransfers()

internal/sftpd/internal_test.go1

1855:79unused-parameterparameter args is unused

internal/sftpd/internal_test.go:1855:79

1854
1855func (f mockCommandExecutor) CombinedOutput(ctx context.Context, name string, args ...string) ([]byte, error) {
1856 return f.Output, f.Err

internal/common/eventmanager.go1

2821:7unused-receiverreceiver j is unused

internal/common/eventmanager.go:2821:7

2820
2821func (j *eventCronJob) getTask(rule *dataprovider.EventRule) (dataprovider.Task, error) {
2822 if rule.GuardFromConcurrentExecution() {

examples/ldapauthserver/logger/logger.go1

116:41use-anyuse any instead of interface{}

examples/ldapauthserver/logger/logger.go:116:41

115// ErrorToConsole logs at error level to stdout
116func ErrorToConsole(format string, v ...interface{}) {
117 consoleLogger.Error().Msg(fmt.Sprintf(format, v...))

internal/dataprovider/bolt.go1

3914:9use-errors-newreplace fmt.Errorf with errors.New for a static message

internal/dataprovider/bolt.go:3914:9

3913 if bucket == nil {
3914 err = fmt.Errorf("unable to find event rules bucket, bolt database structure not correcly defined")
3915 }

internal/command/command_test.go1

82:26add-constantstring literal "e=f" appears more than twice; define a constant

internal/command/command_test.go:82:26

81 assert.NotContains(t, env, "c=d")
82 assert.Contains(t, env, "e=f")
83 assert.Len(t, args, 0)

internal/acme/acme.go1

659:25cognitive-complexityfunction has cognitive complexity 9; maximum is 7

internal/acme/acme.go:659:25

658// getCertificates tries to obtain the certificates for the configured domains
659func (c *Configuration) getCertificates() error {
660 account, client, err := c.setup()

internal/dataprovider/memory.go1

332:69confusing-resultsadjacent unnamed results of the same type should be named

internal/dataprovider/memory.go:332:69

331
332func (p *MemoryProvider) getUsedQuota(username string) (int, int64, int64, int64, error) {
333 p.dbHandle.Lock()

internal/common/common.go1

1296:33cyclomatic-complexityfunction complexity is 14; maximum is 10

internal/common/common.go:1296:33

1295// transfers is exceeded for the client connection, its IP address or the user
1296func (conns *ActiveConnections) IsNewTransferAllowed(c *BaseConnection) error {
1297 if isShuttingDown.Load() {

internal/cmd/acme.go1

73:5deep-exitprocess-exit calls should be confined to main or init

internal/cmd/acme.go:73:5

72 logger.ErrorToConsole("Unable to initialize MFA: %v", err)
73 os.Exit(1)
74 }

internal/sftpd/internal_test.go1

1485:29deprecated-api-usagegolang.org/x/crypto/ssh.InsecureKeyAlgoDSA is deprecated: DSA is only supported at insecure key sizes, and was removed from major implementations.

internal/sftpd/internal_test.go:1485:29

1484 MACs: []string{ssh.HMACSHA512ETM},
1485 PublicKeyAlgos: []string{ssh.InsecureKeyAlgoDSA}, //nolint:staticcheck
1486 },

internal/cmd/resetpwd.go1

125:2discarded-error-resulterror result returned by resetPwdCmd.MarkFlagRequired is discarded

internal/cmd/resetpwd.go:125:2

124 resetPwdCmd.Flags().StringVar(&resetPwdAdmin, "admin", "", `Administrator username whose password to reset`)
125 resetPwdCmd.MarkFlagRequired("admin") //nolint:errcheck
126

examples/ldapauthserver/httpd/httpd.go1

134:1doc-comment-perioddocumentation comment should end with punctuation

examples/ldapauthserver/httpd/httpd.go:134:1

133
134// ReloadTLSCertificate reloads the TLS certificate and key from the configured paths
135func ReloadTLSCertificate() {

internal/httpdtest/httpdtest.go1

2081:3early-returninvert the condition and return early to reduce nesting

internal/httpdtest/httpdtest.go:2081:3

2080 for dir, perms := range expected {
2081 if actualPerms, ok := actual[dir]; ok {
2082 for _, v := range actualPerms {

internal/dataprovider/memory.go1

154:27error-stringserror string should not be capitalized or end with punctuation

internal/dataprovider/memory.go:154:27

153 if tlsCert == nil {
154 return user, errors.New("TLS certificate cannot be null or empty")
155 }

internal/sftpd/server.go1

1158:3excessive-blank-identifiersassignment discards three or more results; name meaningful results or simplify the return contract

internal/sftpd/server.go:1158:3

1157 }
1158 parsedKey, _, _, _, err := ssh.ParseAuthorizedKey(keyBytes)
1159 if err != nil {

internal/command/command.go1

34:2exported-declaration-commentexported declaration should have a comment beginning with its name

internal/command/command.go:34:2

33 HookFsActions = "fs_actions"
34 HookProviderActions = "provider_actions"
35 HookStartup = "startup"

internal/common/transfer.go1

1:1file-length-limitfile has 551 lines; maximum is 500

internal/common/transfer.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//

internal/common/connection.go1

1467:35flag-parameterboolean parameter checkFiles controls function flow

internal/common/connection.go:1467:35

1466// HasSpace checks user's quota usage
1467func (c *BaseConnection) HasSpace(checkFiles, getUsage bool, requestPath string) (vfs.QuotaCheckResult,
1468 dataprovider.TransferQuota,

internal/acme/acme.go1

1:1formatfile is not formatted

internal/acme/acme.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//
  • Fix (safe): run `strider fmt internal/acme/acme.go`

internal/common/common_test.go1

524:6function-lengthfunction has 54 statements and 100 lines; maximum is 50 statements or 75 lines

internal/common/common_test.go:524:6

523
524func TestRateLimitersIntegration(t *testing.T) {
525 configCopy := Config

internal/httpd/webadmin.go1

1972:6function-result-limitfunction returns 4 values; maximum is 3

internal/httpd/webadmin.go:1972:6

1971
1972func getTransferLimits(r *http.Request) (int64, int64, int64, error) {
1973 dataTransferUL, err := strconv.ParseInt(r.Form.Get("upload_data_transfer"), 10, 64)

internal/httpd/api_admin.go1

47:6get-function-return-valueGet-prefixed function should return a value

internal/httpd/api_admin.go:47:6

46
47func getAdminByUsername(w http.ResponseWriter, r *http.Request) {
48 r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)

internal/common/connection.go1

358:2import-shadowingidentifier fs shadows an imported package

internal/common/connection.go:358:2

357func (c *BaseConnection) CheckParentDirs(virtualPath string) error {
358 fs, err := c.User.GetFilesystemForPath(virtualPath, c.GetID())
359 if err != nil {

internal/httpd/httpd_test.go1

24763:27inefficient-sprintffmt.Sprintf is unnecessary for this conversion; use strconv.Itoa

internal/httpd/httpd_test.go:24763:27

24762 form.Set("pwd_expiration_threshold", "10")
24763 form.Set("http_timeout", fmt.Sprintf("%d", action.Options.HTTPConfig.Timeout))
24764 form.Set("http_headers[0][http_header_key]", action.Options.HTTPConfig.Headers[0].Key)

internal/common/common_test.go1

1304:42insecure-url-schemeURL uses insecure http scheme

internal/common/common_test.go:1304:42

1303
1304 Config.PostDisconnectHook = fmt.Sprintf("http://%v", httpAddr)
1305 Config.executePostDisconnectHook(remoteAddr, ProtocolSFTP, "", "", time.Now())

internal/dataprovider/dataprovider.go1

347:6max-public-structsfile declares more than 5 exported structs

internal/dataprovider/dataprovider.go:347:6

346// ObjectsActions defines the action to execute on user create, update, delete for the specified objects
347type ObjectsActions struct {
348 // Valid values are add, update, delete. Empty slice to disable

internal/common/connection.go1

69:2modifies-parameterassignment modifies parameter user

internal/common/connection.go:69:2

68 }
69 user.UploadBandwidth, user.DownloadBandwidth = user.GetBandwidthForIP(util.GetIPFromRemoteAddress(remoteAddr), connID)
70 c := &BaseConnection{

internal/httpd/httpd_test.go1

27622:13nested-structsmove nested anonymous struct types to named declarations

internal/httpd/httpd_test.go:27622:13

27621func TestIsNameValid(t *testing.T) {
27622 tests := []struct {
27623 name string

internal/httpd/httpd.go1

1087:4nil-error-returnthis branch proves an error is non-nil but returns nil in an error result

internal/httpd/httpd.go:1087:4

1086 logger.Error(logSender, "", "unable to load acme cert file %q: %v", crt, err)
1087 return nil
1088 }

internal/common/protocol_test.go1

6175:4no-defer-in-loopdefer inside a loop runs at function exit, not iteration exit

internal/common/protocol_test.go:6175:4

6174 if assert.NoError(t, err) {
6175 defer conn.Close()
6176 defer client.Close()

internal/httpd/webadmin.go1

4064:4no-else-after-returnremove else and unindent its body after the return

internal/httpd/webadmin.go:4064:4

4063 return
4064 } else if err != nil {
4065 s.renderInternalServerErrorPage(w, r, err)

internal/cmd/genman.go1

66:6no-initreplace init with explicit initialization

internal/cmd/genman.go:66:6

65
66func init() {
67 genManCmd.Flags().StringVarP(&manDir, "dir", "d", "man", "The directory to write the man pages")

internal/sftpd/ssh_cmd.go1

122:2no-naked-returnreturn values must be explicit

internal/sftpd/ssh_cmd.go:122:2

121 }
122 return
123}

examples/ldapauthserver/cmd/root.go1

53:2no-package-varpackage variables introduce mutable global state

examples/ldapauthserver/cmd/root.go:53:2

52
53 rootCmd = &cobra.Command{
54 Use: "ldapauthserver",

examples/ldapauthserver/httpd/tlsutils.go1

1:9package-commentspackage should have a documentation comment

examples/ldapauthserver/httpd/tlsutils.go:1:9

1package httpd
2

internal/common/eventmanager.go1

2129:34range-value-addresstaking the address of range value user can be misleading

internal/common/eventmanager.go:2129:34

2128 if params.sender == "" {
2129 if !checkUserConditionOptions(&user, &conditions) {
2130 eventManagerLog(logger.LevelDebug, "skipping fs compress for user %s, condition options don't match",

internal/common/common_test.go1

790:18redundant-conversionconversion from int32 to the identical type is redundant

internal/common/common_test.go:790:18

789 Connections.transfers.remove(userC)
790 assert.Equal(t, int32(0), Connections.GetTotalTransfers())
791}

internal/dataprovider/bolt.go1

3277:7slice-preallocationpreallocate folders with capacity len(range source) before appending once per iteration

internal/dataprovider/bolt.go:3277:7

3276 if len(user.VirtualFolders) > 0 {
3277 var folders []vfs.VirtualFolder
3278 for idx := range user.VirtualFolders {

internal/common/connection.go1

1843:1top-level-declaration-ordertop-level declarations should be ordered as const, var, type, then func

internal/common/connection.go:1843:1

1842// DirListerAt defines a directory lister implementing the ListAt method.
1843type DirListerAt struct {
1844 virtualPath string

internal/httpclient/httpclient.go1

92:42unchecked-type-assertionuse the checked two-result form of the type assertion

internal/httpclient/httpclient.go:92:42

91 }
92 customTransport := http.DefaultTransport.(*http.Transport).Clone()
93 if customTransport.TLSClientConfig != nil {

tests/ipfilter/main.go1

12:30unused-parameterparameter protocol is unused

tests/ipfilter/main.go:12:30

11
12func (f *Filter) CheckIP(ip, protocol string) error {
13 if ip == "192.168.1.12" {

internal/common/transferschecker.go1

61:7unused-receiverreceiver t is unused

internal/common/transferschecker.go:61:7

60
61func (t *baseTransferChecker) isDataTransferExceeded(user dataprovider.User, transfer dataprovider.ActiveTransfer, ulSize,
62 dlSize int64,

examples/ldapauthserver/logger/request_logger.go1

21:20use-anyuse any instead of interface{}

examples/ldapauthserver/logger/request_logger.go:21:20

20 Logger *zerolog.Logger
21 fields map[string]interface{}
22}

internal/dataprovider/bolt.go1

3924:11use-errors-newreplace fmt.Errorf with errors.New for a static message

internal/dataprovider/bolt.go:3924:11

3923 if bucket == nil {
3924 return fmt.Errorf("unable to find database schema version bucket")
3925 }

internal/command/command_test.go1

87:13add-constantstring literal "cmd1" appears more than twice; define a constant

internal/command/command_test.go:87:13

86 {
87 Path: "cmd1",
88 Timeout: 30,

internal/acme/acme.go1

703:25cognitive-complexityfunction has cognitive complexity 17; maximum is 7

internal/acme/acme.go:703:25

702
703func (c *Configuration) renewCertificates() error {
704 lockTime, err := c.getLockTime()

internal/dataprovider/memory.go1

332:76confusing-resultsadjacent unnamed results of the same type should be named

internal/dataprovider/memory.go:332:76

331
332func (p *MemoryProvider) getUsedQuota(username string) (int, int64, int64, int64, error) {
333 p.dbHandle.Lock()

internal/common/common.go1

1331:33cyclomatic-complexityfunction complexity is 14; maximum is 10

internal/common/common.go:1331:33

1330// or the service is shutting down
1331func (conns *ActiveConnections) IsNewConnectionAllowed(ipAddr, protocol string) error {
1332 if isShuttingDown.Load() {

internal/cmd/acme.go1

79:5deep-exitprocess-exit calls should be confined to main or init

internal/cmd/acme.go:79:5

78 logger.ErrorToConsole("error initializing data provider: %v", err)
79 os.Exit(1)
80 }

internal/sftpd/server.go1

442:40deprecated-api-usagenet.Temporary is deprecated: Temporary errors are not well-defined. Most "temporary" errors are timeouts, and the few exceptions are surprising. Do not use this method.

internal/sftpd/server.go:442:40

441 // see https://github.com/golang/go/blob/4aa1efed4853ea067d665a952eee77c52faac774/src/net/http/server.go#L3046
442 if ne, ok := err.(net.Error); ok && ne.Temporary() { //nolint:staticcheck
443 if tempDelay == 0 {

internal/cmd/root.go1

107:3discarded-error-resulterror result returned by fmt.Println is discarded

internal/cmd/root.go:107:3

106 if err := rootCmd.Execute(); err != nil {
107 fmt.Println(err)
108 os.Exit(1)

examples/ldapauthserver/httpd/models.go1

15:1doc-comment-perioddocumentation comment should end with punctuation

examples/ldapauthserver/httpd/models.go:15:1

14
15// SFTPGoExtensionsFilter defines filters based on file extensions
16type SFTPGoExtensionsFilter struct {

internal/sftpd/scp.go1

706:3early-returninvert the condition and return early to reduce nesting

internal/sftpd/scp.go:706:3

705 }
706 if strings.HasPrefix(command, "T") {
707 err = c.sendConfirmationMessage()

internal/dataprovider/memory.go1

1654:21error-stringserror string should not be capitalized or end with punctuation

internal/dataprovider/memory.go:1654:21

1653 if err == nil {
1654 return fmt.Errorf("API key %q already exists", apiKey.KeyID)
1655 }

internal/sftpd/sftpd_test.go1

12192:2excessive-blank-identifiersassignment discards three or more results; name meaningful results or simplify the return contract

internal/sftpd/sftpd_test.go:12192:2

12191 }
12192 cert, _, _, _, err := ssh.ParseAuthorizedKey(certBytes) //nolint:dogsled
12193 if err != nil {

internal/command/command.go1

35:2exported-declaration-commentexported declaration should have a comment beginning with its name

internal/command/command.go:35:2

34 HookProviderActions = "provider_actions"
35 HookStartup = "startup"
36 HookPostConnect = "post_connect"

internal/common/transferschecker_test.go1

1:1file-length-limitfile has 852 lines; maximum is 500

internal/common/transferschecker_test.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//

internal/common/connection.go1

1467:47flag-parameterboolean parameter getUsage controls function flow

internal/common/connection.go:1467:47

1466// HasSpace checks user's quota usage
1467func (c *BaseConnection) HasSpace(checkFiles, getUsage bool, requestPath string) (vfs.QuotaCheckResult,
1468 dataprovider.TransferQuota,

internal/cmd/install_windows.go1

1:1formatfile is not formatted

internal/cmd/install_windows.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//
  • Fix (safe): run `strider fmt internal/cmd/install_windows.go`

internal/common/common_test.go1

699:6function-lengthfunction has 57 statements and 93 lines; maximum is 50 statements or 75 lines

internal/common/common_test.go:699:6

698
699func TestIsNewTransferAllowedPerHost(t *testing.T) {
700 oldMaxTotal := Config.MaxTotalConnections

internal/mfa/mfa.go1

104:6function-result-limitfunction returns 4 values; maximum is 3

internal/mfa/mfa.go:104:6

103// using the configuration with configName
104func GenerateTOTPSecret(configName, username string) (string, *otp.Key, []byte, error) {
105 for _, config := range totpConfigs {

internal/httpd/api_admin.go1

203:6get-function-return-valueGet-prefixed function should return a value

internal/httpd/api_admin.go:203:6

202
203func getAdminProfile(w http.ResponseWriter, r *http.Request) {
204 r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)

internal/common/connection.go1

415:2import-shadowingidentifier fs shadows an imported package

internal/common/connection.go:415:2

414 }
415 fs, fsPath, err := c.GetFsAndResolvedPath(virtualPath)
416 if err != nil {

internal/httpd/httpd_test.go1

24904:19inefficient-sprintffmt.Sprintf is unnecessary for this conversion; use strconv.Itoa

internal/httpd/httpd_test.go:24904:19

24903 }()
24904 form.Set("type", fmt.Sprintf("%d", action.Type))
24905 req, err = http.NewRequest(http.MethodPost, path.Join(webAdminEventActionPath, action.Name),

internal/common/common_test.go1

1332:27insecure-url-schemeURL uses insecure http scheme

internal/common/common_test.go:1332:27

1331
1332 Config.PostConnectHook = "http://foo\x7f.com/"
1333 assert.Error(t, Config.ExecutePostConnectHook(ipAddr, ProtocolSFTP))

internal/dataprovider/dataprovider.go1

357:6max-public-structsfile declares more than 5 exported structs

internal/dataprovider/dataprovider.go:357:6

356// ProviderStatus defines the provider status
357type ProviderStatus struct {
358 Driver string `json:"driver"`

internal/common/connection.go1

69:24modifies-parameterassignment modifies parameter user

internal/common/connection.go:69:24

68 }
69 user.UploadBandwidth, user.DownloadBandwidth = user.GetBandwidthForIP(util.GetIPFromRemoteAddress(remoteAddr), connID)
70 c := &BaseConnection{

internal/httpd/internal_test.go1

4166:17nested-structsmove nested anonymous struct types to named declarations

internal/httpd/internal_test.go:4166:17

4165 base := webClientFilesPath
4166 testCases := []struct {
4167 name string

internal/httpd/httpd.go1

1091:4nil-error-returnthis branch proves an error is non-nil but returns nil in an error result

internal/httpd/httpd.go:1091:4

1090 logger.Error(logSender, "", "unable to load acme key file %q: %v", key, err)
1091 return nil
1092 }

internal/common/protocol_test.go1

6176:4no-defer-in-loopdefer inside a loop runs at function exit, not iteration exit

internal/common/protocol_test.go:6176:4

6175 defer conn.Close()
6176 defer client.Close()
6177

internal/httpd/webadmin.go1

4179:4no-else-after-returnremove else and unindent its body after the return

internal/httpd/webadmin.go:4179:4

4178 return
4179 } else if err != nil {
4180 s.renderInternalServerErrorPage(w, r, err)

internal/cmd/initprovider.go1

121:6no-initreplace init with explicit initialization

internal/cmd/initprovider.go:121:6

120
121func init() {
122 rootCmd.AddCommand(initProviderCmd)

internal/sftpd/transfer.go1

116:3no-naked-returnreturn values must be explicit

internal/sftpd/transfer.go:116:3

115 err = t.ConvertError(err)
116 return
117 }

examples/ldapauthserver/cmd/serve.go1

15:2no-package-varpackage variables introduce mutable global state

examples/ldapauthserver/cmd/serve.go:15:2

14var (
15 serveCmd = &cobra.Command{
16 Use: "serve",

examples/ldapauthserver/logger/logger.go1

1:9package-commentspackage should have a documentation comment

examples/ldapauthserver/logger/logger.go:1:9

1package logger
2

internal/common/eventmanager.go1

2210:34range-value-addresstaking the address of range value user can be misleading

internal/common/eventmanager.go:2210:34

2209 if params.sender == "" {
2210 if !checkUserConditionOptions(&user, &conditions) {
2211 eventManagerLog(logger.LevelDebug, "skipping quota reset for user %q, condition options don't match",

internal/common/common_test.go1

851:18redundant-conversionconversion from int32 to the identical type is redundant

internal/common/common_test.go:851:18

850 assert.Error(t, Connections.IsNewConnectionAllowed(ipAddr, ProtocolFTP))
851 assert.Equal(t, int32(3), Connections.GetClientConnections())
852 // Add the IP to the defender safe list

internal/dataprovider/configs.go1

104:6slice-preallocationpreallocate hostKeyAlgos with capacity len(range source) before appending once per iteration

internal/dataprovider/configs.go:104:6

103func (c *SFTPDConfigs) validate() error {
104 var hostKeyAlgos []string
105 for _, algo := range c.HostKeyAlgos {

internal/common/dataretention.go1

107:1top-level-declaration-ordertop-level declarations should be ordered as const, var, type, then func

internal/common/dataretention.go:107:1

106
107type folderRetentionCheckResult struct {
108 Path string `json:"path"`

internal/httpclient/httpclient.go1

197:29unchecked-type-assertionuse the checked two-result form of the type assertion

internal/httpclient/httpclient.go:197:29

196 client.HTTPClient.Timeout = time.Duration(httpConfig.Timeout * float64(time.Second))
197 client.HTTPClient.Transport.(*http.Transport).TLSClientConfig = httpConfig.customTransport.TLSClientConfig
198 client.Logger = &logger.LeveledLogger{Sender: "RetryableHTTPClient"}

internal/common/transferschecker.go1

86:7unused-receiverreceiver t is unused

internal/common/transferschecker.go:86:7

85
86func (t *baseTransferChecker) getRemainingDiskQuota(user dataprovider.User, folderName string) (int64, error) {
87 var result int64

examples/ldapauthserver/logger/request_logger.go1

37:23use-anyuse any instead of interface{}

examples/ldapauthserver/logger/request_logger.go:37:23

36
37 fields := map[string]interface{}{
38 "remote_addr": r.RemoteAddr,

internal/dataprovider/bolt.go1

3942:11use-errors-newreplace fmt.Errorf with errors.New for a static message

internal/dataprovider/bolt.go:3942:11

3941 if bucket == nil {
3942 return fmt.Errorf("unable to find database schema version bucket")
3943 }

internal/command/command_test.go1

90:22add-constantstring literal "1" appears more than twice; define a constant

internal/command/command_test.go:90:22

89 Env: []string{"c=d"},
90 Args: []string{"1", "", "2"},
91 Hook: HookCheckPassword,

internal/cmd/install_windows.go1

75:6cognitive-complexityfunction has cognitive complexity 10; maximum is 7

internal/cmd/install_windows.go:75:6

74
75func getCustomServeFlags() []string {
76 result := []string{}

internal/dataprovider/mysql.go1

351:68confusing-resultsadjacent unnamed results of the same type should be named

internal/dataprovider/mysql.go:351:68

350
351func (p *MySQLProvider) getUsedQuota(username string) (int, int64, int64, int64, error) {
352 return sqlCommonGetUsedQuota(username, p.dbHandle)

internal/common/connection.go1

615:26cyclomatic-complexityfunction complexity is 12; maximum is 10

internal/common/connection.go:615:26

614
615func (c *BaseConnection) checkCopy(srcInfo, dstInfo os.FileInfo, virtualSource, virtualTarget string) error {
616 _, fsSourcePath, err := c.GetFsAndResolvedPath(virtualSource)

internal/cmd/acme.go1

85:5deep-exitprocess-exit calls should be confined to main or init

internal/cmd/acme.go:85:5

84 logger.ErrorToConsole("Unable to initialize ACME configuration: %v", err)
85 os.Exit(1)
86 }

internal/sftpd/sftpd.go1

42:3deprecated-api-usagegolang.org/x/crypto/ssh.InsecureCertAlgoDSAv01 is deprecated: DSA is only supported at insecure key sizes, and was removed from major implementations.

internal/sftpd/sftpd.go:42:3

41 ssh.CertAlgoRSASHA512v01: ssh.KeyAlgoRSASHA512,
42 ssh.InsecureCertAlgoDSAv01: ssh.InsecureKeyAlgoDSA, //nolint:staticcheck
43 ssh.CertAlgoECDSA256v01: ssh.KeyAlgoECDSA256,

internal/cmd/root.go1

114:2discarded-error-resulterror result returned by viper.BindEnv is discarded

internal/cmd/root.go:114:2

113 viper.SetDefault(configDirKey, defaultConfigDir)
114 viper.BindEnv(configDirKey, "SFTPGO_CONFIG_DIR") //nolint:errcheck // err is not nil only if the key to bind is missing
115 cmd.Flags().StringVarP(&configDir, configDirFlag, "c", viper.GetString(configDirKey),

examples/ldapauthserver/httpd/models.go1

22:1doc-comment-perioddocumentation comment should end with punctuation

examples/ldapauthserver/httpd/models.go:22:1

21
22// SFTPGoUserFilters defines additional restrictions for an SFTPGo user
23type SFTPGoUserFilters struct {

internal/sftpd/scp.go1

746:2early-returninvert the condition and return early to reduce nesting

internal/sftpd/scp.go:746:2

745 parts := strings.SplitN(command, " ", 3)
746 if len(parts) == 3 {
747 size, err = strconv.ParseInt(parts[1], 10, 64)

internal/dataprovider/mysql_disabled.go1

30:20error-stringserror string should not be capitalized or end with punctuation

internal/dataprovider/mysql_disabled.go:30:20

29func initializeMySQLProvider() error {
30 return errors.New("MySQL disabled at build time")
31}

internal/webdavd/internal_test.go1

1054:2excessive-blank-identifiersassignment discards three or more results; name meaningful results or simplify the return contract

internal/webdavd/internal_test.go:1054:2

1053
1054 _, _, _, _, err = server.authenticate(req, ipAddr) //nolint:dogsled
1055 assert.Error(t, err)

internal/command/command.go1

36:2exported-declaration-commentexported declaration should have a comment beginning with its name

internal/command/command.go:36:2

35 HookStartup = "startup"
36 HookPostConnect = "post_connect"
37 HookPostDisconnect = "post_disconnect"

internal/config/config.go1

1:1file-length-limitfile has 2296 lines; maximum is 500

internal/config/config.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//

internal/common/dataretention.go1

254:66flag-parameterboolean parameter checkVal controls function flow

internal/common/dataretention.go:254:66

253
254func (c *RetentionCheck) checkEmptyDirRemoval(folderPath string, checkVal bool) {
255 if folderPath == "/" || !checkVal {

internal/cmd/portable.go1

1:1formatfile is not formatted

internal/cmd/portable.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//
  • Fix (safe): run `strider fmt internal/cmd/portable.go`

internal/common/common_test.go1

878:6function-lengthfunction has 57 statements and 102 lines; maximum is 50 statements or 75 lines

internal/common/common_test.go:878:6

877
878func TestIdleConnections(t *testing.T) {
879 configCopy := Config

internal/plugin/kms.go1

126:21function-result-limitfunction returns 4 values; maximum is 3

internal/plugin/kms.go:126:21

125
126func (p *kmsPlugin) Encrypt(secret kms.BaseSecret, url string, masterKey string) (string, string, int32, error) {
127 return p.service.Encrypt(secret.Payload, secret.AdditionalData, url, masterKey)

internal/httpd/api_defender.go1

30:6get-function-return-valueGet-prefixed function should return a value

internal/httpd/api_defender.go:30:6

29
30func getDefenderHosts(w http.ResponseWriter, r *http.Request) {
31 r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)

internal/common/connection.go1

446:37import-shadowingidentifier fs shadows an imported package

internal/common/connection.go:446:37

445// RemoveFile removes a file at the specified fsPath
446func (c *BaseConnection) RemoveFile(fs vfs.Fs, fsPath, virtualPath string, info os.FileInfo) error {
447 if err := c.IsRemoveFileAllowed(virtualPath); err != nil {

internal/httpd/httpd_test.go1

24923:26inefficient-sprintffmt.Sprintf is unnecessary for this conversion; use strconv.Itoa

internal/httpd/httpd_test.go:24923:26

24922 assert.Contains(t, rr.Body.String(), util.I18nError500Message)
24923 form.Set("cmd_timeout", fmt.Sprintf("%d", action.Options.CmdConfig.Timeout))
24924 form.Set("env_vars[0][cmd_env_key]", action.Options.CmdConfig.EnvVars[0].Key)

internal/common/common_test.go1

1335:27insecure-url-schemeURL uses insecure http scheme

internal/common/common_test.go:1335:27

1334
1335 Config.PostConnectHook = "http://invalid:1234/"
1336 assert.Error(t, Config.ExecutePostConnectHook(ipAddr, ProtocolSFTP))

internal/dataprovider/dataprovider.go1

364:6max-public-structsfile declares more than 5 exported structs

internal/dataprovider/dataprovider.go:364:6

363// Config defines the provider configuration
364type Config struct {
365 // Driver name, must be one of the SupportedProviders

internal/common/connection.go1

565:3modifies-parameterassignment modifies parameter recursion

internal/common/connection.go:565:3

564 }
565 recursion++
566 lister, err := c.ListDir(virtualPath)

internal/httpd/internal_test.go1

4303:13nested-structsmove nested anonymous struct types to named declarations

internal/httpd/internal_test.go:4303:13

4302func TestValidateBaseURL(t *testing.T) {
4303 tests := []struct {
4304 name string

internal/httpd/webadmin.go1

2857:4nil-error-returnthis branch proves an error is non-nil but returns nil in an error result

internal/httpd/webadmin.go:2857:4

2856 if errors.Is(err, http.ErrMissingFile) {
2857 return result, nil
2858 }

internal/common/protocol_test.go1

6736:4no-defer-in-loopdefer inside a loop runs at function exit, not iteration exit

internal/common/protocol_test.go:6736:4

6735 if assert.NoError(t, err) {
6736 defer conn.Close()
6737 defer client.Close()

internal/httpd/webadmin.go1

4303:4no-else-after-returnremove else and unindent its body after the return

internal/httpd/webadmin.go:4303:4

4302 return
4303 } else if err != nil {
4304 s.renderInternalServerErrorPage(w, r, err)

internal/cmd/install_windows.go1

70:6no-initreplace init with explicit initialization

internal/cmd/install_windows.go:70:6

69
70func init() {
71 serviceCmd.AddCommand(installCmd)

internal/sftpd/transfer.go1

119:2no-naked-returnreturn values must be explicit

internal/sftpd/transfer.go:119:2

118 t.HandleThrottle()
119 return
120}

examples/ldapauthserver/config/config.go1

50:5no-package-varpackage variables introduce mutable global state

examples/ldapauthserver/config/config.go:50:5

49
50var conf appConfig
51

examples/ldapauthserver/logger/request_logger.go1

1:9package-commentspackage should have a documentation comment

examples/ldapauthserver/logger/request_logger.go:1:9

1package logger
2

internal/common/eventmanager.go1

2217:37range-value-addresstaking the address of range value user can be misleading

internal/common/eventmanager.go:2217:37

2216 executed++
2217 if err = executeQuotaResetForUser(&user); err != nil {
2218 params.AddError(err)

internal/common/common_test.go1

872:18redundant-conversionconversion from int32 to the identical type is redundant

internal/common/common_test.go:872:18

871
872 assert.Equal(t, int32(0), Connections.GetClientConnections())
873

internal/dataprovider/configs.go1

115:6slice-preallocationpreallocate kexAlgos with capacity len(range source) before appending once per iteration

internal/dataprovider/configs.go:115:6

114 c.HostKeyAlgos = hostKeyAlgos
115 var kexAlgos []string
116 for _, algo := range c.KexAlgorithms {

internal/common/defender.go1

29:1top-level-declaration-ordertop-level declarations should be ordered as const, var, type, then func

internal/common/defender.go:29:1

28// Supported host events
29const (
30 HostEventLoginFailed HostEvent = "LoginFailed"

internal/httpd/httpd_test.go1

3487:45unchecked-type-assertionuse the checked two-result form of the type assertion

internal/httpd/httpd_test.go:3487:45

3486 assert.NoError(t, err)
3487 userToken := responseHolder["access_token"].(string)
3488 assert.NotEmpty(t, userToken)

internal/common/transferschecker.go1

160:7unused-receiverreceiver t is unused

internal/common/transferschecker.go:160:7

159
160func (t *baseTransferChecker) getUsersToCheck(usersToFetch map[string]bool) (map[string]dataprovider.User, error) {
161 users, err := dataprovider.GetUsersForQuotaCheck(usersToFetch)

examples/ldapauthserver/logger/request_logger.go1

53:107use-anyuse any instead of interface{}

examples/ldapauthserver/logger/request_logger.go:53:107

52// Write logs a new entry at the end of the HTTP request
53func (l *StructuredLoggerEntry) Write(status, bytes int, header http.Header, elapsed time.Duration, extra interface{}) {
54 l.Logger.Info().

internal/dataprovider/dataprovider.go1

3769:17use-errors-newreplace fmt.Errorf with errors.New for a static message

internal/dataprovider/dataprovider.go:3769:17

3768 if len(vals) != 5 {
3769 return false, fmt.Errorf("pbkdf2: hash is not in the correct format")
3770 }

internal/command/command_test.go1

90:31add-constantstring literal "2" appears more than twice; define a constant

internal/command/command_test.go:90:31

89 Env: []string{"c=d"},
90 Args: []string{"1", "", "2"},
91 Hook: HookCheckPassword,

internal/cmd/ping.go1

32:6cognitive-complexityfunction has cognitive complexity 9; maximum is 7

internal/cmd/ping.go:32:6

31
32func getHealthzURLFromBindings(bindings []httpd.Binding) string {
33 for _, b := range bindings {

internal/dataprovider/mysql.go1

351:75confusing-resultsadjacent unnamed results of the same type should be named

internal/dataprovider/mysql.go:351:75

350
351func (p *MySQLProvider) getUsedQuota(username string) (int, int64, int64, int64, error) {
352 return sqlCommonGetUsedQuota(username, p.dbHandle)

internal/common/connection.go1

696:26cyclomatic-complexityfunction complexity is 12; maximum is 10

internal/common/connection.go:696:26

695
696func (c *BaseConnection) doRecursiveCopy(virtualSourcePath, virtualTargetPath string, srcInfo os.FileInfo,
697 createTargetDir bool, recursion int,

internal/cmd/acme.go1

89:5deep-exitprocess-exit calls should be confined to main or init

internal/cmd/acme.go:89:5

88 logger.ErrorToConsole("Cannot get certificates: %v", err)
89 os.Exit(1)
90 }

internal/sftpd/sftpd.go1

42:31deprecated-api-usagegolang.org/x/crypto/ssh.InsecureKeyAlgoDSA is deprecated: DSA is only supported at insecure key sizes, and was removed from major implementations.

internal/sftpd/sftpd.go:42:31

41 ssh.CertAlgoRSASHA512v01: ssh.KeyAlgoRSASHA512,
42 ssh.InsecureCertAlgoDSAv01: ssh.InsecureKeyAlgoDSA, //nolint:staticcheck
43 ssh.CertAlgoECDSA256v01: ssh.KeyAlgoECDSA256,

internal/cmd/root.go1

130:2discarded-error-resulterror result returned by viper.BindPFlag is discarded

internal/cmd/root.go:130:2

129env var too.`)
130 viper.BindPFlag(configDirKey, cmd.Flags().Lookup(configDirFlag)) //nolint:errcheck
131

examples/ldapauthserver/httpd/models.go1

30:1doc-comment-perioddocumentation comment should end with punctuation

examples/ldapauthserver/httpd/models.go:30:1

29
30// S3FsConfig defines the configuration for S3 based filesystem
31type S3FsConfig struct {

internal/vfs/sftpfs.go1

1194:3early-returninvert the condition and return early to reduce nesting

internal/vfs/sftpfs.go:1194:3

1193 for {
1194 if val, ok := c.items[key]; ok {
1195 activeSessions := val.ActiveSessions()

internal/dataprovider/pgsql_disabled.go1

30:20error-stringserror string should not be capitalized or end with punctuation

internal/dataprovider/pgsql_disabled.go:30:20

29func initializePGSQLProvider() error {
30 return errors.New("PostgreSQL disabled at build time")
31}

internal/webdavd/internal_test.go1

1076:2excessive-blank-identifiersassignment discards three or more results; name meaningful results or simplify the return contract

internal/webdavd/internal_test.go:1076:2

1075 req.SetBasicAuth(username, "wrong")
1076 _, _, _, _, err = server.authenticate(req, ipAddr) //nolint:dogsled
1077 assert.EqualError(t, err, dataprovider.ErrInvalidCredentials.Error())

internal/command/command.go1

37:2exported-declaration-commentexported declaration should have a comment beginning with its name

internal/command/command.go:37:2

36 HookPostConnect = "post_connect"
37 HookPostDisconnect = "post_disconnect"
38 HookCheckPassword = "check_password"

internal/config/config_test.go1

1:1file-length-limitfile has 1642 lines; maximum is 500

internal/config/config_test.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//

internal/common/eventmanager.go1

787:45flag-parameterboolean parameter addObjectData controls function flow

internal/common/eventmanager.go:787:45

786
787func (p *EventParams) getStringReplacements(addObjectData bool, escapeMode int) []string {
788 var dateTimeString string

internal/cmd/resetprovider.go1

1:1formatfile is not formatted

internal/cmd/resetprovider.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//
  • Fix (safe): run `strider fmt internal/cmd/resetprovider.go`

internal/common/common_test.go1

1559:6function-lengthfunction has 58 statements and 137 lines; maximum is 50 statements or 75 lines

internal/common/common_test.go:1559:6

1558
1559func TestVfsSameResource(t *testing.T) {
1560 fs := vfs.Filesystem{}

internal/plugin/plugin.go1

436:19function-result-limitfunction returns 4 values; maximum is 3

internal/plugin/plugin.go:436:19

435
436func (m *Manager) kmsEncrypt(secret kms.BaseSecret, url string, masterKey string, kmsID int) (string, string, int32, error) {
437 m.kmsLock.RLock()

internal/httpd/api_defender.go1

44:6get-function-return-valueGet-prefixed function should return a value

internal/httpd/api_defender.go:44:6

43
44func getDefenderHostByID(w http.ResponseWriter, r *http.Request) {
45 r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)

internal/common/connection.go1

486:45import-shadowingidentifier fs shadows an imported package

internal/common/connection.go:486:45

485// IsRemoveDirAllowed returns an error if removing this directory is not allowed
486func (c *BaseConnection) IsRemoveDirAllowed(fs vfs.Fs, fsPath, virtualPath string) error {
487 if virtualPath == "/" || fs.GetRelativePath(fsPath) == "/" {

internal/httpd/httpd_test.go1

24973:19inefficient-sprintffmt.Sprintf is unnecessary for this conversion; use strconv.Itoa

internal/httpd/httpd_test.go:24973:19

24972 }
24973 form.Set("type", fmt.Sprintf("%d", action.Type))
24974 form.Set("email_recipients", "address1@example.com, address2@example.com")

internal/common/common_test.go1

1338:39insecure-url-schemeURL uses insecure http scheme

internal/common/common_test.go:1338:39

1337
1338 Config.PostConnectHook = fmt.Sprintf("http://%v/404", httpAddr)
1339 assert.Error(t, Config.ExecutePostConnectHook(ipAddr, ProtocolFTP))

internal/dataprovider/dataprovider.go1

629:6max-public-structsfile declares more than 5 exported structs

internal/dataprovider/dataprovider.go:629:6

628// ActiveTransfer defines an active protocol transfer
629type ActiveTransfer struct {
630 ID int64

internal/common/connection.go1

704:3modifies-parameterassignment modifies parameter recursion

internal/common/connection.go:704:3

703 }
704 recursion++
705 if createTargetDir {

internal/httpd/internal_test.go1

4429:13nested-structsmove nested anonymous struct types to named declarations

internal/httpd/internal_test.go:4429:13

4428func TestSlicesEqual(t *testing.T) {
4429 tests := []struct {
4430 name string

internal/sftpd/scp.go1

104:5nil-error-returnthis branch proves an error is non-nil but returns nil in an error result

internal/sftpd/scp.go:104:5

103 if errors.Is(err, io.EOF) {
104 return nil
105 }

internal/common/protocol_test.go1

6737:4no-defer-in-loopdefer inside a loop runs at function exit, not iteration exit

internal/common/protocol_test.go:6737:4

6736 defer conn.Close()
6737 defer client.Close()
6738

internal/httpd/webclient.go1

1575:4no-else-after-returnremove else and unindent its body after the return

internal/httpd/webclient.go:1575:4

1574 return
1575 } else if err != nil {
1576 s.renderClientInternalServerErrorPage(w, r, err)

internal/cmd/ping.go1

117:6no-initreplace init with explicit initialization

internal/cmd/ping.go:117:6

116
117func init() {
118 addConfigFlags(pingCmd)

internal/sftpd/transfer.go1

141:3no-naked-returnreturn values must be explicit

internal/sftpd/transfer.go:141:3

140 err = t.ConvertError(err)
141 return
142 }

examples/ldapauthserver/httpd/auth.go1

25:2no-package-varpackage variables introduce mutable global state

examples/ldapauthserver/httpd/auth.go:25:2

24var (
25 md5CryptPwdPrefixes = []string{"$1$", "$apr1$"}
26 bcryptPwdPrefixes = []string{"$2a$", "$2$", "$2x$", "$2y$", "$2b$"}

examples/ldapauthserver/logger/sync_wrapper.go1

1:9package-commentspackage should have a documentation comment

examples/ldapauthserver/logger/sync_wrapper.go:1:9

1package logger
2

internal/common/eventmanager.go1

2265:47range-value-addresstaking the address of range value folder can be misleading

internal/common/eventmanager.go:2265:47

2264 }
2265 err = dataprovider.UpdateVirtualFolderQuota(&folder, numFiles, size, true)
2266 if err != nil {

internal/common/common_test.go1

973:18redundant-conversionconversion from int32 to the identical type is redundant

internal/common/common_test.go:973:18

972 }, 1*time.Second, 200*time.Millisecond)
973 assert.Equal(t, int32(0), Connections.GetClientConnections())
974 stopEventScheduler()

internal/dataprovider/dataprovider.go1

2812:6slice-preallocationpreallocate virtualFolders with capacity len(range source) before appending once per iteration

internal/dataprovider/dataprovider.go:2812:6

2811 }
2812 var virtualFolders []vfs.VirtualFolder
2813 folderMounts := make(map[folderMountKey]bool)

internal/common/defendermem.go1

345:1top-level-declaration-ordertop-level declarations should be ordered as const, var, type, then func

internal/common/defendermem.go:345:1

344
345type kv struct {
346 Key string

internal/httpd/httpd_test.go1

3542:46unchecked-type-assertionuse the checked two-result form of the type assertion

internal/httpd/httpd_test.go:3542:46

3541 assert.NoError(t, err)
3542 adminToken := responseHolder["access_token"].(string)
3543 assert.NotEmpty(t, adminToken)

internal/common/transferschecker.go1

296:7unused-receiverreceiver t is unused

internal/common/transferschecker.go:296:7

295
296func (t *transfersCheckerDB) AddTransfer(transfer dataprovider.ActiveTransfer) {
297 dataprovider.AddActiveTransfer(transfer)

examples/ldapauthserver/logger/request_logger.go1

65:41use-anyuse any instead of interface{}

examples/ldapauthserver/logger/request_logger.go:65:41

64// Panic logs panics
65func (l *StructuredLoggerEntry) Panic(v interface{}, stack []byte) {
66 l.Logger.Error().

internal/ftpd/internal_test.go1

946:13use-errors-newreplace fmt.Errorf with errors.New for a static message

internal/ftpd/internal_test.go:946:13

945 assert.NoError(t, err)
946 errFake := fmt.Errorf("fake upload error")
947 go func() {

internal/command/command_test.go1

171:13add-constantstring literal "path" appears more than twice; define a constant

internal/command/command_test.go:171:13

170 {
171 Path: "path",
172 Timeout: 30,

internal/cmd/portable.go1

458:6cognitive-complexityfunction has cognitive complexity 17; maximum is 7

internal/cmd/portable.go:458:6

457
458func parsePatternsFilesFilters() []sdk.PatternsFilter {
459 var patterns []sdk.PatternsFilter

internal/dataprovider/pgsql.go1

321:72confusing-resultsadjacent unnamed results of the same type should be named

internal/dataprovider/pgsql.go:321:72

320
321func getPGSQLHostsAndPorts(configHost string, configPort int) (string, string) {
322 var hosts, ports []string

internal/common/connection.go1

767:26cyclomatic-complexityfunction complexity is 14; maximum is 10

internal/common/connection.go:767:26

766// Copy virtualSourcePath to virtualTargetPath
767func (c *BaseConnection) Copy(virtualSourcePath, virtualTargetPath string) error {
768 copyFromSource := strings.HasSuffix(virtualSourcePath, "/")

internal/cmd/genman.go1

48:6deep-exitprocess-exit calls should be confined to main or init

internal/cmd/genman.go:48:6

47 logger.WarnToConsole("Unable to generate man page files: %v", err)
48 os.Exit(1)
49 }

internal/cmd/root.go1

133:2discarded-error-resulterror result returned by viper.BindEnv is discarded

internal/cmd/root.go:133:2

132 viper.SetDefault(configFileKey, defaultConfigFile)
133 viper.BindEnv(configFileKey, "SFTPGO_CONFIG_FILE") //nolint:errcheck
134 cmd.Flags().StringVar(&configFile, configFileFlag, viper.GetString(configFileKey),

examples/ldapauthserver/httpd/models.go1

43:1doc-comment-perioddocumentation comment should end with punctuation

examples/ldapauthserver/httpd/models.go:43:1

42
43// GCSFsConfig defines the configuration for Google Cloud Storage based filesystem
44type GCSFsConfig struct {

internal/webdavd/server.go1

300:3early-returninvert the condition and return early to reduce nesting

internal/webdavd/server.go:300:3

299 if ok {
300 if cachedUser.IsExpired() {
301 dataprovider.RemoveCachedWebDAVUser(username)

internal/dataprovider/sqlcommon.go1

1185:27error-stringserror string should not be capitalized or end with punctuation

internal/dataprovider/sqlcommon.go:1185:27

1184 if tlsCert == nil {
1185 return user, errors.New("TLS certificate cannot be null or empty")
1186 }

internal/webdavd/internal_test.go1

1195:2excessive-blank-identifiersassignment discards three or more results; name meaningful results or simplify the return contract

internal/webdavd/internal_test.go:1195:2

1194
1195 _, _, _, _, err = server.authenticate(req, ipAddr) //nolint:dogsled
1196 assert.Error(t, err)

internal/command/command.go1

38:2exported-declaration-commentexported declaration should have a comment beginning with its name

internal/command/command.go:38:2

37 HookPostDisconnect = "post_disconnect"
38 HookCheckPassword = "check_password"
39 HookPreLogin = "pre_login"

internal/dataprovider/admin.go1

1:1file-length-limitfile has 661 lines; maximum is 500

internal/dataprovider/admin.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//

internal/config/config.go1

1301:39flag-parameterboolean parameter isSet controls function flow

internal/config/config.go:1301:39

1300
1301func applyFTPDBindingFromEnv(idx int, isSet bool, binding ftpd.Binding) {
1302 if isSet {

internal/cmd/revertprovider.go1

1:1formatfile is not formatted

internal/cmd/revertprovider.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//
  • Fix (safe): run `strider fmt internal/cmd/revertprovider.go`

internal/common/common_test.go1

1736:6function-lengthfunction has 27 statements and 111 lines; maximum is 50 statements or 75 lines

internal/common/common_test.go:1736:6

1735
1736func TestIPList(t *testing.T) {
1737 type test struct {

internal/vfs/azblobfs.go1

225:24function-result-limitfunction returns 4 values; maximum is 3

internal/vfs/azblobfs.go:225:24

224// Open opens the named file for reading
225func (fs *AzureBlobFs) Open(name string, offset int64) (File, PipeReader, func(), error) {
226 r, w, err := createPipeFn(fs.localTempDir, fs.config.DownloadPartSize*int64(fs.config.DownloadConcurrency)+1)

internal/httpd/api_eventrule.go1

31:6get-function-return-valueGet-prefixed function should return a value

internal/httpd/api_eventrule.go:31:6

30
31func getEventActions(w http.ResponseWriter, r *http.Request) {
32 r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)

internal/common/connection.go1

516:2import-shadowingidentifier fs shadows an imported package

internal/common/connection.go:516:2

515func (c *BaseConnection) RemoveDir(virtualPath string) error {
516 fs, fsPath, err := c.GetFsAndResolvedPath(virtualPath)
517 if err != nil {

internal/httpd/httpd_test.go1

24977:33inefficient-sprintffmt.Sprintf is unnecessary for this conversion; use strconv.Itoa

internal/httpd/httpd_test.go:24977:33

24976 form.Set("email_subject", action.Options.EmailConfig.Subject)
24977 form.Set("email_content_type", fmt.Sprintf("%d", action.Options.EmailConfig.ContentType))
24978 form.Set("email_body", action.Options.EmailConfig.Body)

internal/common/common_test.go1

1341:39insecure-url-schemeURL uses insecure http scheme

internal/common/common_test.go:1341:39

1340
1341 Config.PostConnectHook = fmt.Sprintf("http://%v", httpAddr)
1342 assert.NoError(t, Config.ExecutePostConnectHook(ipAddr, ProtocolFTP))

internal/dataprovider/dataprovider.go1

644:6max-public-structsfile declares more than 5 exported structs

internal/dataprovider/dataprovider.go:644:6

643// TransferQuota stores the allowed transfer quota fields
644type TransferQuota struct {
645 ULSize int64

internal/common/connection.go1

770:2modifies-parameterassignment modifies parameter virtualSourcePath

internal/common/connection.go:770:2

769 copyInTarget := strings.HasSuffix(virtualTargetPath, "/")
770 virtualSourcePath = path.Clean(virtualSourcePath)
771 virtualTargetPath = path.Clean(virtualTargetPath)

internal/plugin/plugin.go1

182:24nested-structsmove nested anonymous struct types to named declarations

internal/plugin/plugin.go:182:24

181 hasIPFilter bool
182 concurrencyGuard chan struct{}
183}

internal/vfs/sftpfs.go1

825:5nil-error-returnthis branch proves an error is non-nil but returns nil in an error result

internal/vfs/sftpfs.go:825:5

824 if fs.IsNotExist(err) {
825 return path.Clean(path.Join(append([]string{candidate}, rest...)...)), nil
826 }

internal/dataprovider/sqlcommon.go1

984:3no-defer-in-loopdefer inside a loop runs at function exit, not iteration exit

internal/dataprovider/sqlcommon.go:984:3

983 }
984 defer rows.Close()
985

internal/sftpd/ssh_cmd.go1

111:4no-else-after-returnremove else and unindent its body after the return

internal/sftpd/ssh_cmd.go:111:4

110 return c.handleHashCommands()
111 } else if c.command == "cd" {
112 c.sendExitStatus(nil)

internal/cmd/portable.go1

305:6no-initreplace init with explicit initialization

internal/cmd/portable.go:305:6

304
305func init() {
306 version.AddFeature("+portable")

internal/sftpd/transfer.go1

144:2no-naked-returnreturn values must be explicit

internal/sftpd/transfer.go:144:2

143 t.HandleThrottle()
144 return
145}

examples/ldapauthserver/httpd/auth.go1

26:2no-package-varpackage variables introduce mutable global state

examples/ldapauthserver/httpd/auth.go:26:2

25 md5CryptPwdPrefixes = []string{"$1$", "$apr1$"}
26 bcryptPwdPrefixes = []string{"$2a$", "$2$", "$2x$", "$2y$", "$2b$"}
27)

examples/ldapauthserver/main.go1

1:9package-commentspackage should have a documentation comment

examples/ldapauthserver/main.go:1:9

1package main
2

internal/common/eventmanager.go1

2292:34range-value-addresstaking the address of range value user can be misleading

internal/common/eventmanager.go:2292:34

2291 if params.sender == "" {
2292 if !checkUserConditionOptions(&user, &conditions) {
2293 eventManagerLog(logger.LevelDebug, "skipping scheduled transfer quota reset for user %s, condition options don't match",

internal/common/common_test.go1

1375:18redundant-conversionconversion from int64 to the identical type is redundant

internal/common/common_test.go:1375:18

1374 info = vfs.NewFileInfo(name, false, 33, time.Now(), false)
1375 assert.Equal(t, int64(0), cryptFs.ConvertFileInfo(info).Size())
1376 info = vfs.NewFileInfo(name, false, 1, time.Now(), false)

internal/dataprovider/dataprovider.go1

2978:6slice-preallocationpreallocate validatedKeys with capacity len(range source) before appending once per iteration

internal/dataprovider/dataprovider.go:2978:6

2977 }
2978 var validatedKeys []string
2979 for idx, key := range user.PublicKeys {

internal/common/eventmanager.go1

122:1top-level-declaration-ordertop-level declarations should be ordered as const, var, type, then func

internal/common/eventmanager.go:122:1

121// eventRulesContainer stores event rules by trigger
122type eventRulesContainer struct {
123 sync.RWMutex

internal/httpd/httpd_test.go1

3980:45unchecked-type-assertionuse the checked two-result form of the type assertion

internal/httpd/httpd_test.go:3980:45

3979 assert.NoError(t, err)
3980 userToken := responseHolder["access_token"].(string)
3981 assert.NotEmpty(t, userToken)

internal/common/transferschecker.go1

300:7unused-receiverreceiver t is unused

internal/common/transferschecker.go:300:7

299
300func (t *transfersCheckerDB) RemoveTransfer(ID int64, connectionID string) {
301 dataprovider.RemoveActiveTransfer(ID, connectionID)

internal/httpd/internal_test.go1

390:8use-errors-newreplace fmt.Errorf with errors.New for a static message

internal/httpd/internal_test.go:390:8

389 assert.Equal(t, http.StatusForbidden, respStatus)
390 err = fmt.Errorf("generic error")
391 respStatus = getRespStatus(err)

internal/common/actions_test.go1

89:54add-constantstring literal "path" appears more than twice; define a constant

internal/common/actions_test.go:89:54

88 user.FsConfig.Provider = sdk.GCSFilesystemProvider
89 a = newActionNotification(&user, operationDownload, "path", "vpath", "target", "", "", ProtocolSCP, "", sessionID,
90 123, 0, c.getNotificationStatus(ErrQuotaExceeded), 0, time.Now(), nil)

internal/cmd/portable.go1

493:6cognitive-complexityfunction has cognitive complexity 13; maximum is 7

internal/cmd/portable.go:493:6

492
493func getPatternsFilterValues(value string) (string, []string) {
494 if strings.Contains(value, "::") {

internal/dataprovider/pgsql.go1

398:68confusing-resultsadjacent unnamed results of the same type should be named

internal/dataprovider/pgsql.go:398:68

397
398func (p *PGSQLProvider) getUsedQuota(username string) (int, int64, int64, int64, error) {
399 return sqlCommonGetUsedQuota(username, p.dbHandle)

internal/common/connection.go1

815:26cyclomatic-complexityfunction complexity is 21; maximum is 10

internal/common/connection.go:815:26

814
815func (c *BaseConnection) renameInternal(virtualSourcePath, virtualTargetPath string, //nolint:gocyclo
816 checkParentDestination bool, checks int,

internal/cmd/genman.go1

60:5deep-exitprocess-exit calls should be confined to main or init

internal/cmd/genman.go:60:5

59 logger.WarnToConsole("Unable to generate man page files: %v", err)
60 os.Exit(1)
61 }

internal/cmd/root.go1

144:2discarded-error-resulterror result returned by viper.BindPFlag is discarded

internal/cmd/root.go:144:2

143env var too.`)
144 viper.BindPFlag(configFileKey, cmd.Flags().Lookup(configFileFlag)) //nolint:errcheck
145}

examples/ldapauthserver/httpd/models.go1

52:1doc-comment-perioddocumentation comment should end with punctuation

examples/ldapauthserver/httpd/models.go:52:1

51
52// SFTPGoFilesystem defines cloud storage filesystem details
53type SFTPGoFilesystem struct {

internal/dataprovider/sqlite_disabled.go1

30:20error-stringserror string should not be capitalized or end with punctuation

internal/dataprovider/sqlite_disabled.go:30:20

29func initializeSQLiteProvider(_ string) error {
30 return errors.New("SQLite disabled at build time")
31}

internal/command/command.go1

39:2exported-declaration-commentexported declaration should have a comment beginning with its name

internal/command/command.go:39:2

38 HookCheckPassword = "check_password"
39 HookPreLogin = "pre_login"
40 HookPostLogin = "post_login"

internal/dataprovider/bolt.go1

1:1file-length-limitfile has 3955 lines; maximum is 500

internal/dataprovider/bolt.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//

internal/config/config.go1

1957:22flag-parameterboolean parameter isSet controls function flow

internal/config/config.go:1957:22

1956
1957func setHTTPDBinding(isSet bool, binding httpd.Binding, idx int) {
1958 if isSet {

internal/cmd/root.go1

1:1formatfile is not formatted

internal/cmd/root.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//
  • Fix (safe): run `strider fmt internal/cmd/root.go`

internal/common/common_test.go1

1848:6function-lengthfunction has 41 statements and 105 lines; maximum is 50 statements or 75 lines

internal/common/common_test.go:1848:6

1847
1848func TestSQLPlaceholderLimits(t *testing.T) {
1849 numGroups := 120

internal/vfs/azblobfs.go1

247:24function-result-limitfunction returns 4 values; maximum is 3

internal/vfs/azblobfs.go:247:24

246// Create creates or opens the named file for writing
247func (fs *AzureBlobFs) Create(name string, flag, checks int) (File, PipeWriter, func(), error) {
248 if checks&CheckParentDir != 0 {

internal/httpd/api_eventrule.go1

63:6get-function-return-valueGet-prefixed function should return a value

internal/httpd/api_eventrule.go:63:6

62
63func getEventActionByName(w http.ResponseWriter, r *http.Request) {
64 r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)

internal/common/connection.go1

552:2import-shadowingidentifier fs shadows an imported package

internal/common/connection.go:552:2

551func (c *BaseConnection) doRecursiveRemoveDirEntry(virtualPath string, info os.FileInfo, recursion int) error {
552 fs, fsPath, err := c.GetFsAndResolvedPath(virtualPath)
553 if err != nil {

internal/httpd/httpd_test.go1

25003:19inefficient-sprintffmt.Sprintf is unnecessary for this conversion; use strconv.Itoa

internal/httpd/httpd_test.go:25003:19

25002 action.Type = dataprovider.ActionTypeDataRetentionCheck
25003 form.Set("type", fmt.Sprintf("%d", action.Type))
25004 form.Set("data_retention[10][folder_retention_path]", "p1")

internal/common/common_test.go1

1623:31insecure-url-schemeURL uses insecure http scheme

internal/common/common_test.go:1623:31

1622 assert.True(t, res)
1623 sasURL := kms.NewPlainSecret("http://127.0.0.1/sasurl")
1624 fs = vfs.Filesystem{

internal/dataprovider/dataprovider.go1

681:6max-public-structsfile declares more than 5 exported structs

internal/dataprovider/dataprovider.go:681:6

680// DefenderEntry defines a defender entry
681type DefenderEntry struct {
682 ID int64 `json:"-"`

internal/common/connection.go1

771:2modifies-parameterassignment modifies parameter virtualTargetPath

internal/common/connection.go:771:2

770 virtualSourcePath = path.Clean(virtualSourcePath)
771 virtualTargetPath = path.Clean(virtualTargetPath)
772 if virtualSourcePath == virtualTargetPath {

internal/plugin/plugin.go1

192:31nested-structsmove nested anonymous struct types to named declarations

internal/plugin/plugin.go:192:31

191 authScopes: -1,
192 concurrencyGuard: make(chan struct{}, 250),
193 }

internal/webdavd/webdavd.go1

286:4nil-error-returnthis branch proves an error is non-nil but returns nil in an error result

internal/webdavd/webdavd.go:286:4

285 logger.Error(logSender, "", "unable to load acme cert file %q: %v", crt, err)
286 return nil
287 }

internal/dataprovider/sqlcommon.go1

1014:3no-defer-in-loopdefer inside a loop runs at function exit, not iteration exit

internal/dataprovider/sqlcommon.go:1014:3

1013 ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
1014 defer cancel()
1015

internal/sftpd/ssh_cmd.go1

119:4no-else-after-returnremove else and unindent its body after the return

internal/sftpd/ssh_cmd.go:119:4

118 return c.handleSFTPGoCopy()
119 } else if c.command == "sftpgo-remove" {
120 return c.handleSFTPGoRemove()

internal/cmd/portable_disabled.go1

21:6no-initreplace init with explicit initialization

internal/cmd/portable_disabled.go:21:6

20
21func init() {
22 version.AddFeature("-portable")

internal/webdavd/file.go1

234:3no-naked-returnreturn values must be explicit

internal/webdavd/file.go:234:3

233 err = f.ConvertError(err)
234 return
235 }

examples/ldapauthserver/httpd/httpd.go1

29:2no-package-varpackage variables introduce mutable global state

examples/ldapauthserver/httpd/httpd.go:29:2

28var (
29 ldapConfig config.LDAPConfig
30 httpAuth httpAuthProvider

examples/ldapauthserver/utils/utils.go1

1:9package-commentspackage should have a documentation comment

examples/ldapauthserver/utils/utils.go:1:9

1package utils
2

internal/common/eventmanager.go1

2299:46range-value-addresstaking the address of range value user can be misleading

internal/common/eventmanager.go:2299:46

2298 executed++
2299 err = dataprovider.UpdateUserTransferQuota(&user, 0, 0, true)
2300 if err != nil {

internal/common/common_test.go1

1377:18redundant-conversionconversion from int64 to the identical type is redundant

internal/common/common_test.go:1377:18

1376 info = vfs.NewFileInfo(name, false, 1, time.Now(), false)
1377 assert.Equal(t, int64(0), cryptFs.ConvertFileInfo(info).Size())
1378}

internal/dataprovider/dataprovider.go1

3022:2slice-preallocationpreallocate filteredPaths with capacity len(range source) before appending once per iteration

internal/dataprovider/dataprovider.go:3022:2

3021 }
3022 filteredPaths := []string{}
3023 var filters []sdk.PatternsFilter

internal/common/eventmanager_test.go1

2134:1top-level-declaration-ordertop-level declarations should be ordered as const, var, type, then func

internal/common/eventmanager_test.go:2134:1

2133
2134type testWriter struct {
2135 errTest error

internal/httpd/httpd_test.go1

4086:45unchecked-type-assertionuse the checked two-result form of the type assertion

internal/httpd/httpd_test.go:4086:45

4085 assert.NoError(t, err)
4086 userToken := responseHolder["access_token"].(string)
4087 assert.NotEmpty(t, userToken)

internal/common/transferschecker.go1

304:7unused-receiverreceiver t is unused

internal/common/transferschecker.go:304:7

303
304func (t *transfersCheckerDB) UpdateTransferCurrentSizes(ulSize, dlSize, ID int64, connectionID string) {
305 dataprovider.UpdateActiveTransferSizes(ulSize, dlSize, ID, connectionID)

internal/httpd/middleware.go1

380:27use-errors-newreplace fmt.Errorf with errors.New for a static message

internal/httpd/middleware.go:380:27

379 logger.Debug(logSender, "", "the node token has been invalidated")
380 sendAPIResponse(w, r, fmt.Errorf("the provided token is not valid"), "", http.StatusUnauthorized)
381 return

internal/common/actions_test.go1

89:62add-constantstring literal "vpath" appears more than twice; define a constant

internal/common/actions_test.go:89:62

88 user.FsConfig.Provider = sdk.GCSFilesystemProvider
89 a = newActionNotification(&user, operationDownload, "path", "vpath", "target", "", "", ProtocolSCP, "", sessionID,
90 123, 0, c.getNotificationStatus(ErrQuotaExceeded), 0, time.Now(), nil)

internal/cmd/serve.go1

89:6cognitive-complexityfunction has cognitive complexity 23; maximum is 7

internal/cmd/serve.go:89:6

88
89func checkServeParamsFromEnvFiles(configDir string) { //nolint:gocyclo
90 // The logger is not yet initialized here, we have no way to report errors.

internal/dataprovider/pgsql.go1

398:75confusing-resultsadjacent unnamed results of the same type should be named

internal/dataprovider/pgsql.go:398:75

397
398func (p *PGSQLProvider) getUsedQuota(username string) (int, int64, int64, int64, error) {
399 return sqlCommonGetUsedQuota(username, p.dbHandle)

internal/common/connection.go1

905:26cyclomatic-complexityfunction complexity is 15; maximum is 10

internal/common/connection.go:905:26

904// CreateSymlink creates fsTargetPath as a symbolic link to fsSourcePath
905func (c *BaseConnection) CreateSymlink(virtualSourcePath, virtualTargetPath string) error {
906 var relativePath string

internal/cmd/initprovider.go1

68:5deep-exitprocess-exit calls should be confined to main or init

internal/cmd/initprovider.go:68:5

67 logger.ErrorToConsole("Unable to initialize KMS: %v", err)
68 os.Exit(1)
69 }

internal/cmd/root.go1

149:2discarded-error-resulterror result returned by viper.BindEnv is discarded

internal/cmd/root.go:149:2

148 viper.SetDefault(loadDataFromKey, defaultLoadDataFrom)
149 viper.BindEnv(loadDataFromKey, "SFTPGO_LOADDATA_FROM") //nolint:errcheck
150 cmd.Flags().StringVar(&loadDataFrom, loadDataFromFlag, viper.GetString(loadDataFromKey),

examples/ldapauthserver/httpd/models.go1

65:1doc-comment-perioddocumentation comment should end with punctuation

examples/ldapauthserver/httpd/models.go:65:1

64
65// SFTPGoUser defines an SFTPGo user
66type SFTPGoUser struct {

internal/ftpd/handler.go1

38:35error-stringserror string should not be capitalized or end with punctuation

internal/ftpd/handler.go:38:35

37 errNotImplemented = errors.New("not implemented")
38 errCOMBNotSupported = errors.New("COMB is not supported for this filesystem")
39)

internal/command/command.go1

40:2exported-declaration-commentexported declaration should have a comment beginning with its name

internal/command/command.go:40:2

39 HookPreLogin = "pre_login"
40 HookPostLogin = "post_login"
41 HookExternalAuth = "external_auth"

internal/dataprovider/configs.go1

1:1file-length-limitfile has 653 lines; maximum is 500

internal/dataprovider/configs.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//

internal/dataprovider/admin.go1

511:30flag-parameterboolean parameter reload controls function flow

internal/dataprovider/admin.go:511:30

510// RenderAsJSON implements the renderer interface used within plugins
511func (a *Admin) RenderAsJSON(reload bool) ([]byte, error) {
512 if reload {

internal/cmd/service_windows.go1

1:1formatfile is not formatted

internal/cmd/service_windows.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//
  • Fix (safe): run `strider fmt internal/cmd/service_windows.go`

internal/common/connection.go1

815:26function-lengthfunction has 54 statements and 86 lines; maximum is 50 statements or 75 lines

internal/common/connection.go:815:26

814
815func (c *BaseConnection) renameInternal(virtualSourcePath, virtualTargetPath string, //nolint:gocyclo
816 checkParentDestination bool, checks int,

internal/vfs/cryptfs.go1

76:20function-result-limitfunction returns 4 values; maximum is 3

internal/vfs/cryptfs.go:76:20

75// Open opens the named file for reading
76func (fs *CryptFs) Open(name string, offset int64) (File, PipeReader, func(), error) {
77 f, key, err := fs.getFileAndEncryptionKey(name)

internal/httpd/api_eventrule.go1

154:6get-function-return-valueGet-prefixed function should return a value

internal/httpd/api_eventrule.go:154:6

153
154func getEventRules(w http.ResponseWriter, r *http.Request) {
155 r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)

internal/common/connection.go1

559:44import-shadowingidentifier fs shadows an imported package

internal/common/connection.go:559:44

558
559func (c *BaseConnection) doRecursiveRemove(fs vfs.Fs, fsPath, virtualPath string, info os.FileInfo, recursion int) error {
560 if info.IsDir() {

internal/httpd/httpd_test.go1

25050:19inefficient-sprintffmt.Sprintf is unnecessary for this conversion; use strconv.Itoa

internal/httpd/httpd_test.go:25050:19

25049 }
25050 form.Set("type", fmt.Sprintf("%d", action.Type))
25051 form.Set("fs_mkdir_paths", strings.Join(action.Options.FsConfig.MkDirs, ","))

internal/common/common_test.go1

1656:49insecure-url-schemeURL uses insecure http scheme

internal/common/common_test.go:1656:49

1655 fs.AzBlobConfig.AccountName = "a"
1656 other.AzBlobConfig.SASURL = kms.NewPlainSecret("http://127.1.1.1/sasurl")
1657 err = other.Validate("data2")

internal/dataprovider/dataprovider.go1

717:6max-public-structsfile declares more than 5 exported structs

internal/dataprovider/dataprovider.go:717:6

716// BackupData defines the structure for the backup/restore files
717type BackupData struct {
718 Users []User `json:"users"`

internal/common/connection.go1

846:3modifies-parameterassignment modifies parameter checkParentDestination

internal/common/connection.go:846:3

845 if err == nil {
846 checkParentDestination = false
847 if dstInfo.IsDir() {

internal/plugin/plugin.go1

718:24nested-structsmove nested anonymous struct types to named declarations

internal/plugin/plugin.go:718:24

717func (m *Manager) addTask() {
718 m.concurrencyGuard <- struct{}{}
719}

internal/webdavd/webdavd.go1

290:4nil-error-returnthis branch proves an error is non-nil but returns nil in an error result

internal/webdavd/webdavd.go:290:4

289 logger.Error(logSender, "", "unable to load acme key file %q: %v", key, err)
290 return nil
291 }

internal/dataprovider/sqlcommon.go1

1025:3no-defer-in-loopdefer inside a loop runs at function exit, not iteration exit

internal/dataprovider/sqlcommon.go:1025:3

1024 }
1025 defer rows.Close()
1026

internal/vfs/s3fs.go1

203:4no-else-after-returnremove else and unindent its body after the return

internal/vfs/s3fs.go:203:4

202 return NewFileInfo(name, true, 0, time.Unix(0, 0), false), nil
203 } else if err != nil {
204 return nil, err

internal/cmd/reload_windows.go1

47:6no-initreplace init with explicit initialization

internal/cmd/reload_windows.go:47:6

46
47func init() {
48 serviceCmd.AddCommand(reloadCmd)

internal/webdavd/file.go1

237:2no-naked-returnreturn values must be explicit

internal/webdavd/file.go:237:2

236 f.HandleThrottle()
237 return
238}

examples/ldapauthserver/httpd/httpd.go1

30:2no-package-varpackage variables introduce mutable global state

examples/ldapauthserver/httpd/httpd.go:30:2

29 ldapConfig config.LDAPConfig
30 httpAuth httpAuthProvider
31 certMgr *certManager

examples/ldapauthserver/utils/version.go1

1:9package-commentspackage should have a documentation comment

examples/ldapauthserver/utils/version.go:1:9

1package utils
2

internal/common/eventmanager.go1

2358:34range-value-addresstaking the address of range value user can be misleading

internal/common/eventmanager.go:2358:34

2357 if params.sender == "" {
2358 if !checkUserConditionOptions(&user, &conditions) {
2359 eventManagerLog(logger.LevelDebug, "skipping scheduled retention check for user %s, condition options don't match",

internal/common/common_test.go1

1396:19redundant-conversionconversion from int64 to the identical type is redundant

internal/common/common_test.go:1396:19

1395 require.True(t, slices.Contains(folderCopy.Users, "user2"))
1396 require.Equal(t, int64(1), folderCopy.ID)
1397 require.Equal(t, folder.Name, folderCopy.Name)

internal/dataprovider/dataprovider.go1

3023:6slice-preallocationpreallocate filters with capacity len(range source) before appending once per iteration

internal/dataprovider/dataprovider.go:3023:6

3022 filteredPaths := []string{}
3023 var filters []sdk.PatternsFilter
3024 for _, f := range baseFilters.FilePatterns {

internal/common/protocol_test.go1

10174:1top-level-declaration-ordertop-level declarations should be ordered as const, var, type, then func

internal/common/protocol_test.go:10174:1

10173
10174type receivedEmail struct {
10175 sync.RWMutex

internal/httpd/httpd_test.go1

4277:40unchecked-type-assertionuse the checked two-result form of the type assertion

internal/httpd/httpd_test.go:4277:40

4276 assert.NoError(t, err)
4277 token = responseHolder["access_token"].(string)
4278 assert.NotEmpty(t, token)

internal/dataprovider/admin.go1

579:7unused-receiverreceiver a is unused

internal/dataprovider/admin.go:579:7

578// GetValidPerms returns the allowed admin permissions
579func (a *Admin) GetValidPerms() []string {
580 return validAdminPerms

internal/httpd/middleware.go1

386:27use-errors-newreplace fmt.Errorf with errors.New for a static message

internal/httpd/middleware.go:386:27

385 logger.Debug(logSender, "", "unable to authenticate node token %q: %v", bearer, err)
386 sendAPIResponse(w, r, fmt.Errorf("the provided token cannot be authenticated"), "", http.StatusUnauthorized)
387 return

internal/common/actions_test.go1

89:71add-constantstring literal "target" appears more than twice; define a constant

internal/common/actions_test.go:89:71

88 user.FsConfig.Provider = sdk.GCSFilesystemProvider
89 a = newActionNotification(&user, operationDownload, "path", "vpath", "target", "", "", ProtocolSCP, "", sessionID,
90 123, 0, c.getNotificationStatus(ErrQuotaExceeded), 0, time.Now(), nil)

internal/command/command.go1

91:17cognitive-complexityfunction has cognitive complexity 22; maximum is 7

internal/command/command.go:91:17

90// Initialize configures commands
91func (c Config) Initialize() error {
92 if c.Timeout < minTimeout || c.Timeout > maxTimeout {

internal/dataprovider/quotaupdater.go1

176:77confusing-resultsadjacent unnamed results of the same type should be named

internal/dataprovider/quotaupdater.go:176:77

175
176func (q *quotaUpdater) getUserPendingTransferQuota(username string) (int64, int64) {
177 q.RLock()

internal/common/connection.go1

965:26cyclomatic-complexityfunction complexity is 14; maximum is 10

internal/common/connection.go:965:26

964
965func (c *BaseConnection) doStatInternal(virtualPath string, mode int, checkFilePatterns,
966 convertResult bool,

internal/cmd/initprovider.go1

73:6deep-exitprocess-exit calls should be confined to main or init

internal/cmd/initprovider.go:73:6

72 logger.ErrorToConsole("unable to initialize plugin system: %v", err)
73 os.Exit(1)
74 }

internal/cmd/root.go1

158:2discarded-error-resulterror result returned by viper.BindPFlag is discarded

internal/cmd/root.go:158:2

157`)
158 viper.BindPFlag(loadDataFromKey, cmd.Flags().Lookup(loadDataFromFlag)) //nolint:errcheck
159

examples/ldapauthserver/logger/logger.go1

22:1doc-comment-perioddocumentation comment should end with punctuation

examples/ldapauthserver/logger/logger.go:22:1

21
22// GetLogger get the configured logger instance
23func GetLogger() *zerolog.Logger {

internal/ftpd/server.go1

354:22error-stringserror string should not be capitalized or end with punctuation

internal/ftpd/server.go:354:22

353 logger.Warn(logSender, "", "TLS connection cannot be verified: unable to get verification chain")
354 return errors.New("TLS connection cannot be verified: unable to get verification chain")
355 }

internal/command/command.go1

41:2exported-declaration-commentexported declaration should have a comment beginning with its name

internal/command/command.go:41:2

40 HookPostLogin = "post_login"
41 HookExternalAuth = "external_auth"
42 HookKeyboardInteractive = "keyboard_interactive"

internal/dataprovider/dataprovider.go1

1:1file-length-limitfile has 4870 lines; maximum is 500

internal/dataprovider/dataprovider.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//

internal/dataprovider/apikey.go1

95:31flag-parameterboolean parameter reload controls function flow

internal/dataprovider/apikey.go:95:31

94// RenderAsJSON implements the renderer interface used within plugins
95func (k *APIKey) RenderAsJSON(reload bool) ([]byte, error) {
96 if reload {

internal/cmd/smtptest.go1

1:1formatfile is not formatted

internal/cmd/smtptest.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//
  • Fix (safe): run `strider fmt internal/cmd/smtptest.go`

internal/common/connection_test.go1

338:6function-lengthfunction has 55 statements and 78 lines; maximum is 50 statements or 75 lines

internal/common/connection_test.go:338:6

337
338func TestUpdateQuotaAfterRename(t *testing.T) {
339 user := dataprovider.User{

internal/vfs/cryptfs.go1

151:20function-result-limitfunction returns 4 values; maximum is 3

internal/vfs/cryptfs.go:151:20

150// Create creates or opens the named file for writing
151func (fs *CryptFs) Create(name string, _, _ int) (File, PipeWriter, func(), error) {
152 root, rel, err := fs.toRootRelative(name)

internal/httpd/api_eventrule.go1

186:6get-function-return-valueGet-prefixed function should return a value

internal/httpd/api_eventrule.go:186:6

185
186func getEventRuleByName(w http.ResponseWriter, r *http.Request) {
187 r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)

internal/common/connection.go1

596:2import-shadowingidentifier fs shadows an imported package

internal/common/connection.go:596:2

595func (c *BaseConnection) RemoveAll(virtualPath string) error {
596 fs, fsPath, err := c.GetFsAndResolvedPath(virtualPath)
597 if err != nil {

internal/httpd/httpd_test.go1

25062:29inefficient-sprintffmt.Sprintf is unnecessary for this conversion; use strconv.Itoa

internal/httpd/httpd_test.go:25062:29

25061
25062 form.Set("fs_action_type", fmt.Sprintf("%d", action.Options.FsConfig.Type))
25063 req, err = http.NewRequest(http.MethodPost, path.Join(webAdminEventActionPath, action.Name),

internal/common/common_test.go1

1676:15insecure-url-schemeURL uses insecure http scheme

internal/common/common_test.go:1676:15

1675 BaseHTTPFsConfig: sdk.BaseHTTPFsConfig{
1676 Endpoint: "http://127.0.0.1/httpfs",
1677 Username: "a",

internal/dataprovider/eventrule.go1

503:6max-public-structsfile declares more than 5 exported structs

internal/dataprovider/eventrule.go:503:6

502// EventActionEmailConfig defines the configuration options for SMTP event actions
503type EventActionEmailConfig struct {
504 Recipients []string `json:"recipients,omitempty"`

internal/common/connection.go1

909:3modifies-parameterassignment modifies parameter virtualSourcePath

internal/common/connection.go:909:3

908 relativePath = virtualSourcePath
909 virtualSourcePath = path.Join(path.Dir(virtualTargetPath), relativePath)
910 c.Log(logger.LevelDebug, "link relative path %q resolved as %q, target path %q",

internal/sftpd/sftpd_test.go1

9329:16nested-structsmove nested anonymous struct types to named declarations

internal/sftpd/sftpd_test.go:9329:16

9328 {0, 0, 0, 3, 'f', 't', 'p'},
9329 ssh.Marshal(struct{ Name string }{Name: "sftpa"}),
9330 ssh.Marshal(struct{ Name string }{Name: "shell"}),

internal/httpd/api_http_user.go1

366:3no-defer-in-loopdefer inside a loop runs at function exit, not iteration exit

internal/httpd/api_http_user.go:366:3

365 }
366 defer file.Close()
367

internal/cmd/resetprovider.go1

84:6no-initreplace init with explicit initialization

internal/cmd/resetprovider.go:84:6

83
84func init() {
85 addConfigFlags(resetProviderCmd)

internal/webdavd/file.go1

257:3no-naked-returnreturn values must be explicit

internal/webdavd/file.go:257:3

256 err = f.ConvertError(err)
257 return
258 }

examples/ldapauthserver/httpd/httpd.go1

31:2no-package-varpackage variables introduce mutable global state

examples/ldapauthserver/httpd/httpd.go:31:2

30 httpAuth httpAuthProvider
31 certMgr *certManager
32 rootCAs *x509.CertPool

internal/acme/account.go1

15:9package-commentspackage should have a documentation comment

internal/acme/account.go:15:9

14
15package acme
16

internal/common/eventmanager.go1

2390:34range-value-addresstaking the address of range value user can be misleading

internal/common/eventmanager.go:2390:34

2389 if params.sender == "" {
2390 if !checkUserConditionOptions(&user, &conditions) {
2391 eventManagerLog(logger.LevelDebug, "skipping expiration check for user %q, condition options don't match",

internal/common/common_test.go1

1412:19redundant-conversionconversion from int64 to the identical type is redundant

internal/common/common_test.go:1412:19

1411 require.True(t, slices.Contains(folderCopy.Users, "user3"))
1412 require.Equal(t, int64(2), folderCopy.ID)
1413 require.Equal(t, folder.Name, folderCopy.Name)

internal/dataprovider/dataprovider.go1

3165:6slice-preallocationpreallocate validateCerts with capacity len(range source) before appending once per iteration

internal/dataprovider/dataprovider.go:3165:6

3164func validateTLSCerts(certs []string) ([]string, error) {
3165 var validateCerts []string
3166 for idx, cert := range certs {

internal/common/ratelimiter.go1

41:1top-level-declaration-ordertop-level declarations should be ordered as const, var, type, then func

internal/common/ratelimiter.go:41:1

40// Supported rate limiter types
41const (
42 rateLimiterTypeGlobal RateLimiterType = iota + 1

internal/httpd/httpd_test.go1

4412:45unchecked-type-assertionuse the checked two-result form of the type assertion

internal/httpd/httpd_test.go:4412:45

4411 assert.NoError(t, err)
4412 userToken := responseHolder["access_token"].(string)
4413 assert.NotEmpty(t, userToken)

internal/dataprovider/admin.go1

584:7unused-receiverreceiver a is unused

internal/dataprovider/admin.go:584:7

583// CanManageMFA returns true if the admin can add a multi-factor authentication configuration
584func (a *Admin) CanManageMFA() bool {
585 return len(mfa.GetAvailableTOTPConfigs()) > 0

internal/httpd/middleware.go1

446:27use-errors-newreplace fmt.Errorf with errors.New for a static message

internal/httpd/middleware.go:446:27

445 apiKey, k.Scope, scope)
446 sendAPIResponse(w, r, fmt.Errorf("the provided api key is invalid for this request"), "", http.StatusForbidden)
447 return

internal/common/actions_test.go1

96:18add-constantstring literal "gcsbucket" appears more than twice; define a constant

internal/common/actions_test.go:96:18

95 123, 0, c.getNotificationStatus(fmt.Errorf("wrapper quota error: %w", ErrQuotaExceeded)), 0, time.Now(), nil)
96 assert.Equal(t, "gcsbucket", a.Bucket)
97 assert.Equal(t, 0, len(a.Endpoint))

internal/common/actions.go1

132:6cognitive-complexityfunction has cognitive complexity 10; maximum is 7

internal/common/actions.go:132:6

131// ExecuteActionNotification executes the defined hook, if any, for the specified action
132func ExecuteActionNotification(conn *BaseConnection, operation, filePath, virtualPath, target, virtualTarget, sshCmd string,
133 fileSize int64, err error, elapsed int64, metadata map[string]string,

internal/dataprovider/sqlcommon.go1

1279:76confusing-resultsadjacent unnamed results of the same type should be named

internal/dataprovider/sqlcommon.go:1279:76

1278
1279func sqlCommonGetUsedQuota(username string, dbHandle *sql.DB) (int, int64, int64, int64, error) {
1280 ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)

internal/common/connection.go1

1105:26cyclomatic-complexityfunction complexity is 12; maximum is 10

internal/common/connection.go:1105:26

1104// SetStat set StatAttributes for the specified fsPath
1105func (c *BaseConnection) SetStat(virtualPath string, attributes *StatAttributes) error {
1106 if ok, policy := c.User.IsFileAllowed(virtualPath); !ok {

internal/cmd/initprovider.go1

83:5deep-exitprocess-exit calls should be confined to main or init

internal/cmd/initprovider.go:83:5

82 logger.ErrorToConsole("Unable to initialize MFA: %v", err)
83 os.Exit(1)
84 }

internal/cmd/root.go1

161:2discarded-error-resulterror result returned by viper.BindEnv is discarded

internal/cmd/root.go:161:2

160 viper.SetDefault(loadDataModeKey, defaultLoadDataMode)
161 viper.BindEnv(loadDataModeKey, "SFTPGO_LOADDATA_MODE") //nolint:errcheck
162 cmd.Flags().IntVar(&loadDataMode, loadDataModeFlag, viper.GetInt(loadDataModeKey),

examples/ldapauthserver/logger/logger.go1

27:1doc-comment-perioddocumentation comment should end with punctuation

examples/ldapauthserver/logger/logger.go:27:1

26
27// InitLogger initialize loggers
28func InitLogger(logFilePath string, logMaxSize, logMaxBackups, logMaxAge int, logCompress bool, level zerolog.Level) {

internal/httpd/httpd_test.go1

27665:14error-stringserror string should not be capitalized or end with punctuation

internal/httpd/httpd_test.go:27665:14

27664 if result != tt.expected {
27665 t.Errorf("IsNameValid(%q) = %v, expected %v", tt.input, result, tt.expected)
27666 }

internal/command/command.go1

42:2exported-declaration-commentexported declaration should have a comment beginning with its name

internal/command/command.go:42:2

41 HookExternalAuth = "external_auth"
42 HookKeyboardInteractive = "keyboard_interactive"
43)

internal/dataprovider/eventrule.go1

1:1file-length-limitfile has 1943 lines; maximum is 500

internal/dataprovider/eventrule.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//

internal/dataprovider/bolt.go1

321:93flag-parameterboolean parameter reset controls function flow

internal/dataprovider/bolt.go:321:93

320
321func (p *BoltProvider) updateTransferQuota(username string, uploadSize, downloadSize int64, reset bool) error {
322 return p.dbHandle.Update(func(tx *bolt.Tx) error {

internal/command/command.go1

1:1formatfile is not formatted

internal/command/command.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//
  • Fix (safe): run `strider fmt internal/command/command.go`

internal/common/connection_test.go1

417:6function-lengthfunction has 51 statements and 74 lines; maximum is 50 statements or 75 lines

internal/common/connection_test.go:417:6

416
417func TestErrorsMapping(t *testing.T) {
418 fs := vfs.NewOsFs("", os.TempDir(), "", nil)

internal/vfs/gcsfs.go1

135:18function-result-limitfunction returns 4 values; maximum is 3

internal/vfs/gcsfs.go:135:18

134// Open opens the named file for reading
135func (fs *GCSFs) Open(name string, offset int64) (File, PipeReader, func(), error) {
136 r, w, err := createPipeFn(fs.localTempDir, 0)

internal/httpd/api_folder.go1

31:6get-function-return-valueGet-prefixed function should return a value

internal/httpd/api_folder.go:31:6

30
31func getFolders(w http.ResponseWriter, r *http.Request) {
32 r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)

internal/common/connection.go1

656:3import-shadowingidentifier fs shadows an imported package

internal/common/connection.go:656:3

655 if c.IsSameResource(virtualSourcePath, virtualTargetPath) {
656 fs, fsTargetPath, err := c.GetFsAndResolvedPath(virtualTargetPath)
657 if err != nil {

internal/httpd/httpd_test.go1

25089:29inefficient-sprintffmt.Sprintf is unnecessary for this conversion; use strconv.Itoa

internal/httpd/httpd_test.go:25089:29

25088 }
25089 form.Set("fs_action_type", fmt.Sprintf("%d", action.Options.FsConfig.Type))
25090 form.Set("fs_exist_paths", strings.Join(action.Options.FsConfig.Exist, ","))

internal/common/common_test.go1

1685:15insecure-url-schemeURL uses insecure http scheme

internal/common/common_test.go:1685:15

1684 BaseHTTPFsConfig: sdk.BaseHTTPFsConfig{
1685 Endpoint: "http://127.0.0.1/httpfs",
1686 Username: "b",

internal/dataprovider/eventrule.go1

582:6max-public-structsfile declares more than 5 exported structs

internal/dataprovider/eventrule.go:582:6

581// FolderRetention defines a folder retention configuration
582type FolderRetention struct {
583 // Path is the virtual directory path, if no other specific retention is defined,

internal/common/connection.go1

1374:3modifies-parameterassignment modifies parameter quotaResult

internal/common/connection.go:1374:3

1373 sourcePath, quotaResult.UsedSize, sizeDiff)
1374 quotaResult.UsedSize += sizeDiff
1375 return quotaResult.GetRemainingSize() >= 0

internal/sftpd/sftpd_test.go1

9330:16nested-structsmove nested anonymous struct types to named declarations

internal/sftpd/sftpd_test.go:9330:16

9329 ssh.Marshal(struct{ Name string }{Name: "sftpa"}),
9330 ssh.Marshal(struct{ Name string }{Name: "shell"}),
9331 }

internal/plugin/plugin.go1

583:4no-defer-in-loopdefer inside a loop runs at function exit, not iteration exit

internal/plugin/plugin.go:583:4

582 if n.exited() {
583 defer func(cfg Config, index int) {
584 Handler.restartNotifierPlugin(cfg, index)

internal/cmd/resetpwd.go1

122:6no-initreplace init with explicit initialization

internal/cmd/resetpwd.go:122:6

121
122func init() {
123 addConfigFlags(resetPwdCmd)

internal/webdavd/file.go1

260:2no-naked-returnreturn values must be explicit

internal/webdavd/file.go:260:2

259 f.HandleThrottle()
260 return
261}

examples/ldapauthserver/httpd/httpd.go1

32:2no-package-varpackage variables introduce mutable global state

examples/ldapauthserver/httpd/httpd.go:32:2

31 certMgr *certManager
32 rootCAs *x509.CertPool
33)

internal/bundle/bundle.go1

17:9package-commentspackage should have a documentation comment

internal/bundle/bundle.go:17:9

16
17package bundle
18

internal/common/eventmanager.go1

2455:34range-value-addresstaking the address of range value user can be misleading

internal/common/eventmanager.go:2455:34

2454 if params.sender == "" {
2455 if !checkUserConditionOptions(&user, &conditions) {
2456 eventManagerLog(logger.LevelDebug, "skipping inactivity check for user %q, condition options don't match",

internal/common/common_test.go1

1516:18redundant-conversionconversion from uint16 to the identical type is redundant

internal/common/common_test.go:1516:18

1515 tlsVer := util.GetTLSVersion(0)
1516 assert.Equal(t, uint16(tls.VersionTLS12), tlsVer)
1517 tlsVer = util.GetTLSVersion(12)

internal/dataprovider/dataprovider.go1

4795:6slice-preallocationpreallocate result with capacity len(range source) before appending once per iteration

internal/dataprovider/dataprovider.go:4795:6

4794func updateEventActionPlaceholders(actions []BaseEventAction) ([]BaseEventAction, error) {
4795 var result []BaseEventAction
4796

internal/common/transferschecker.go1

57:1top-level-declaration-ordertop-level declarations should be ordered as const, var, type, then func

internal/common/transferschecker.go:57:1

56
57type baseTransferChecker struct {
58 transfers []dataprovider.ActiveTransfer

internal/httpd/httpd_test.go1

4493:46unchecked-type-assertionuse the checked two-result form of the type assertion

internal/httpd/httpd_test.go:4493:46

4492 assert.NoError(t, err)
4493 adminToken := responseHolder["access_token"].(string)
4494 assert.NotEmpty(t, adminToken)

internal/dataprovider/bolt.go1

1210:7unused-receiverreceiver p is unused

internal/dataprovider/bolt.go:1210:7

1209
1210func (p *BoltProvider) deleteFolderMappings(folder vfs.BaseVirtualFolder, usersBucket, groupsBucket *bolt.Bucket) error {
1211 for _, username := range folder.Users {

internal/httpd/middleware.go1

452:27use-errors-newreplace fmt.Errorf with errors.New for a static message

internal/httpd/middleware.go:452:27

451 logger.Debug(logSender, "", "unable to authenticate api key %q: %v", apiKey, err)
452 sendAPIResponse(w, r, fmt.Errorf("the provided api key cannot be authenticated"), "", http.StatusUnauthorized)
453 return

internal/common/actions_test.go1

115:18add-constantstring literal "azcontainer" appears more than twice; define a constant

internal/common/actions_test.go:115:18

114 123, os.O_APPEND, c.getNotificationStatus(nil), 0, time.Now(), nil)
115 assert.Equal(t, "azcontainer", a.Bucket)
116 assert.Equal(t, "azendpoint", a.Endpoint)

internal/common/common.go1

191:6cognitive-complexityfunction has cognitive complexity 24; maximum is 7

internal/common/common.go:191:6

190// Initialize sets the common configuration
191func Initialize(c Configuration, isShared int) error {
192 isShuttingDown.Store(false)

internal/dataprovider/sqlcommon.go1

1279:83confusing-resultsadjacent unnamed results of the same type should be named

internal/dataprovider/sqlcommon.go:1279:83

1278
1279func sqlCommonGetUsedQuota(username string, dbHandle *sql.DB) (int, int64, int64, int64, error) {
1280 ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)

internal/common/connection.go1

1274:26cyclomatic-complexityfunction complexity is 13; maximum is 10

internal/common/connection.go:1274:26

1273
1274func (c *BaseConnection) isRenamePermitted(fsSrc, fsDst vfs.Fs, fsSourcePath, fsTargetPath, virtualSourcePath,
1275 virtualTargetPath string, srcInfo os.FileInfo,

internal/cmd/initprovider.go1

99:5deep-exitprocess-exit calls should be confined to main or init

internal/cmd/initprovider.go:99:5

98 logger.ErrorToConsole("Unable to initialize/update the data provider: %v", err)
99 os.Exit(1)
100 }

internal/cmd/root.go1

171:2discarded-error-resulterror result returned by viper.BindPFlag is discarded

internal/cmd/root.go:171:2

170`)
171 viper.BindPFlag(loadDataModeKey, cmd.Flags().Lookup(loadDataModeFlag)) //nolint:errcheck
172

examples/ldapauthserver/logger/logger.go1

49:1doc-comment-perioddocumentation comment should end with punctuation

examples/ldapauthserver/logger/logger.go:49:1

48// DisableLogger disable the main logger.
49// ConsoleLogger will not be affected
50func DisableLogger() {

internal/httpd/httpd_test.go1

28019:25error-stringserror string should not be capitalized or end with punctuation

internal/httpd/httpd_test.go:28019:25

28018 if csrfToken == "" {
28019 return "", errors.New("CSRF token not found")
28020 }

internal/command/command.go1

72:6exported-declaration-commentexported type should have a comment beginning with its name

internal/command/command.go:72:6

71// program based hooks
72type Config struct {
73 // Timeout specifies a global time limit, in seconds, for the external commands execution

internal/dataprovider/iplist.go1

1:1file-length-limitfile has 532 lines; maximum is 500

internal/dataprovider/iplist.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//

internal/dataprovider/bolt.go1

356:82flag-parameterboolean parameter reset controls function flow

internal/dataprovider/bolt.go:356:82

355
356func (p *BoltProvider) updateQuota(username string, filesAdd int, sizeAdd int64, reset bool) error {
357 return p.dbHandle.Update(func(tx *bolt.Tx) error {

internal/command/command_test.go1

1:1formatfile is not formatted

internal/command/command_test.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//
  • Fix (safe): run `strider fmt internal/command/command_test.go`

internal/common/connection_test.go1

693:6function-lengthfunction has 181 statements and 392 lines; maximum is 50 statements or 75 lines

internal/common/connection_test.go:693:6

692
693func TestFilePatterns(t *testing.T) {
694 filters := dataprovider.UserFilters{

internal/vfs/gcsfs.go1

177:18function-result-limitfunction returns 4 values; maximum is 3

internal/vfs/gcsfs.go:177:18

176// Create creates or opens the named file for writing
177func (fs *GCSFs) Create(name string, flag, checks int) (File, PipeWriter, func(), error) {
178 if checks&CheckParentDir != 0 {

internal/httpd/api_folder.go1

121:6get-function-return-valueGet-prefixed function should return a value

internal/httpd/api_folder.go:121:6

120
121func getFolderByName(w http.ResponseWriter, r *http.Request) {
122 r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)

internal/common/connection.go1

918:2import-shadowingidentifier fs shadows an imported package

internal/common/connection.go:918:2

917 // we cannot have a cross folder request here so only one fs is enough
918 fs, fsSourcePath, err := c.GetFsAndResolvedPath(virtualSourcePath)
919 if err != nil {

internal/httpd/httpd_test.go1

25124:29inefficient-sprintffmt.Sprintf is unnecessary for this conversion; use strconv.Itoa

internal/httpd/httpd_test.go:25124:29

25123 }
25124 form.Set("fs_action_type", fmt.Sprintf("%d", action.Options.FsConfig.Type))
25125 form.Set("fs_rename[0][fs_rename_source]", action.Options.FsConfig.Renames[0].Key)

internal/common/eventmanager_test.go1

486:15insecure-url-schemeURL uses insecure http scheme

internal/common/eventmanager_test.go:486:15

485 HTTPConfig: dataprovider.EventActionHTTPConfig{
486 Endpoint: "http://localhost",
487 Timeout: 20,

internal/dataprovider/eventrule.go1

606:6max-public-structsfile declares more than 5 exported structs

internal/dataprovider/eventrule.go:606:6

605// EventActionDataRetentionConfig defines the configuration for a data retention check
606type EventActionDataRetentionConfig struct {
607 Folders []FolderRetention `json:"folders,omitempty"`

internal/common/connection.go1

1632:3modifies-parameterassignment modifies parameter numFiles

internal/common/connection.go:1632:3

1631 // calculate them (best effort, may be inaccurate).
1632 numFiles = 1
1633 if fi, err := fs.Stat(targetPath); err == nil {

internal/vfs/azblobfs.go1

947:21nested-structsmove nested anonymous struct types to named declarations

internal/vfs/azblobfs.go:947:21

946 partSize := fs.config.DownloadPartSize
947 guard := make(chan struct{}, fs.config.DownloadConcurrency)
948 blockCtxTimeout := time.Duration(fs.config.DownloadPartSize/(1024*1024)) * time.Minute

internal/plugin/plugin.go1

595:4no-defer-in-loopdefer inside a loop runs at function exit, not iteration exit

internal/plugin/plugin.go:595:4

594 if k.exited() {
595 defer func(cfg Config, index int) {
596 Handler.restartKMSPlugin(cfg, index)

internal/cmd/revertprovider.go1

88:6no-initreplace init with explicit initialization

internal/cmd/revertprovider.go:88:6

87
88func init() {
89 addConfigFlags(revertProviderCmd)

internal/webdavd/webdavd.go1

397:4no-naked-returnreturn values must be explicit

internal/webdavd/webdavd.go:397:4

396 if err == nil {
397 return
398 }

examples/ldapauthserver/logger/logger.go1

18:2no-package-varpackage variables introduce mutable global state

examples/ldapauthserver/logger/logger.go:18:2

17var (
18 logger zerolog.Logger
19 consoleLogger zerolog.Logger

internal/cmd/acme.go1

15:9package-commentspackage should have a documentation comment

internal/cmd/acme.go:15:9

14
15package cmd
16

internal/common/eventmanager.go1

2461:42range-value-addresstaking the address of range value user can be misleading

internal/common/eventmanager.go:2461:42

2460 }
2461 if err = executeInactivityCheckForUser(&user, config, when); err != nil {
2462 params.AddError(err)

internal/common/common_test.go1

1518:18redundant-conversionconversion from uint16 to the identical type is redundant

internal/common/common_test.go:1518:18

1517 tlsVer = util.GetTLSVersion(12)
1518 assert.Equal(t, uint16(tls.VersionTLS12), tlsVer)
1519 tlsVer = util.GetTLSVersion(2)

internal/dataprovider/memory.go1

379:6slice-preallocationpreallocate mappedGroups with capacity len(range source) before appending once per iteration

internal/dataprovider/memory.go:379:6

378 }
379 var mappedGroups []string
380 for idx := range user.Groups {

internal/dataprovider/admin.go1

106:1top-level-declaration-ordertop-level declarations should be ordered as const, var, type, then func

internal/dataprovider/admin.go:106:1

105// AdminPreferences defines the admin preferences
106type AdminPreferences struct {
107 // Allow to hide some sections from the user page.

internal/httpd/httpd_test.go1

4564:45unchecked-type-assertionuse the checked two-result form of the type assertion

internal/httpd/httpd_test.go:4564:45

4563 assert.NoError(t, err)
4564 userToken := responseHolder["access_token"].(string)
4565 assert.NotEmpty(t, userToken)

internal/dataprovider/bolt.go1

2066:7unused-receiverreceiver p is unused

internal/dataprovider/bolt.go:2066:7

2065
2066func (p *BoltProvider) getDefenderHosts(_ int64, _ int) ([]DefenderEntry, error) {
2067 return nil, ErrNotImplemented

internal/httpd/middleware.go1

463:28use-errors-newreplace fmt.Errorf with errors.New for a static message

internal/httpd/middleware.go:463:28

462 apiUser, apiKey, err)
463 sendAPIResponse(w, r, fmt.Errorf("the admin associated with the provided api key cannot be authenticated"),
464 "", http.StatusUnauthorized)

internal/common/actions_test.go1

116:18add-constantstring literal "azendpoint" appears more than twice; define a constant

internal/common/actions_test.go:116:18

115 assert.Equal(t, "azcontainer", a.Bucket)
116 assert.Equal(t, "azendpoint", a.Endpoint)
117 assert.Equal(t, 1, a.Status)

internal/common/common.go1

280:6cognitive-complexityfunction has cognitive complexity 9; maximum is 7

internal/common/common.go:280:6

279// A zero graceTime means no wait
280func WaitForTransfers(graceTime int) {
281 if graceTime == 0 {

internal/dataprovider/sqlcommon.go1

3250:67confusing-resultsadjacent unnamed results of the same type should be named

internal/dataprovider/sqlcommon.go:3250:67

3249
3250func sqlCommonGetAPIKeyRelatedIDs(apiKey *APIKey) (sql.NullInt64, sql.NullInt64, error) {
3251 var userID, adminID sql.NullInt64

internal/common/connection.go1

1308:26cyclomatic-complexityfunction complexity is 14; maximum is 10

internal/common/connection.go:1308:26

1307
1308func (c *BaseConnection) hasSpaceForRename(fs vfs.Fs, virtualSourcePath, virtualTargetPath string, initialSize int64,
1309 sourcePath string, srcInfo os.FileInfo) bool {

internal/cmd/initprovider.go1

104:6deep-exitprocess-exit calls should be confined to main or init

internal/cmd/initprovider.go:104:6

103 logger.ErrorToConsole("%v", err)
104 os.Exit(1)
105 }

internal/cmd/root.go1

174:2discarded-error-resulterror result returned by viper.BindEnv is discarded

internal/cmd/root.go:174:2

173 viper.SetDefault(loadDataCleanKey, defaultLoadDataClean)
174 viper.BindEnv(loadDataCleanKey, "SFTPGO_LOADDATA_CLEAN") //nolint:errcheck
175 cmd.Flags().BoolVar(&loadDataClean, loadDataCleanFlag, viper.GetBool(loadDataCleanKey),

examples/ldapauthserver/logger/logger.go1

54:1doc-comment-perioddocumentation comment should end with punctuation

examples/ldapauthserver/logger/logger.go:54:1

53
54// EnableConsoleLogger enables the console logger
55func EnableConsoleLogger(level zerolog.Level) {

internal/httpd/internal_test.go1

4410:25error-stringserror string should not be capitalized or end with punctuation

internal/httpd/internal_test.go:4410:25

4409 if csrfToken == "" {
4410 return "", errors.New("CSRF token not found")
4411 }

internal/common/actions.go1

77:6exported-declaration-commentexported function or method should have a comment beginning with its name

internal/common/actions.go:77:6

76// Do NOT call this function after application initialization.
77func InitializeActionHandler(handler ActionHandler) {
78 actionHandler = handler

internal/dataprovider/memory.go1

1:1file-length-limitfile has 3340 lines; maximum is 500

internal/dataprovider/memory.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//

internal/dataprovider/bolt.go1

1298:84flag-parameterboolean parameter reset controls function flow

internal/dataprovider/bolt.go:1298:84

1297
1298func (p *BoltProvider) updateFolderQuota(name string, filesAdd int, sizeAdd int64, reset bool) error {
1299 return p.dbHandle.Update(func(tx *bolt.Tx) error {

internal/common/actions.go1

1:1formatfile is not formatted

internal/common/actions.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//
  • Fix (safe): run `strider fmt internal/common/actions.go`

internal/common/connection_test.go1

1117:6function-lengthfunction has 87 statements and 115 lines; maximum is 50 statements or 75 lines

internal/common/connection_test.go:1117:6

1116
1117func TestListerAt(t *testing.T) {
1118 dir := t.TempDir()

internal/vfs/httpfs.go1

317:19function-result-limitfunction returns 4 values; maximum is 3

internal/vfs/httpfs.go:317:19

316// Open opens the named file for reading
317func (fs *HTTPFs) Open(name string, offset int64) (File, PipeReader, func(), error) {
318 r, w, err := createPipeFn(fs.localTempDir, 0)

internal/httpd/api_group.go1

30:6get-function-return-valueGet-prefixed function should return a value

internal/httpd/api_group.go:30:6

29
30func getGroups(w http.ResponseWriter, r *http.Request) {
31 r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)

internal/common/connection.go1

984:2import-shadowingidentifier fs shadows an imported package

internal/common/connection.go:984:2

983
984 fs, fsPath, err := c.GetFsAndResolvedPath(virtualPath)
985 if err != nil {

internal/httpd/httpd_test.go1

25152:29inefficient-sprintffmt.Sprintf is unnecessary for this conversion; use strconv.Itoa

internal/httpd/httpd_test.go:25152:29

25151 }
25152 form.Set("fs_action_type", fmt.Sprintf("%d", action.Options.FsConfig.Type))
25153 form.Set("fs_copy[0][fs_copy_source]", action.Options.FsConfig.Copy[0].Key)

internal/common/eventmanager_test.go1

846:20insecure-url-schemeURL uses insecure http scheme

internal/common/eventmanager_test.go:846:20

845 HTTPConfig: dataprovider.EventActionHTTPConfig{
846 Endpoint: "http://foo\x7f.com/", // invalid URL
847 SkipTLSVerify: true,

internal/dataprovider/eventrule.go1

639:6max-public-structsfile declares more than 5 exported structs

internal/dataprovider/eventrule.go:639:6

638// EventActionFsCompress defines the configuration for the compress filesystem action
639type EventActionFsCompress struct {
640 // Archive path

internal/common/connection.go1

1635:5modifies-parameterassignment modifies parameter numFiles

internal/common/connection.go:1635:5

1634 if fi.Mode().IsDir() {
1635 numFiles, filesSize, err = fs.GetDirSize(targetPath)
1636 if err != nil {

internal/vfs/azblobfs.go1

971:12nested-structsmove nested anonymous struct types to named declarations

internal/vfs/azblobfs.go:971:12

970
971 guard <- struct{}{}
972 if hasError.Load() {

internal/plugin/plugin.go1

605:4no-defer-in-loopdefer inside a loop runs at function exit, not iteration exit

internal/plugin/plugin.go:605:4

604 if a.exited() {
605 defer func(cfg Config, index int) {
606 Handler.restartAuthPlugin(cfg, index)

internal/cmd/root.go1

95:6no-initreplace init with explicit initialization

internal/cmd/root.go:95:6

94
95func init() {
96 rootCmd.CompletionOptions.DisableDefaultCmd = true

internal/webdavd/webdavd.go1

400:2no-naked-returnreturn values must be explicit

internal/webdavd/webdavd.go:400:2

399 }
400 return
401}

examples/ldapauthserver/logger/logger.go1

19:2no-package-varpackage variables introduce mutable global state

examples/ldapauthserver/logger/logger.go:19:2

18 logger zerolog.Logger
19 consoleLogger zerolog.Logger
20)

internal/cmd/gen.go1

15:9package-commentspackage should have a documentation comment

internal/cmd/gen.go:15:9

14
15package cmd
16

internal/common/eventmanager.go1

2527:34range-value-addresstaking the address of range value user can be misleading

internal/common/eventmanager.go:2527:34

2526 if params.sender == "" {
2527 if !checkUserConditionOptions(&user, &conditions) {
2528 eventManagerLog(logger.LevelDebug, "skipping password check for user %q, condition options don't match",

internal/common/common_test.go1

1520:18redundant-conversionconversion from uint16 to the identical type is redundant

internal/common/common_test.go:1520:18

1519 tlsVer = util.GetTLSVersion(2)
1520 assert.Equal(t, uint16(tls.VersionTLS12), tlsVer)
1521 tlsVer = util.GetTLSVersion(13)

internal/dataprovider/memory.go1

390:6slice-preallocationpreallocate mappedFolders with capacity len(range source) before appending once per iteration

internal/dataprovider/memory.go:390:6

389 }
390 var mappedFolders []string
391 for idx := range user.VirtualFolders {

internal/dataprovider/apikey.go1

34:1top-level-declaration-ordertop-level declarations should be ordered as const, var, type, then func

internal/dataprovider/apikey.go:34:1

33// Supported API key scopes
34const (
35 // the API key will be used for an admin

internal/httpd/httpd_test.go1

4936:85unchecked-type-assertionuse the checked two-result form of the type assertion

internal/httpd/httpd_test.go:4936:85

4935 assert.NoError(t, err)
4936 assert.Equal(t, dataprovider.ErrInvalidCredentials.Error(), responseHolder["error"].(string))
4937 // wrong username

internal/dataprovider/bolt.go1

2070:7unused-receiverreceiver p is unused

internal/dataprovider/bolt.go:2070:7

2069
2070func (p *BoltProvider) getDefenderHostByIP(_ string, _ int64) (DefenderEntry, error) {
2071 return DefenderEntry{}, ErrNotImplemented

internal/httpdtest/httpdtest.go1

2172:10use-errors-newreplace fmt.Errorf with errors.New for a static message

internal/httpdtest/httpdtest.go:2172:10

2171 if expected.OSConfig.ReadBufferSize != actual.OSConfig.ReadBufferSize {
2172 return fmt.Errorf("read buffer size mismatch")
2173 }

internal/common/actions_test.go1

174:14add-constantstring literal "username" appears more than twice; define a constant

internal/common/actions_test.go:174:14

173 BaseUser: sdk.BaseUser{
174 Username: "username",
175 },

internal/common/common.go1

841:25cognitive-complexityfunction has cognitive complexity 10; maximum is 7

internal/common/common.go:841:25

840// ExecutePostConnectHook executes the post connect hook if defined
841func (c *Configuration) ExecutePostConnectHook(ipAddr, protocol string) error {
842 if c.PostConnectHook == "" {

internal/dataprovider/sqlite.go1

319:69confusing-resultsadjacent unnamed results of the same type should be named

internal/dataprovider/sqlite.go:319:69

318
319func (p *SQLiteProvider) getUsedQuota(username string) (int, int64, int64, int64, error) {
320 return sqlCommonGetUsedQuota(username, p.dbHandle)

internal/common/connection.go1

1343:26cyclomatic-complexityfunction complexity is 14; maximum is 10

internal/common/connection.go:1343:26

1342// hasSpaceForCrossRename checks the quota after a rename between different folders
1343func (c *BaseConnection) hasSpaceForCrossRename(fs vfs.Fs, quotaResult vfs.QuotaCheckResult, initialSize int64,
1344 sourcePath string, srcInfo os.FileInfo,

internal/cmd/initprovider.go1

114:6deep-exitprocess-exit calls should be confined to main or init

internal/cmd/initprovider.go:114:6

113 logger.ErrorToConsole("Cannot load initial data: %v", err)
114 os.Exit(1)
115 }

internal/cmd/root.go1

181:2discarded-error-resulterror result returned by viper.BindPFlag is discarded

internal/cmd/root.go:181:2

180`)
181 viper.BindPFlag(loadDataCleanKey, cmd.Flags().Lookup(loadDataCleanFlag)) //nolint:errcheck
182}

examples/ldapauthserver/logger/logger.go1

64:1doc-comment-perioddocumentation comment should end with punctuation

examples/ldapauthserver/logger/logger.go:64:1

63
64// Debug logs at debug level for the specified sender
65func Debug(prefix, requestID string, format string, v ...interface{}) {

internal/httpd/middleware.go1

520:21error-stringserror string should not be capitalized or end with punctuation

internal/httpd/middleware.go:520:21

519 if !admin.Filters.AllowAPIKeyAuth {
520 return fmt.Errorf("API key authentication disabled for admin %q", admin.Username)
521 }

internal/common/actions.go1

86:6exported-declaration-commentexported function or method should have a comment beginning with its name

internal/common/actions.go:86:6

85// - 2 executed using the event manager
86func ExecutePreAction(conn *BaseConnection, operation, filePath, virtualPath string, fileSize int64, openFlags int) (int, error) {
87 var event *notifier.FsEvent

internal/dataprovider/mysql.go1

1:1file-length-limitfile has 959 lines; maximum is 500

internal/dataprovider/mysql.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//

internal/dataprovider/configs.go1

622:32flag-parameterboolean parameter reload controls function flow

internal/dataprovider/configs.go:622:32

621// RenderAsJSON implements the renderer interface used within plugins
622func (c *Configs) RenderAsJSON(reload bool) ([]byte, error) {
623 if reload {

internal/common/actions_test.go1

1:1formatfile is not formatted

internal/common/actions_test.go:1:1

1// Copyright (C) 2019 Nicola Murino
2//
  • Fix (safe): run `strider fmt internal/common/actions_test.go`

internal/common/connection_test.go1

1233:6function-lengthfunction has 12 statements and 207 lines; maximum is 50 statements or 75 lines

internal/common/connection_test.go:1233:6

1232
1233func TestGetFsAndResolvedPath(t *testing.T) {
1234 homeDir := filepath.Join(os.TempDir(), "home_test")

internal/vfs/httpfs.go1

351:19function-result-limitfunction returns 4 values; maximum is 3

internal/vfs/httpfs.go:351:19

350// Create creates or opens the named file for writing
351func (fs *HTTPFs) Create(name string, flag, checks int) (File, PipeWriter, func(), error) {
352 r, w, err := createPipeFn(fs.localTempDir, 0)

internal/httpd/api_group.go1

119:6get-function-return-valueGet-prefixed function should return a value

internal/httpd/api_group.go:119:6

118
119func getGroupByName(w http.ResponseWriter, r *http.Request) {
120 r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)

internal/common/connection.go1

1031:40import-shadowingidentifier fs shadows an imported package

internal/common/connection.go:1031:40

1030
1031func (c *BaseConnection) ignoreSetStat(fs vfs.Fs) bool {
1032 if Config.SetstatMode == 1 {

internal/httpd/httpd_test.go1

25170:19inefficient-sprintffmt.Sprintf is unnecessary for this conversion; use strconv.Itoa

internal/httpd/httpd_test.go:25170:19

25169 action.Options.PwdExpirationConfig.Threshold = 15
25170 form.Set("type", fmt.Sprintf("%d", action.Type))
25171 form.Set("pwd_expiration_threshold", "a")

internal/common/eventmanager_test.go1

872:51insecure-url-schemeURL uses insecure http scheme

internal/common/eventmanager_test.go:872:51

871 }
872 action.Options.HTTPConfig.Endpoint = fmt.Sprintf("http://%v", httpAddr)
873 params := &EventParams{

internal/dataprovider/eventrule.go1

669:6max-public-structsfile declares more than 5 exported structs

internal/dataprovider/eventrule.go:669:6

668// RenameConfig defines the configuration for a filesystem rename
669type RenameConfig struct {
670 // key is the source and target the value

internal/common/connection.go1

1635:15modifies-parameterassignment modifies parameter filesSize

internal/common/connection.go:1635:15

1634 if fi.Mode().IsDir() {
1635 numFiles, filesSize, err = fs.GetDirSize(targetPath)
1636 if err != nil {

internal/vfs/azblobfs.go1

1013:21nested-structsmove nested anonymous struct types to named declarations

internal/vfs/azblobfs.go:1013:21

1012 partSize := fs.config.UploadPartSize
1013 guard := make(chan struct{}, fs.config.UploadConcurrency)
1014 blockCtxTimeout := time.Duration(fs.config.UploadPartSize/(1024*1024)) * time.Minute

internal/sftpd/sftpd_test.go1

1091:4no-defer-in-loopdefer inside a loop runs at function exit, not iteration exit

internal/sftpd/sftpd_test.go:1091:4

1090 if assert.NoError(t, err) {
1091 defer conn.Close()
1092 defer client.Close()

internal/cmd/rotatelogs_windows.go1

47:6no-initreplace init with explicit initialization

internal/cmd/rotatelogs_windows.go:47:6

46
47func init() {
48 serviceCmd.AddCommand(rotateLogCmd)

examples/ldapauthserver/utils/version.go1

6:2no-package-varpackage variables introduce mutable global state

examples/ldapauthserver/utils/version.go:6:2

5var (
6 commit = ""
7 date = ""

internal/cmd/gencompletion.go1

15:9package-commentspackage should have a documentation comment

internal/cmd/gencompletion.go:15:9

14
15package cmd
16

internal/common/eventmanager.go1

2533:45range-value-addresstaking the address of range value user can be misleading

internal/common/eventmanager.go:2533:45

2532 }
2533 if err = executePwdExpirationCheckForUser(&user, config); err != nil {
2534 params.AddError(err)

internal/common/common_test.go1

1522:18redundant-conversionconversion from uint16 to the identical type is redundant

internal/common/common_test.go:1522:18

1521 tlsVer = util.GetTLSVersion(13)
1522 assert.Equal(t, uint16(tls.VersionTLS13), tlsVer)
1523}

internal/dataprovider/memory.go1

760:6slice-preallocationpreallocate mappedAdmins with capacity len(range source) before appending once per iteration

internal/dataprovider/memory.go:760:6

759 }
760 var mappedAdmins []string
761 for idx := range admin.Groups {

internal/dataprovider/cachedpassword.go1

56:1top-level-declaration-ordertop-level declarations should be ordered as const, var, type, then func

internal/dataprovider/cachedpassword.go:56:1

55
56type credentialObject struct {
57 key string

internal/httpd/httpd_test.go1

4947:85unchecked-type-assertionuse the checked two-result form of the type assertion

internal/httpd/httpd_test.go:4947:85

4946 assert.NoError(t, err)
4947 assert.Equal(t, dataprovider.ErrInvalidCredentials.Error(), responseHolder["error"].(string))
4948}

internal/dataprovider/bolt.go1

2074:7unused-receiverreceiver p is unused

internal/dataprovider/bolt.go:2074:7

2073
2074func (p *BoltProvider) isDefenderHostBanned(_ string) (DefenderEntry, error) {
2075 return DefenderEntry{}, ErrNotImplemented

internal/httpdtest/httpdtest.go1

2175:10use-errors-newreplace fmt.Errorf with errors.New for a static message

internal/httpdtest/httpdtest.go:2175:10

2174 if expected.OSConfig.WriteBufferSize != actual.OSConfig.WriteBufferSize {
2175 return fmt.Errorf("write buffer size mismatch")
2176 }

internal/common/actions_test.go1

266:20add-constantstring literal "id" appears more than twice; define a constant

internal/common/actions_test.go:266:20

265 user.Permissions["/"] = []string{dataprovider.PermAny}
266 fs := vfs.NewOsFs("id", homeDir, "", nil)
267 c := NewBaseConnection("id", ProtocolSFTP, "", "", user)

internal/common/common.go1

1037:33cognitive-complexityfunction has cognitive complexity 10; maximum is 7

internal/common/common.go:1037:33

1036// authenticates
1037func (conns *ActiveConnections) Swap(c ActiveConnection) error {
1038 conns.Lock()

internal/dataprovider/sqlite.go1

319:76confusing-resultsadjacent unnamed results of the same type should be named

internal/dataprovider/sqlite.go:319:76

318
319func (p *SQLiteProvider) getUsedQuota(username string) (int, int64, int64, int64, error) {
320 return sqlCommonGetUsedQuota(username, p.dbHandle)

internal/common/connection.go1

1398:26cyclomatic-complexityfunction complexity is 12; maximum is 10

internal/common/connection.go:1398:26

1397// if no enough size is available for a resume/append
1398func (c *BaseConnection) GetMaxWriteSize(quotaResult vfs.QuotaCheckResult, isResume bool, fileSize int64,
1399 isUploadResumeSupported bool,

internal/cmd/install_windows.go1

62:5deep-exitprocess-exit calls should be confined to main or init

internal/cmd/install_windows.go:62:5

61 fmt.Printf("Error installing service: %v\r\n", err)
62 os.Exit(1)
63 } else {

internal/cmd/root.go1

188:2discarded-error-resulterror result returned by viper.BindEnv is discarded

internal/cmd/root.go:188:2

187 viper.SetDefault(logFilePathKey, defaultLogFile)
188 viper.BindEnv(logFilePathKey, "SFTPGO_LOG_FILE_PATH") //nolint:errcheck
189 cmd.Flags().StringVarP(&logFilePath, logFilePathFlag, "l", viper.GetString(logFilePathKey),

examples/ldapauthserver/logger/logger.go1

73:1doc-comment-perioddocumentation comment should end with punctuation

examples/ldapauthserver/logger/logger.go:73:1

72
73// Info logs at info level for the specified sender
74func Info(prefix, requestID string, format string, v ...interface{}) {

internal/httpd/middleware.go1

564:21error-stringserror string should not be capitalized or end with punctuation

internal/httpd/middleware.go:564:21

563 if !user.Filters.AllowAPIKeyAuth {
564 err := fmt.Errorf("API key authentication disabled for user %q", user.Username)
565 updateLoginMetrics(&user, dataprovider.LoginMethodPassword, ipAddr, err, r)