Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,11 @@ func main() {

// Create scan failure reporter (sends SBOM failures to careportreceiver for user notifications)
var failureReporter sbommanager.SbomFailureReporter
if services, svcErr := config.LoadServiceURLs("/etc/config/services.json"); svcErr == nil && services.GetReportReceiverHttpUrl() != "" {
apiURL := os.Getenv("API_URL")
if apiURL == "" {
apiURL = "api.armosec.io"
}
Comment on lines +398 to +401
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In github.com/kubescape/backend/pkg/servicediscovery/v3, does NewServiceDiscoveryClientV3 require an absolute URL including scheme (e.g., https://...), or does it accept bare hostnames like api.armosec.io?

💡 Result:

NewServiceDiscoveryClientV3 in github.com/kubescape/backend/pkg/servicediscovery/v3 likely requires an absolute URL including scheme. Evidence from Kubescape operator usage shows service discovery fetching from https://api.armosec.io/api/v1/servicediscovery, indicating HTTPS absolute URLs are used. Bare hostnames like api.armosec.io are used in contexts like firewall rules but curl commands prepend https://, suggesting the client expects full URLs. No source code found explicitly stating bare hostnames are accepted, and standard Go HTTP clients typically require schemes for absolute URLs.

Citations:


🏁 Script executed:

# Find and read cmd/main.go around lines 398-401
cat -n cmd/main.go | sed -n '395,405p'

Repository: kubescape/node-agent

Length of output: 776


🏁 Script executed:

# Search for NewServiceDiscoveryClientV3 to understand its signature and usage
rg "NewServiceDiscoveryClientV3" -A 3 -B 1

Repository: kubescape/node-agent

Length of output: 348


🏁 Script executed:

# Look for how apiURL is used after being set
rg "apiURL" cmd/main.go -A 2 -B 2

Repository: kubescape/node-agent

Length of output: 695


🏁 Script executed:

# Check LoadServiceURLs implementation
rg "func LoadServiceURLs" -A 10 pkg/config/config.go

Repository: kubescape/node-agent

Length of output: 446


🏁 Script executed:

# Check if servicediscoveryv3 is from an external module and its go.mod
cat go.mod | grep -i servicediscovery

Repository: kubescape/node-agent

Length of output: 46


🏁 Script executed:

# Look for any URL normalization or scheme-handling in the codebase
rg "https://" cmd/main.go | head -20

Repository: kubescape/node-agent

Length of output: 46


🏁 Script executed:

# Check if there are other places where api.armosec.io is set and how
rg "armosec.io" -B 2 -A 2

Repository: kubescape/node-agent

Length of output: 6609


🏁 Script executed:

# Search for other calls to LoadServiceURLs
rg "LoadServiceURLs" -B 2 -A 2

Repository: kubescape/node-agent

Length of output: 823


🏁 Script executed:

# Check imports in cmd/main.go to see if strings is available
head -50 cmd/main.go | grep -E "^import|strings"

Repository: kubescape/node-agent

Length of output: 83


🏁 Script executed:

# Check if there are tests for LoadServiceURLs or config
fd "config.*test" --type f

Repository: kubescape/node-agent

Length of output: 89


🏁 Script executed:

# Check config_test.go to see if there are tests for LoadServiceURLs
cat -n pkg/config/config_test.go | head -50

Repository: kubescape/node-agent

Length of output: 2052


🏁 Script executed:

# Search for how the scheme is handled elsewhere in similar code
rg "://" pkg/config/ -B 1 -A 1

Repository: kubescape/node-agent

Length of output: 1890


Add URL scheme to default API_URL and normalize user-provided values.

Line 400 defaults to api.armosec.io without a scheme. When passed to NewServiceDiscoveryClientV3(), this bare hostname will fail service discovery (which requires an absolute URL), preventing scan-failure reporting from being enabled.

Additionally, users who provide a custom API_URL environment variable without a scheme will encounter the same failure.

Proposed patch
 	apiURL := os.Getenv("API_URL")
 	if apiURL == "" {
-		apiURL = "api.armosec.io"
+		apiURL = "https://api.armosec.io"
+	} else if !strings.Contains(apiURL, "://") {
+		apiURL = "https://" + apiURL
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/main.go` around lines 398 - 401, The current apiURL variable may be a
bare hostname which breaks NewServiceDiscoveryClientV3() because it expects an
absolute URL; change the default to include a scheme (e.g.,
"https://api.armosec.io") and normalize any user-provided API_URL by parsing it
(using url.Parse) and prepending "https://" when the scheme is empty before
passing to NewServiceDiscoveryClientV3(); update the apiURL
assignment/normalization logic around the apiURL variable to perform this fix.

if services, svcErr := config.LoadServiceURLs(apiURL); svcErr == nil && services.GetReportReceiverHttpUrl() != "" {
failureReporter = sbommanagerv1.NewHTTPSbomFailureReporter(services.GetReportReceiverHttpUrl(), accessKey, clusterData.AccountID, clusterData.ClusterName)
logger.L().Info("scan failure reporting enabled", helpers.String("eventReceiverURL", services.GetReportReceiverHttpUrl()))
}
Comment on lines +402 to 405
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Don’t swallow service-discovery errors silently.

At Line 402, svcErr is ignored on failure. Add a warning log so misconfiguration/network issues are diagnosable.

Proposed patch
 	if services, svcErr := config.LoadServiceURLs(apiURL); svcErr == nil && services.GetReportReceiverHttpUrl() != "" {
 		failureReporter = sbommanagerv1.NewHTTPSbomFailureReporter(services.GetReportReceiverHttpUrl(), accessKey, clusterData.AccountID, clusterData.ClusterName)
 		logger.L().Info("scan failure reporting enabled", helpers.String("eventReceiverURL", services.GetReportReceiverHttpUrl()))
+	} else if svcErr != nil {
+		logger.L().Warning("scan failure reporting disabled: unable to load backend services", helpers.Error(svcErr), helpers.String("apiURL", apiURL))
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if services, svcErr := config.LoadServiceURLs(apiURL); svcErr == nil && services.GetReportReceiverHttpUrl() != "" {
failureReporter = sbommanagerv1.NewHTTPSbomFailureReporter(services.GetReportReceiverHttpUrl(), accessKey, clusterData.AccountID, clusterData.ClusterName)
logger.L().Info("scan failure reporting enabled", helpers.String("eventReceiverURL", services.GetReportReceiverHttpUrl()))
}
if services, svcErr := config.LoadServiceURLs(apiURL); svcErr == nil && services.GetReportReceiverHttpUrl() != "" {
failureReporter = sbommanagerv1.NewHTTPSbomFailureReporter(services.GetReportReceiverHttpUrl(), accessKey, clusterData.AccountID, clusterData.ClusterName)
logger.L().Info("scan failure reporting enabled", helpers.String("eventReceiverURL", services.GetReportReceiverHttpUrl()))
} else if svcErr != nil {
logger.L().Warning("scan failure reporting disabled: unable to load backend services", helpers.Error(svcErr), helpers.String("apiURL", apiURL))
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/main.go` around lines 402 - 405, The current LoadServiceURLs call
swallows svcErr when service discovery fails; update the block around
LoadServiceURLs so that if svcErr != nil you emit a warning via the logger
(include svcErr.Error()) and only proceed to create failureReporter when svcErr
== nil and services.GetReportReceiverHttpUrl() != ""; also log a warning if
svcErr == nil but services.GetReportReceiverHttpUrl() is empty to indicate a
missing configured URL; reference the LoadServiceURLs call, the svcErr variable,
services.GetReportReceiverHttpUrl(), and failureReporter when making these
changes.

Expand Down
13 changes: 6 additions & 7 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (

"github.com/kubescape/backend/pkg/servicediscovery"
"github.com/kubescape/backend/pkg/servicediscovery/schema"
servicediscoveryv2 "github.com/kubescape/backend/pkg/servicediscovery/v2"
servicediscoveryv3 "github.com/kubescape/backend/pkg/servicediscovery/v3"
"github.com/kubescape/node-agent/pkg/exporters"
"github.com/kubescape/node-agent/pkg/hostfimsensor/v1"
processtreecreator "github.com/kubescape/node-agent/pkg/processtree/config"
Expand Down Expand Up @@ -289,13 +289,12 @@ func (c *Config) SkipNamespace(ns string) bool {
return false
}

func LoadServiceURLs(filePath string) (schema.IBackendServices, error) {
if pathFromEnv, present := os.LookupEnv("SERVICES"); present {
filePath = pathFromEnv
func LoadServiceURLs(apiURL string) (schema.IBackendServices, error) {
client, err := servicediscoveryv3.NewServiceDiscoveryClientV3(apiURL)
if err != nil {
return nil, err
}
return servicediscovery.GetServices(
servicediscoveryv2.NewServiceDiscoveryFileV2(filePath),
)
return servicediscovery.GetServices(client)
}

type OrderedEventQueueConfig struct {
Expand Down
Loading