[BUG] Kubescape tool reports ApplicationProfile execs/opens/containers as 0 due to metadata-only LIST (spec is not fetched)
メンテナーはふだん 3 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 3/5
- 見積もり時間
- 1〜2日
- 初心者へのやさしさ
- 72/100
調査の方向性
pkg/kubescape/kubescape.go の ApplicationProfile の List handler 付近から始め、List レスポンスが spec 由来のカウンターをどのように設定しているかを確認します。一覧表示されたオブジェクトと個別の GET 結果を比較し、そのうえで、handler が実際の値を返すか、利用できないデータを明確に示すようにします。0 を返す状態にはしないでください。関連する vulnerabilityManifests path でも同じパターンが使われている場合は、それも含めて ApplicationProfile の一覧表示の動作を確認します。
索引モデルが issue の本文から書いたものです。
説明
🎯 Affected Component(s)
pkg/kubescape (kagent-tools MCP server) — the list-style handlers for ApplicationProfile (and likely other spdx.softwarecomposition.kubescape.io resources whose list handlers read spec-derived fields, e.g. vulnerabilityManifests).
🐛 Bug Description
Note: I think the Kubescape tool is still in an early/beta stage and not yet listed among the GA tools. I'm filing this in case the feedback is useful for hardening it before GA — please feel free to deprioritize if this tool is out of active scope.
Kubescape's Storage aggregated API server implements metadata-only LIST: a LIST request (e.g., kubectl get <custom resource> -A -o json) returns object metadata only and omits the heavy spec payload. The full spec is only returned by an individual GET on a named object (or via the documented fullSpec resourceVersion mechanism).
The Kubescape tool's list handlers appear to aggregate values from spec (e.g., spec.containers[].execs, spec.containers[].opens) using data obtained through a LIST call. Because LIST returns no spec, the aggregation counts nothing and returns 0 for all fields — even containers_count — while the objects actually contain data.
This is a documented behavior of Kubescape Storage. Per the kubescape/storage README:
a listed object comes back with its spec fields at their zero values (for example a VulnerabilityManifestSummary reports all severity counts as 0)
(the same applies to ApplicationProfile, whose spec.containers[] is likewise omitted on LIST)
🔄 Steps To Reproduce
- Install the Kubescape operator with relevancy enabled (default with node-agent/eBPF), and let the learning period complete for at least one workload.
- Invoke
kubescape_list_application_profilesthrough a kagent agent (or the MCP server directly). - Observe that all profiles report
total_execs: 0,total_opens: 0,total_syscalls: 0,containers_count: 0.
🤔 Expected Behavior
The tool should return the real spec-derived values (e.g., execs, opens, container counts) for each ApplicationProfile, or at minimum must not report 0 when the data is simply not present in a metadata-only LIST response.
Acceptable approaches:
- Fetch each object with an individual GET (which returns the full
spec) before aggregating, or - If only metadata is available, clearly distinguish "not fetched / unknown" from "0", instead of emitting
0.
Note: The storage's fullSpec resourceVersion mechanism is not applicable here — per the kubescape/storage README, fullSpec is rejected on LIST for applicationprofiles and networkneighborhoods (it is honored only for the summary resources). Individual GET is therefore the appropriate approach for these resources.
📱 Actual Behavior
All ApplicationProfiles are reported with zeroed counters (trimmed):
{
"application_profiles": [
{
"containers_count": 0,
"created_at": "2026-06-04T08:41:49Z",
"name": "replicaset-rockylinux-58468585c7",
"namespace": "kagent",
"total_capabilities": 0,
"total_endpoints": 0,
"total_execs": 0,
"total_opens": 0,
"total_syscalls": 0
},
{ "... same zeros for every profile ..." }
]
}
However, an individual GET on the same objects returns real data, and the learning is marked complete:
$ kubectl get applicationprofile replicaset-rockylinux-58468585c7 -n kagent -o json \
| jq '.spec.containers[]? | {name, execs:(.execs|length), opens:(.opens|length)}'
{
"name": "rockylinux",
"execs": 13,
"opens": 115
}
$ kubectl get applicationprofile replicaset-rockylinux-58468585c7 -n kagent -o json \
| jq '.metadata.annotations'
{
"kubescape.io/completion": "complete",
"kubescape.io/status": "completed",
...
}
So the data exists (execs: 13, opens: 115) and the profile is completed; the tool's 0 values come from LIST not returning spec, not from an actually-empty profile.
💻 Environment
- OS version: Rocky Linux 8.10 (x86_64) bastion; nodes on Amazon Linux
- Kubernetes: v1.35.6 (EKS)
- Kubernetes Provider: AWS (EKS)
- kagent-tools / MCP server version: v0.2.1
- Kubescape operator: v4.0.5 (Helm chart 1.40.2)
🔍 Additional Context
Root cause:
In pkg/kubescape/kubescape.go (v0.2.1, around L741), the list handler fetches profiles with a LIST call and then reads spec-derived fields directly from each listed item:
profiles, err := k.spdxClient.ApplicationProfiles(queryNamespace).List(ctx, metav1.ListOptions{})
// ...
for _, profile := range profiles.Items {
containersCount := len(profile.Spec.Containers)
// ...
for _, c := range profile.Spec.Containers {
totalExecs += len(c.Execs)
totalOpens += len(c.Opens)
totalSyscalls += len(c.Syscalls)
totalCapabilities += len(c.Capabilities)
totalEndpoints += len(c.Endpoints)
}
// ... written into profileMap as containers_count / total_execs / ...
}
The List call uses an empty metav1.ListOptions{}. Since Kubescape Storage serves metadata-only LIST (the payload/spec is not loaded from disk), profile.Spec comes back zero-valued: profile.Spec.Containers is empty, so containers_count and every total_* counter sum to 0. The values are read from a response that, by design, never contains spec.
Suggested fix: GET each object individually to obtain spec before aggregating, or report the counters as "unknown/not fetched" rather than 0 when spec is unavailable.
(The fullSpec LIST mechanism cannot be used here: the storage server rejects it for applicationprofiles and networkneighborhoods.)
References:
- Kubescape Storage README (documents metadata-only LIST and fullSpec): https://github.com/kubescape/storage
- Relevancy (execs/opens learning via eBPF node-agent): https://kubescape.io/docs/operator/relevancy/
- 主要言語
- Go
- スター
- 35
- フォーク
- 30
- 平均マージ
- 3日 23時間
- マージ済み PR(30日)
- 3
環境構築
このプロジェクトの環境構築ファイルはまだ確認していません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
kagent-dev/tools のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
kagent-dev/tools#54 ·
メンテナーはふだん 3 日以内に返信
-
難易度 4/5 3〜5日 初心者へのやさしさ 45/100
kagent-dev/tools#82 ·
メンテナーはふだん 3 日以内に返信
-
難易度 3/5 1〜2日 初心者へのやさしさ 78/100
kagent-dev/tools#80 ·
メンテナーはふだん 3 日以内に返信
-
難易度 3/5 1〜2日 初心者へのやさしさ 68/100
kagent-dev/tools#68 · コメント 1 件 ·
メンテナーはふだん 3 日以内に返信
-
難易度 4/5 3〜5日 初心者へのやさしさ 48/100
kagent-dev/tools#60 · リアクション 1 件 ·
メンテナーはふだん 3 日以内に返信
kagent-dev/tools の issue をすべて見る
似ている issue
-
area/proxy kind/bug priority/backlog triage/accepted
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
lexfrei/cloudflare-tunnel-gateway-controller#840 ·
メンテナーはふだん 1 日以内に返信
-
area:chat bug sev:papercut
難易度 2/5 1〜3時間 初心者へのやさしさ 86/100
Agent-Field/CodeAF#1592 ·
メンテナーはふだん 1 日以内に返信
-
kind/bug
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
メンテナーはふだん 7 日以内に返信
-
bug needs triage
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信
-
bug P2 reliability
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
afreidah/s3-orchestrator#1564 ·
メンテナーはふだん 1 日以内に返信