mirror of
https://github.com/kubescape/kubescape.git
synced 2026-02-14 18:09:55 +00:00
Merge pull request #1926 from kubescape/copilot/fix-kubescan-interface-error
Fix panic on unsafe interface{} to string type assertions
This commit is contained in:
@@ -294,11 +294,19 @@ func (ksServer *KubescapeMcpserver) CallTool(name string, arguments map[string]i
|
|||||||
if !ok {
|
if !ok {
|
||||||
namespace = "kubescape"
|
namespace = "kubescape"
|
||||||
}
|
}
|
||||||
|
namespaceStr, ok := namespace.(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("namespace must be a string")
|
||||||
|
}
|
||||||
manifestName, ok := arguments["manifest_name"]
|
manifestName, ok := arguments["manifest_name"]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("manifest_name is required")
|
return nil, fmt.Errorf("manifest_name is required")
|
||||||
}
|
}
|
||||||
manifest, err := ksServer.ksClient.VulnerabilityManifests(namespace.(string)).Get(context.Background(), manifestName.(string), metav1.GetOptions{})
|
manifestNameStr, ok := manifestName.(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("manifest_name must be a string")
|
||||||
|
}
|
||||||
|
manifest, err := ksServer.ksClient.VulnerabilityManifests(namespaceStr).Get(context.Background(), manifestNameStr, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get vulnerability manifest: %s", err)
|
return nil, fmt.Errorf("failed to get vulnerability manifest: %s", err)
|
||||||
}
|
}
|
||||||
@@ -323,21 +331,33 @@ func (ksServer *KubescapeMcpserver) CallTool(name string, arguments map[string]i
|
|||||||
if !ok {
|
if !ok {
|
||||||
namespace = "kubescape"
|
namespace = "kubescape"
|
||||||
}
|
}
|
||||||
|
namespaceStr, ok := namespace.(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("namespace must be a string")
|
||||||
|
}
|
||||||
manifestName, ok := arguments["manifest_name"]
|
manifestName, ok := arguments["manifest_name"]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("manifest_name is required")
|
return nil, fmt.Errorf("manifest_name is required")
|
||||||
}
|
}
|
||||||
|
manifestNameStr, ok := manifestName.(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("manifest_name must be a string")
|
||||||
|
}
|
||||||
cveID, ok := arguments["cve_id"]
|
cveID, ok := arguments["cve_id"]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("cve_id is required")
|
return nil, fmt.Errorf("cve_id is required")
|
||||||
}
|
}
|
||||||
manifest, err := ksServer.ksClient.VulnerabilityManifests(namespace.(string)).Get(context.Background(), manifestName.(string), metav1.GetOptions{})
|
cveIDStr, ok := cveID.(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("cve_id must be a string")
|
||||||
|
}
|
||||||
|
manifest, err := ksServer.ksClient.VulnerabilityManifests(namespaceStr).Get(context.Background(), manifestNameStr, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get vulnerability manifest: %s", err)
|
return nil, fmt.Errorf("failed to get vulnerability manifest: %s", err)
|
||||||
}
|
}
|
||||||
var match []v1beta1.Match
|
var match []v1beta1.Match
|
||||||
for _, m := range manifest.Spec.Payload.Matches {
|
for _, m := range manifest.Spec.Payload.Matches {
|
||||||
if m.Vulnerability.ID == cveID.(string) {
|
if m.Vulnerability.ID == cveIDStr {
|
||||||
match = append(match, m)
|
match = append(match, m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -358,7 +378,11 @@ func (ksServer *KubescapeMcpserver) CallTool(name string, arguments map[string]i
|
|||||||
if !ok {
|
if !ok {
|
||||||
namespace = "kubescape"
|
namespace = "kubescape"
|
||||||
}
|
}
|
||||||
manifests, err := ksServer.ksClient.WorkloadConfigurationScans(namespace.(string)).List(context.Background(), metav1.ListOptions{})
|
namespaceStr, ok := namespace.(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("namespace must be a string")
|
||||||
|
}
|
||||||
|
manifests, err := ksServer.ksClient.WorkloadConfigurationScans(namespaceStr).List(context.Background(), metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -394,11 +418,19 @@ func (ksServer *KubescapeMcpserver) CallTool(name string, arguments map[string]i
|
|||||||
if !ok {
|
if !ok {
|
||||||
namespace = "kubescape"
|
namespace = "kubescape"
|
||||||
}
|
}
|
||||||
|
namespaceStr, ok := namespace.(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("namespace must be a string")
|
||||||
|
}
|
||||||
manifestName, ok := arguments["manifest_name"]
|
manifestName, ok := arguments["manifest_name"]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("manifest_name is required")
|
return nil, fmt.Errorf("manifest_name is required")
|
||||||
}
|
}
|
||||||
manifest, err := ksServer.ksClient.WorkloadConfigurationScans(namespace.(string)).Get(context.Background(), manifestName.(string), metav1.GetOptions{})
|
manifestNameStr, ok := manifestName.(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("manifest_name must be a string")
|
||||||
|
}
|
||||||
|
manifest, err := ksServer.ksClient.WorkloadConfigurationScans(namespaceStr).Get(context.Background(), manifestNameStr, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get configuration manifest: %s", err)
|
return nil, fmt.Errorf("failed to get configuration manifest: %s", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,14 +144,23 @@ func CheckShortTerminalWidth(rows []table.Row, headers table.Row) bool {
|
|||||||
for _, row := range rows {
|
for _, row := range rows {
|
||||||
rowWidth := 0
|
rowWidth := 0
|
||||||
for idx, cell := range row {
|
for idx, cell := range row {
|
||||||
cellLen := len(cell.(string))
|
cellStr, ok := cell.(string)
|
||||||
|
if !ok {
|
||||||
|
// If cell is not a string, skip this calculation
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
cellLen := len(cellStr)
|
||||||
if cellLen > 50 { // Take only 50 characters of each sentence for counting size
|
if cellLen > 50 { // Take only 50 characters of each sentence for counting size
|
||||||
cellLen = 50
|
cellLen = 50
|
||||||
}
|
}
|
||||||
if cellLen > len(headers[idx].(string)) {
|
headerStr, ok := headers[idx].(string)
|
||||||
|
if !ok {
|
||||||
|
// If header is not a string, use cell length
|
||||||
|
rowWidth += cellLen
|
||||||
|
} else if cellLen > len(headerStr) {
|
||||||
rowWidth += cellLen
|
rowWidth += cellLen
|
||||||
} else {
|
} else {
|
||||||
rowWidth += len(headers[idx].(string))
|
rowWidth += len(headerStr)
|
||||||
}
|
}
|
||||||
rowWidth += 2
|
rowWidth += 2
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jedib0t/go-pretty/v6/table"
|
||||||
"github.com/jwalton/gchalk"
|
"github.com/jwalton/gchalk"
|
||||||
"github.com/kubescape/opa-utils/reporthandling/apis"
|
"github.com/kubescape/opa-utils/reporthandling/apis"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -334,3 +335,69 @@ func TestGetColorForVulnerabilitySeverity(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCheckShortTerminalWidth(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
rows []table.Row
|
||||||
|
headers table.Row
|
||||||
|
// We can't predict the exact result since it depends on terminal size
|
||||||
|
// but we can test it doesn't panic with various inputs
|
||||||
|
shouldNotPanic bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Normal string rows",
|
||||||
|
rows: []table.Row{
|
||||||
|
{"cell1", "cell2", "cell3"},
|
||||||
|
{"longer cell 1", "longer cell 2", "longer cell 3"},
|
||||||
|
},
|
||||||
|
headers: table.Row{"Header1", "Header2", "Header3"},
|
||||||
|
shouldNotPanic: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Rows with non-string values (map)",
|
||||||
|
rows: []table.Row{
|
||||||
|
{"cell1", map[string]interface{}{"key": "value"}, "cell3"},
|
||||||
|
{"cell4", "cell5", "cell6"},
|
||||||
|
},
|
||||||
|
headers: table.Row{"Header1", "Header2", "Header3"},
|
||||||
|
shouldNotPanic: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Headers with non-string values",
|
||||||
|
rows: []table.Row{
|
||||||
|
{"cell1", "cell2", "cell3"},
|
||||||
|
},
|
||||||
|
headers: table.Row{"Header1", map[string]interface{}{"key": "value"}, "Header3"},
|
||||||
|
shouldNotPanic: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Both rows and headers with non-string values",
|
||||||
|
rows: []table.Row{
|
||||||
|
{map[string]interface{}{"key": "value"}, "cell2", 123},
|
||||||
|
},
|
||||||
|
headers: table.Row{[]string{"a", "b"}, "Header2", true},
|
||||||
|
shouldNotPanic: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Empty rows",
|
||||||
|
rows: []table.Row{},
|
||||||
|
headers: table.Row{"Header1", "Header2"},
|
||||||
|
shouldNotPanic: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
if tt.shouldNotPanic {
|
||||||
|
t.Errorf("CheckShortTerminalWidth() panicked when it shouldn't: %v", r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
// Call the function - we just want to ensure it doesn't panic
|
||||||
|
_ = CheckShortTerminalWidth(tt.rows, tt.headers)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -56,7 +56,6 @@ require (
|
|||||||
go.opentelemetry.io/otel v1.39.0
|
go.opentelemetry.io/otel v1.39.0
|
||||||
go.opentelemetry.io/otel/metric v1.39.0
|
go.opentelemetry.io/otel/metric v1.39.0
|
||||||
golang.org/x/mod v0.31.0
|
golang.org/x/mod v0.31.0
|
||||||
golang.org/x/sync v0.19.0
|
|
||||||
golang.org/x/term v0.38.0
|
golang.org/x/term v0.38.0
|
||||||
gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473
|
gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
@@ -557,6 +556,7 @@ require (
|
|||||||
golang.org/x/image v0.25.0 // indirect
|
golang.org/x/image v0.25.0 // indirect
|
||||||
golang.org/x/net v0.48.0 // indirect
|
golang.org/x/net v0.48.0 // indirect
|
||||||
golang.org/x/oauth2 v0.34.0 // indirect
|
golang.org/x/oauth2 v0.34.0 // indirect
|
||||||
|
golang.org/x/sync v0.19.0 // indirect
|
||||||
golang.org/x/sys v0.39.0 // indirect
|
golang.org/x/sys v0.39.0 // indirect
|
||||||
golang.org/x/text v0.32.0 // indirect
|
golang.org/x/text v0.32.0 // indirect
|
||||||
golang.org/x/time v0.14.0 // indirect
|
golang.org/x/time v0.14.0 // indirect
|
||||||
|
|||||||
Reference in New Issue
Block a user