diff --git a/CHANGELOG.md b/CHANGELOG.md index 77fc344..550fa2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.6.5] - 2026-03-24 +### Fixed +- Fixed an issue where client-side flags could override server-side flags. + - Client-side overrides now need an explicit enablement flag: `AllowFlagsOverride` + ## [1.6.4] - 2026-03-23 ### Added - Add support for single worker scan timeout HTTP response handling (504) @@ -200,3 +205,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [1.6.2]: https://github.com/scanoss/api.go/compare/v1.6.1...v1.6.2 [1.6.3]: https://github.com/scanoss/api.go/compare/v1.6.2...v1.6.3 [1.6.4]: https://github.com/scanoss/api.go/compare/v1.6.3...v1.6.4 +[1.6.5]: https://github.com/scanoss/api.go/compare/v1.6.4...v1.6.5 diff --git a/config/app-config-prod.json b/config/app-config-prod.json index de38f89..d990fae 100644 --- a/config/app-config-prod.json +++ b/config/app-config-prod.json @@ -25,6 +25,7 @@ "ScanBinary": "scanoss", "ScanDebug": false, "ScanFlags": 0, + "AllowFlagsOverride": false, "ScanTimeout": 180, "WfpGrouping": 3, "Workers": 2, diff --git a/pkg/config/server_config.go b/pkg/config/server_config.go index b15cdec..56e0118 100644 --- a/pkg/config/server_config.go +++ b/pkg/config/server_config.go @@ -59,6 +59,7 @@ type ServerConfig struct { ScanKbName string `env:"SCAN_KB_NAME"` // KB name passed as "-n" parameter to the scanoss command ScanDebug bool `env:"SCAN_DEBUG"` // true/false ScanFlags int `env:"SCAN_ENGINE_FLAGS"` // Default flags to use when scanning + AllowFlagsOverride bool `env:"SCAN_ALLOW_FLAGS_OVERRIDE"` // Allow clients to override the default flags ScanTimeout int `env:"SCAN_ENGINE_TIMEOUT"` // timeout for waiting for the scan engine to respond WfpGrouping int `env:"SCAN_WFP_GROUPING"` // number of WFP to group into a single scan engine command Workers int `env:"SCAN_WORKERS"` // Number of concurrent workers to use per scan request @@ -138,6 +139,7 @@ func setServerConfigDefaults(cfg *ServerConfig) { cfg.Scanning.MinSnippetHits = 0 // Lets the engine decide on minimum snippet hits based on the file total lines cfg.Scanning.MinSnippetLines = 0 // Lets the engine decide on minimum snippet hits on the file total lines cfg.Scanning.HonourFileExts = true + cfg.Scanning.AllowFlagsOverride = false // Disallow clients overriding the default flags if it's set server-side } // LoadFile loads the specified file and returns its contents in a string array. diff --git a/pkg/service/scanning_service.go b/pkg/service/scanning_service.go index 985a9d8..1cdb5bb 100644 --- a/pkg/service/scanning_service.go +++ b/pkg/service/scanning_service.go @@ -184,6 +184,16 @@ func (s APIService) getConfigFromRequest(r *http.Request, zs *zap.SugaredLogger) if len(dbName) == 0 { dbName = strings.TrimSpace(r.Header.Get("db_name")) } + if len(flags) > 0 && s.config.Scanning.ScanFlags > 0 { + if !s.config.Scanning.AllowFlagsOverride { + zs.Warnf("Ignoring flags (%v) in the request. Using flags from the server config: %v", + flags, s.config.Scanning.ScanFlags) + flags = "" // Clear the flags to use the server configuration + } else { + zs.Debugf("Using flags (%v) from the request instead of server config: %v", + flags, s.config.Scanning.ScanFlags) + } + } scanSettings := strings.TrimSpace(r.Header.Get("scanoss-settings")) // Check the header for scan settings if s.config.App.Trace { zs.Debugf("Header: %v, Form: %v, flags: %v, type: %v, assets: %v, db_name: %v, scanSettings: %v", diff --git a/pkg/service/scanning_service_test.go b/pkg/service/scanning_service_test.go index 21c845f..db068cd 100644 --- a/pkg/service/scanning_service_test.go +++ b/pkg/service/scanning_service_test.go @@ -601,3 +601,75 @@ func TestScanDirectSingleSlow(t *testing.T) { }) } } + +func TestScanFlags(t *testing.T) { + err := zlog.NewSugaredDevLogger() + if err != nil { + t.Fatalf("an error '%s' was not expected when opening a sugared logger", err) + } + defer zlog.SyncZap() + myConfig := setupConfig(t) + myConfig.App.Trace = true + myConfig.Scanning.ScanDebug = true + myConfig.Scanning.ScanTimeout = 5 + + tests := []struct { + name string + serverFlags int + allowFlagsOverride bool + clientFlags string + want int + }{ + { + name: "Scanning - no flags", + serverFlags: 0, + allowFlagsOverride: false, + clientFlags: "", + want: 0, + }, + { + name: "Scanning - client flags", + serverFlags: 0, + allowFlagsOverride: false, + clientFlags: "256", + want: 256, + }, + { + name: "Scanning - server flags", + serverFlags: 1248, + allowFlagsOverride: false, + clientFlags: "", + want: 1248, + }, + { + name: "Scanning - server/clients flags - allowed", + serverFlags: 1248, + allowFlagsOverride: true, + clientFlags: "256", + want: 256, + }, + { + name: "Scanning - server/clients flags - not allowed", + serverFlags: 1248, + allowFlagsOverride: false, + clientFlags: "256", + want: 1248, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + myConfig.Scanning.ScanFlags = test.serverFlags + myConfig.Scanning.AllowFlagsOverride = test.allowFlagsOverride + + req := httptest.NewRequest(http.MethodPost, "/scan/direct", nil) + if len(test.clientFlags) > 0 { + req.Header.Add("flags", test.clientFlags) + } + apiService := NewAPIService(myConfig) + cfg, err := apiService.getConfigFromRequest(req, zlog.S) + assert.NoError(t, err) + assert.Equal(t, test.want, cfg.flags) + fmt.Println("Flags: ", cfg.flags) + }) + } +}