Skip to content

SBOB wildcards: DNS + IP + path exec wildcards, sign/tamper - #326

Closed
entlein wants to merge 3 commits into
kubescape:mainfrom
k8sstormcenter:upstream-pr/sbob-EVERYTHING
Closed

entlein wants to merge 3 commits into
kubescape:mainfrom
k8sstormcenter:upstream-pr/sbob-EVERYTHING

Conversation

@entlein

@entlein entlein commented May 15, 2026 •

Copy link
Copy Markdown
Contributor

Umbrella PR consolidating the SBOB-wildcards storage surface. Tier-by-tier breakdown per CodeRabbit's atomic-split advisory on kubescape/storage#323:

  • Tier 0 — opens: kubescape/storage#323 (path-wildcards core: anchored trailing-*, per-endpoint port key, CollapseConfig types)
  • Tier 2 — execs: kubescape/storage#322 (CompareExecArgs), #325 (CollapseConfig CRD + processors)
  • Tier 3 — network: kubescape/storage#324 (networkmatch package: DNS leading-* + trailing-* + mid-⋯ + CIDR + IPAddresses + * sentinel)

This umbrella carries the union of the above. Once the per-tier PRs land in order, the umbrella shrinks to empty.

Performance evidence (node-agent side)

The bench is run on the node-agent build that links against this storage version. Validated on workflow run 25959674209:

Metric Baseline (NA v0.3.113) Candidate Delta
Avg CPU (cores) 0.214 0.209 -2.2%
Peak CPU (cores) 0.223 0.218 -2.2%
Avg Memory (MiB) 277.659 259.997 -6.4%
Peak Memory (MiB) 279.367 264.609 -5.3%

Companion node-agent umbrella

kubescape/node-agent#810. Storage and node-agent run on different syft chains by design — storage on anchore/syft v1.42.4 (matches storage upstream main), node-agent on kubescape/syft v1.32.0-ks.2 via replace (matches node-agent upstream main).

Notes

….7%/-12.4% memory)

Signed-off-by: entlein <einentlein@gmail.com>
@coderabbitai

coderabbitai Bot commented May 15, 2026 •

Copy link
Copy Markdown

Warning

Rate limit exceeded

@entlein has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 59 minutes and 19 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 27d0d5c5-7ada-4760-9c5d-07eaef73227c

📥 Commits

Reviewing files that changed from the base of the PR and between db0c766 and b9e23a4.

📒 Files selected for processing (14)
  • pkg/apis/softwarecomposition/v1beta1/generated.proto
  • pkg/apis/softwarecomposition/v1beta1/network_types_protobuf_test.go
  • pkg/registry/file/applicationprofile_processor.go
  • pkg/registry/file/applicationprofile_processor_collapse_provider_test.go
  • pkg/registry/file/dynamicpathdetector/analyze_endpoints.go
  • pkg/registry/file/dynamicpathdetector/analyze_opens.go
  • pkg/registry/file/dynamicpathdetector/analyzer.go
  • pkg/registry/file/dynamicpathdetector/tests/analyze_endpoints_test.go
  • pkg/registry/file/dynamicpathdetector/tests/analyze_opens_test.go
  • pkg/registry/file/dynamicpathdetector/tests/compare_dynamic_memoise_test.go
  • pkg/registry/file/dynamicpathdetector/tests/compare_exec_args_test.go
  • pkg/registry/file/dynamicpathdetector/tests/coverage_test.go
  • pkg/registry/file/dynamicpathdetector/types.go
  • pkg/registry/file/networkmatch/README.md
📝 Walkthrough

Walkthrough

This PR introduces a CollapseConfiguration Kubernetes CRD for configurable dynamic path collapse thresholds, enhances the path analyzer with per-prefix configuration and consolidation logic, adds wildcard-aware network matching for IPs and DNS names, integrates these capabilities into profile processors, and provides registry strategy with admission-time validation.

Changes

Collapse Configuration and Dynamic Path Analysis

Layer / File(s) Summary
API Types and Schema Definition
pkg/apis/softwarecomposition/collapse_types.go, pkg/apis/softwarecomposition/v1beta1/collapse_types.go, pkg/apis/softwarecomposition/v1beta1/generated.proto, pkg/apis/softwarecomposition/network_types.go, pkg/apis/softwarecomposition/v1beta1/network_types.go, pkg/apis/softwarecomposition/register.go, pkg/apis/softwarecomposition/v1beta1/register.go, pkg/apis/softwarecomposition/v1beta1/zz_generated.conversion.go, pkg/apis/softwarecomposition/v1beta1/zz_generated.deepcopy.go, pkg/apis/softwarecomposition/v1beta1/zz_generated.model_name.go, pkg/apis/softwarecomposition/zz_generated.deepcopy.go, pkg/apis/softwarecomposition/v1beta1/network_types_protobuf_test.go
Introduces CollapseConfiguration CRD with per-prefix collapse thresholds, adds IPAddresses list field to NetworkNeighbor, generates protobuf, conversions, and deepcopy implementations across both API versions.
Runtime Collapse Configuration
pkg/registry/file/dynamicpathdetector/types.go, pkg/registry/file/dynamicpathdetector/collapse_config_from_crd.go
Defines CollapseSettings struct and CollapseSettingsProvider hook type; implements DefaultCollapseSettings() with defensive copying, and CRD-to-runtime conversions (CollapseSettingsFromCRD, CRDFromCollapseSettings).
Enhanced Path Analyzer
pkg/registry/file/dynamicpathdetector/analyzer.go, pkg/registry/file/dynamicpathdetector/analyze_opens.go, pkg/registry/file/dynamicpathdetector/analyze_endpoints.go, pkg/registry/file/dynamicpathdetector/compare_exec_args.go
Refactors analyzer to use pooled byte buffers and compute per-prefix collapse thresholds; completely rewrites CompareDynamic with recursive wildcard matching; adds consolidateOpens to remove literals covered by dynamic patterns; enhances endpoint merging with wildcard-port folding and Internal field support; implements CompareExecArgs for argv pattern matching.
Network Wildcard Matching
pkg/registry/file/networkmatch/match_ip.go, pkg/registry/file/networkmatch/match_dns.go, pkg/registry/file/networkmatch/validate.go, pkg/registry/file/networkmatch/README.md, pkg/registry/file/networkmatch/doc.go
Adds IP and DNS wildcard matchers with precompilation support and defensive error handling; implements validation helpers for admission-time checks; documents token vocabulary, API contracts, and performance requirements.
Profile Processor Integration
pkg/registry/file/applicationprofile_processor.go, pkg/registry/file/containerprofile_processor.go
Updates ApplicationProfileProcessor and ContainerProfileProcessor to accept configurable collapse settings via provider hooks; adds SetCollapseSettings method and default initialization.
Registry Strategy and Validation
pkg/apiserver/apiserver.go, pkg/registry/softwarecomposition/collapseconfiguration/etcd.go, pkg/registry/softwarecomposition/collapseconfiguration/strategy.go, pkg/registry/softwarecomposition/networkneighborhood/strategy.go
Implements cluster-scoped CollapseConfigurationStrategy with spec validation for thresholds and prefix invariants; wires etcd REST endpoint; extends NetworkNeighborhoodStrategy to validate network profile IP/DNS entries.
Comprehensive Test Coverage
pkg/registry/file/applicationprofile_processor_collapse_provider_test.go, pkg/registry/file/applicationprofile_processor_test.go, pkg/registry/file/cleanup_test.go, pkg/registry/file/containerprofile_processor_collapse_provider_test.go, pkg/registry/file/dynamicpathdetector/tests/*, pkg/registry/softwarecomposition/collapseconfiguration/strategy_test.go, pkg/registry/softwarecomposition/networkneighborhood/strategy_test.go
Adds 50+ new test functions covering analyzer behavior, consolidation, endpoint merging, network matching, CRD conversion, and registry validation; includes benchmarks for path analysis and network matching; adds opt-in profiling support.
Minor Changes
.gitignore, go.mod, pkg/registry/file/cleanup.go
Updates gitignore for temporary directories; downgrades three Go module dependencies; adds user-managed resource detection for cleanup skip logic.

🎯 4 (Complex) | ⏱️ ~60 minutes

Sequence Diagrams

sequenceDiagram
    participant Admin as Administrator
    participant ApiServer as API Server
    participant Strategy as CollapseConfigurationStrategy
    participant Store as etcd Store
    
    Admin->>ApiServer: POST CollapseConfiguration
    ApiServer->>Strategy: Validate
    Strategy->>Strategy: Check thresholds >= 0
    Strategy->>Strategy: Validate prefixes (non-empty, /*, no duplicates)
    Strategy-->>ApiServer: Field errors or OK
    ApiServer->>Store: Store or Reject
    Store-->>ApiServer: Acknowledged
    ApiServer-->>Admin: Created or Error
Loading
sequenceDiagram
    participant Processor as ApplicationProfileProcessor
    participant Settings as CollapseSettings
    participant Analyzer as PathAnalyzer
    participant Consolidate as consolidateOpens
    
    Processor->>Settings: GetCollapseSettings()
    Settings-->>Processor: Thresholds + CollapseConfigs
    Processor->>Analyzer: NewPathAnalyzerWithConfigs(threshold, configs)
    Processor->>Analyzer: AnalyzePath for opens
    Analyzer->>Analyzer: processSegments with per-prefix thresholds
    Analyzer-->>Processor: Dynamic paths + literal paths
    Processor->>Consolidate: consolidateOpens(results, sbomSet)
    Consolidate->>Consolidate: Check each literal against patterns
    Consolidate-->>Processor: Filtered + merged results
    Processor-->>Processor: PreSave completes deflation
Loading

Suggested Labels

release

Suggested Reviewers

  • matthyx

🐰 A PR of dynamic collapse and network grace,
With configs in CRDs setting the pace,
Paths merge by threshold, and IP wildcards dance,
While validators keep bad patterns at bay—
A careful, thoughtful architectural advance! ✨

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

@entlein

entlein commented May 16, 2026 •

Copy link
Copy Markdown
Contributor Author

@CodeRabbit review this one together with kubescape/node-agent#810

@coderabbitai

coderabbitai Bot commented May 16, 2026

Copy link
Copy Markdown
🧩 Analysis chain

@entlein, I'll fetch the details of PR #326 and kick off a full review right away!


🏁 Script executed:

#!/bin/bash
# Fetch PR `#326` details
gh pr view 326 --repo kubescape/storage --json title,body,files,additions,deletions,commits,baseRefName,headRefName,author,labels,state

Length of output: 9559


@entlein, thanks for the context! This is a significant PR with 8,028 additions across 68 files. Here's a high-level overview of what I'm seeing before the full review kicks off:

Key Areas Introduced

Area Files
🆕 CollapseConfiguration CRD Types, registry, etcd, strategy, generated clientset/informers/listers/openapi
🌐 networkmatch package DNS + IP wildcard matching with benchmarks and tests
🔍 dynamicpathdetector enhancements Path/exec wildcards, collapse config from CRD, exec args comparison
🔏 networkneighborhood sign/tamper Strategy changes with new tests
⚙️ applicationprofile / containerprofile processors Collapse provider integration
🤖 Generated code Protobuf, deepcopy, conversions, OpenAPI, apply configs

I'll now run a thorough review across all changed files. Given the size and scope, I'll pay close attention to:

  • Correctness of wildcard matching logic (DNS/IP/path/exec)
  • CRD strategy validation
  • Sign/tamper integrity checks
  • Test coverage quality
  • Generated code consistency
✅ Actions performed

Full review triggered.

@coderabbitai

coderabbitai Bot commented May 16, 2026

Copy link
Copy Markdown
🧩 Analysis chain

Let me fetch both PRs so I can review them together with full context.


🏁 Script executed:

#!/bin/bash
# Fetch details of the current PR
gh pr view 326 --repo kubescape/storage --json title,body,files,additions,deletions,commits

echo "---NODE-AGENT PR---"
# Fetch details of the linked node-agent PR
gh pr view 810 --repo kubescape/node-agent --json title,body,files,additions,deletions,commits

Length of output: 20562


@entlein, I've reviewed both PRs together. Here's a cross-PR summary before triggering the full automated review:


Cross-PR Context: kubescape/storage#326 + kubescape/node-agent#810

These two PRs form a tightly coupled feature pair:

graph LR
    subgraph storage["kubescape/storage `#326`"]
        A["CollapseConfiguration CRD\n(new API type)"]
        B["networkmatch pkg\n(DNS + IP wildcards)"]
        C["dynamicpathdetector\n(path + exec wildcards)"]
        D["networkneighborhood\nstrategy updates"]
    end

    subgraph nodeagent["kubescape/node-agent `#810`"]
        E["pkg/signature\n(cosign sign/verify/tamper)"]
        F["CEL libraries\n(wildcard evaluation)"]
        G["Container profile cache\n(projection + tamper alert)"]
        H["Component tests\n(20 network wildcard fixtures)"]
    end

    A -->|consumed by| F
    B -->|consumed by| F
    C -->|consumed by| F
    D -->|consumed by| G
    E -->|signs profiles| G
Loading

Key highlights I'm noting for the review:

Aspect Detail
New CRD CollapseConfiguration — full lifecycle (types, registry, protobuf, openapi, informers, listers, clientset)
Wildcard matching DNS (leading *., mid ..., trailing *), IP/CIDR, exec-arg comparison
Signing/tamper Cosign-based sign+verify for ApplicationProfile / NetworkNeighborhood in node-agent
Memory impact -11.7% avg / -12.4% peak (from node-agent benchmarks)
Test coverage Extensive unit + component tests across both repos

Triggering the full review now with this cross-PR context in mind.

✅ Actions performed

Full review triggered.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/registry/file/dynamicpathdetector/tests/analyze_endpoints_test.go (1)

169-178: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add a length assertion before indexed comparisons.

On Line 174, the test iterates over result and indexes tt.expected[i] without first asserting equal lengths. If result is shorter than expected, missing endpoints won’t be detected.

Proposed fix
 		t.Run(tt.name, func(t *testing.T) {
 			analyzer := dynamicpathdetector.NewPathAnalyzerWithConfigs(dynamicpathdetector.EndpointDynamicThreshold, nil)
 			result := dynamicpathdetector.AnalyzeEndpoints(&tt.input, analyzer)
+			assert.Len(t, result, len(tt.expected))
 			ja := jsonassert.New(t)
 			for i := range result {
 				assert.Equal(t, tt.expected[i].Endpoint, result[i].Endpoint)
 				assert.Equal(t, tt.expected[i].Methods, result[i].Methods)
 				ja.Assert(string(result[i].Headers), string(tt.expected[i].Headers))
 			}
 		})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/registry/file/dynamicpathdetector/tests/analyze_endpoints_test.go` around
lines 169 - 178, The test iterates result and indexes tt.expected without
checking lengths; before the for-loop that ranges over result in the test (the
block that calls dynamicpathdetector.AnalyzeEndpoints and assigns result), add
an assertion that len(result) == len(tt.expected) to ensure mismatched lengths
fail the test; reference the test variable names result and tt.expected and the
call to dynamicpathdetector.AnalyzeEndpoints (and the analyzer created by
NewPathAnalyzerWithConfigs) so you place the length check immediately after
result is computed and before the indexed comparisons.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@go.mod`:
- Line 9: The diff downgraded critical modules—github.com/anchore/syft,
github.com/anchore/stereoscope, and
github.com/opencontainers/runtime-spec—reintroducing known CVE/behavior
regressions; revert these changes by restoring or pinning safe versions (e.g.,
github.com/anchore/syft at >= v1.42.3 to include CVE-2026-33481 fixes,
github.com/anchore/stereoscope to a version that patches the tar path traversal
vulnerability, and github.com/opencontainers/runtime-spec to v1.3.0+ to retain
spec features), then run go mod tidy and run the test suite/CI to ensure
compatibility; add a short PR note explaining why these exact versions are
required (security fixes and spec compatibility) so the downgrade rationale is
documented.

In `@pkg/apis/softwarecomposition/v1beta1/generated.proto`:
- Around line 134-177: The generated proto is out of sync with the Go struct:
add the missing ipAddresses field (field number 9) to the NetworkNeighbor
message in the protobuf definition so it matches the Go struct's IPAddresses
[]string protobuf tag (bytes,9,rep,name=ipAddresses), then re-run the protobuf
generation to update generated types (or regenerate the file that produced
CollapseConfiguration additions) so marshal/unmarshal uses the same schema;
ensure the NetworkNeighbor message contains "repeated string ipAddresses = 9;"
(or equivalent) and that the regenerated Go/JSON tags align with the existing
NetworkNeighbor.IPAddresses field.

In `@pkg/registry/file/applicationprofile_processor.go`:
- Line 92: The call to a.collapseSettings() inside ApplicationProfileProcessor
can panic when a is zero-valued; before using it in
deflateApplicationProfileContainer, obtain a local settings variable (e.g., cs
:= a.collapseSettings()) and if cs == nil set cs =
dynamicpathdetector.DefaultCollapseSettings, then pass cs to
deflateApplicationProfileContainer instead of calling a.collapseSettings()
inline; update the call site in the container loop (where
deflateApplicationProfileContainer is invoked) to use this guarded local
variable.

In `@pkg/registry/file/dynamicpathdetector/analyzer.go`:
- Around line 397-433: The recursive wildcard backtracking in compareSegments
can explode exponentially; add memoization keyed by the pair of positions in the
two slices to cache boolean results and short-circuit repeated subcalls.
Implement either a small wrapper (e.g., compareSegmentsMemo or change
compareSegments signature to accept indices di, ri plus a memo map) where the
memo key is a pair (di, ri) or a compact int64/struct, check memo at entry,
compute as now, store the true/false result in memo before returning, and use
that memo for the loop that tries offsets when dynamic[0] == WildcardIdentifier;
keep existing semantics for WildcardIdentifier and DynamicIdentifier unchanged.

In `@pkg/registry/file/dynamicpathdetector/tests/compare_exec_args_test.go`:
- Around line 284-313: The timing assertion in
TestCompareExecArgs_ReDoSResistance is too brittle; update the test to avoid CI
flakes by (1) skipping the timing check when testing.Short() is true and (2)
raising the wall‑clock cap from 100ms to a more generous value (e.g. 500ms) for
the remaining runs. Modify the TestCompareExecArgs_ReDoSResistance function to
wrap the elapsed > threshold check with a conditional that first returns if
testing.Short() and otherwise uses the larger threshold when asserting
performance of dynamicpathdetector.CompareExecArgs.

---

Outside diff comments:
In `@pkg/registry/file/dynamicpathdetector/tests/analyze_endpoints_test.go`:
- Around line 169-178: The test iterates result and indexes tt.expected without
checking lengths; before the for-loop that ranges over result in the test (the
block that calls dynamicpathdetector.AnalyzeEndpoints and assigns result), add
an assertion that len(result) == len(tt.expected) to ensure mismatched lengths
fail the test; reference the test variable names result and tt.expected and the
call to dynamicpathdetector.AnalyzeEndpoints (and the analyzer created by
NewPathAnalyzerWithConfigs) so you place the length check immediately after
result is computed and before the indexed comparisons.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e12e4fd2-1b66-4ed9-b497-e7bf4ca9c574

📥 Commits

Reviewing files that changed from the base of the PR and between 2a689d8 and db0c766.

⛔ Files ignored due to path filters (18)
  • go.sum is excluded by !**/*.sum
  • pkg/apis/softwarecomposition/v1beta1/generated.pb.go is excluded by !**/*.pb.go
  • pkg/apis/softwarecomposition/v1beta1/generated.protomessage.pb.go is excluded by !**/*.pb.go
  • pkg/generated/applyconfiguration/softwarecomposition/v1beta1/collapseconfigentry.go is excluded by !**/generated/**
  • pkg/generated/applyconfiguration/softwarecomposition/v1beta1/collapseconfiguration.go is excluded by !**/generated/**
  • pkg/generated/applyconfiguration/softwarecomposition/v1beta1/collapseconfigurationspec.go is excluded by !**/generated/**
  • pkg/generated/applyconfiguration/utils.go is excluded by !**/generated/**
  • pkg/generated/clientset/versioned/typed/softwarecomposition/v1beta1/collapseconfiguration.go is excluded by !**/generated/**
  • pkg/generated/clientset/versioned/typed/softwarecomposition/v1beta1/fake/fake_collapseconfiguration.go is excluded by !**/generated/**
  • pkg/generated/clientset/versioned/typed/softwarecomposition/v1beta1/fake/fake_softwarecomposition_client.go is excluded by !**/generated/**
  • pkg/generated/clientset/versioned/typed/softwarecomposition/v1beta1/generated_expansion.go is excluded by !**/generated/**
  • pkg/generated/clientset/versioned/typed/softwarecomposition/v1beta1/softwarecomposition_client.go is excluded by !**/generated/**
  • pkg/generated/informers/externalversions/generic.go is excluded by !**/generated/**
  • pkg/generated/informers/externalversions/softwarecomposition/v1beta1/collapseconfiguration.go is excluded by !**/generated/**
  • pkg/generated/informers/externalversions/softwarecomposition/v1beta1/interface.go is excluded by !**/generated/**
  • pkg/generated/listers/softwarecomposition/v1beta1/collapseconfiguration.go is excluded by !**/generated/**
  • pkg/generated/listers/softwarecomposition/v1beta1/expansion_generated.go is excluded by !**/generated/**
  • pkg/generated/openapi/zz_generated.openapi.go is excluded by !**/generated/**
📒 Files selected for processing (52)
  • .gitignore
  • artifacts/collapseconfiguration-default-sample.yaml
  • go.mod
  • pkg/apis/softwarecomposition/collapse_types.go
  • pkg/apis/softwarecomposition/network_types.go
  • pkg/apis/softwarecomposition/register.go
  • pkg/apis/softwarecomposition/v1beta1/collapse_types.go
  • pkg/apis/softwarecomposition/v1beta1/generated.proto
  • pkg/apis/softwarecomposition/v1beta1/network_types.go
  • pkg/apis/softwarecomposition/v1beta1/network_types_protobuf_test.go
  • pkg/apis/softwarecomposition/v1beta1/register.go
  • pkg/apis/softwarecomposition/v1beta1/zz_generated.conversion.go
  • pkg/apis/softwarecomposition/v1beta1/zz_generated.deepcopy.go
  • pkg/apis/softwarecomposition/v1beta1/zz_generated.model_name.go
  • pkg/apis/softwarecomposition/zz_generated.deepcopy.go
  • pkg/apiserver/apiserver.go
  • pkg/registry/file/applicationprofile_processor.go
  • pkg/registry/file/applicationprofile_processor_collapse_provider_test.go
  • pkg/registry/file/applicationprofile_processor_test.go
  • pkg/registry/file/cleanup.go
  • pkg/registry/file/cleanup_test.go
  • pkg/registry/file/containerprofile_processor.go
  • pkg/registry/file/containerprofile_processor_collapse_provider_test.go
  • pkg/registry/file/dynamicpathdetector/analyze_endpoints.go
  • pkg/registry/file/dynamicpathdetector/analyze_endpoints_internal_test.go
  • pkg/registry/file/dynamicpathdetector/analyze_opens.go
  • pkg/registry/file/dynamicpathdetector/analyzer.go
  • pkg/registry/file/dynamicpathdetector/collapse_config_from_crd.go
  • pkg/registry/file/dynamicpathdetector/compare_exec_args.go
  • pkg/registry/file/dynamicpathdetector/tests/analyze_endpoints_test.go
  • pkg/registry/file/dynamicpathdetector/tests/analyze_opens_test.go
  • pkg/registry/file/dynamicpathdetector/tests/benchmark_test.go
  • pkg/registry/file/dynamicpathdetector/tests/collapse_config_crd_test.go
  • pkg/registry/file/dynamicpathdetector/tests/compare_exec_args_test.go
  • pkg/registry/file/dynamicpathdetector/tests/consolidate_opens_test.go
  • pkg/registry/file/dynamicpathdetector/tests/coverage_test.go
  • pkg/registry/file/dynamicpathdetector/tests/profile_test.go
  • pkg/registry/file/dynamicpathdetector/types.go
  • pkg/registry/file/networkmatch/README.md
  • pkg/registry/file/networkmatch/bench_test.go
  • pkg/registry/file/networkmatch/doc.go
  • pkg/registry/file/networkmatch/match_dns.go
  • pkg/registry/file/networkmatch/match_dns_test.go
  • pkg/registry/file/networkmatch/match_ip.go
  • pkg/registry/file/networkmatch/match_ip_test.go
  • pkg/registry/file/networkmatch/validate.go
  • pkg/registry/file/networkmatch/validate_test.go
  • pkg/registry/softwarecomposition/collapseconfiguration/etcd.go
  • pkg/registry/softwarecomposition/collapseconfiguration/strategy.go
  • pkg/registry/softwarecomposition/collapseconfiguration/strategy_test.go
  • pkg/registry/softwarecomposition/networkneighborhood/strategy.go
  • pkg/registry/softwarecomposition/networkneighborhood/strategy_test.go

Comment thread go.mod Resolved
Signed-off-by: entlein <einentlein@gmail.com>
@entlein

entlein commented May 16, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Collective re-review request after applying your atomic-split advisory + rabbit-feedback fixes across the full SBOB upstream PR set. Each PR is now scoped to a single tier per your dependency map:

Tier 0 (opens):

Tier 2 (execs):

Tier 3 (network):

Tier 4 (tamper/sign):

Umbrellas:

Please confirm atomicity per your earlier advisory and flag any remaining cross-PR coupling we missed.

@coderabbitai

coderabbitai Bot commented May 16, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Fetch details of the atomic storage PRs
for pr in 322 323 324 325; do
  echo "=== kubescape/storage PR #$pr ==="
  gh pr view $pr --repo kubescape/storage --json title,state,headRefName,baseRefName,additions,deletions,files \
    | jq '{title, state, head: .headRefName, base: .baseRefName, additions, deletions, fileCount: (.files | length), files: [.files[].path]}'
  echo ""
done

Length of output: 5716


@entlein, the tier split looks structurally sound. Here's my atomicity confirmation and the cross-PR coupling gaps I found:


✅ Confirmed Atomic

PR Files Assessment
storage#322 2 files — compare_exec_args.go + test ✅ Perfectly isolated
storage#323 12 files — all dynamicpathdetector core ✅ Self-contained foundational layer
storage#324 14 files — networkmatch + network_types.go + networkneighborhood/strategy.go ✅ Self-contained
storage#325 40 files — CRD types, processors, generated code ✅ Correctly depends on #323 (Tier 0 first)

⚠️ Remaining Cross-PR Coupling Gaps

1. go.mod dependency downgrade is orphaned in the umbrella only

The syft downgrade (v1.42.3 → v1.32.0), stereoscope (v0.1.22 → v0.1.9), and runtime-spec (v1.3.0 → v1.2.1) appear only in storage#326, not in any atomic PR. If the atomic PRs merge and the umbrella is discarded, this fix is lost.

Action: Assign the go.mod/go.sum change to one of the atomic PRs (storage#325 is the best fit as the infrastructure tier) or open a dedicated chore PR.

2. Generated deepcopy/conversion for IPAddresses is orphaned

storage#324 adds the IPAddresses []string field to NetworkNeighbor in both the internal and v1beta1 types, but the generated zz_generated.deepcopy.go and zz_generated.conversion.go updates for that field are only present in the umbrella storage#326. Without those, #324 would leave the codebase in an inconsistent state (field defined, generators not re-run).

Action: Re-run controller-gen and conversion-gen in the storage#324 branch and commit the updated zz_generated.* files.

3. .gitignore changes are umbrella-only

tmp/ and .claude/ additions exist only in storage#326.

Action: Minor — move to storage#325 (or a housekeeping PR) if the umbrella isn't being merged.

4. Tier 1 gap in the numbering

The tier map jumps 0 → 2 with no Tier 1 listed. Was Tier 1 intentionally skipped (e.g., a tier that was merged or collapsed into Tier 0), or is there a missing PR?

5. storage#323 title says "R0040 args" — verify scope leak

The title of storage#323 mentions "R0040 args" but the R0040 args consumer is attributed to node-agent#807. Please confirm no R0040-specific dispatch logic leaked into storage#323 (the dynamicpathdetector core should only define the CompareExecArgs primitive, with the R0040 consumer living in node-agent).


Merge Order (confirmed correct)

storage#322 ─────────────────────────────────── Tier 2 (independent)
storage#323 ──┐                                  Tier 0
              └──► storage#325 ─────────────── Tier 2 (depends on `#323`)
storage#324 ─────────────────────────────────── Tier 3 (independent of `#322/`#323)

Triggering the full re-review of storage#326 now.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented May 16, 2026

Copy link
Copy Markdown
🧩 Analysis chain

@entlein, let me fetch the details of all the tiered PRs to verify atomicity and flag any remaining cross-PR coupling.


🏁 Script executed:

#!/bin/bash
# Fetch all storage PRs
echo "=== storage#322 ==="
gh pr view 322 --repo kubescape/storage --json title,body,files,baseRefName,headRefName,state 2>/dev/null | jq '{title,state,base:.baseRefName,head:.headRefName,files:[.files[].path]}'

echo "=== storage#323 ==="
gh pr view 323 --repo kubescape/storage --json title,body,files,baseRefName,headRefName,state 2>/dev/null | jq '{title,state,base:.baseRefName,head:.headRefName,files:[.files[].path]}'

echo "=== storage#324 ==="
gh pr view 324 --repo kubescape/storage --json title,body,files,baseRefName,headRefName,state 2>/dev/null | jq '{title,state,base:.baseRefName,head:.headRefName,files:[.files[].path]}'

echo "=== storage#325 ==="
gh pr view 325 --repo kubescape/storage --json title,body,files,baseRefName,headRefName,state 2>/dev/null | jq '{title,state,base:.baseRefName,head:.headRefName,files:[.files[].path]}'

echo "=== storage#326 (umbrella) ==="
gh pr view 326 --repo kubescape/storage --json title,body,files,baseRefName,headRefName,state 2>/dev/null | jq '{title,state,base:.baseRefName,head:.headRefName,fileCount:(.files|length)}'

Unrecoverable error: Failed to clone repository


🏁 Script executed:

#!/bin/bash
# Fetch all node-agent PRs
echo "=== node-agent#805 ==="
gh pr view 805 --repo kubescape/node-agent --json title,body,files,baseRefName,headRefName,state 2>/dev/null | jq '{title,state,base:.baseRefName,head:.headRefName,files:[.files[].path]}'

echo "=== node-agent#806 ==="
gh pr view 806 --repo kubescape/node-agent --json title,body,files,baseRefName,headRefName,state 2>/dev/null | jq '{title,state,base:.baseRefName,head:.headRefName,files:[.files[].path]}'

echo "=== node-agent#807 ==="
gh pr view 807 --repo kubescape/node-agent --json title,body,files,baseRefName,headRefName,state 2>/dev/null | jq '{title,state,base:.baseRefName,head:.headRefName,files:[.files[].path]}'

echo "=== node-agent#808 ==="
gh pr view 808 --repo kubescape/node-agent --json title,body,files,baseRefName,headRefName,state 2>/dev/null | jq '{title,state,base:.baseRefName,head:.headRefName,files:[.files[].path]}'

echo "=== node-agent#809 ==="
gh pr view 809 --repo kubescape/node-agent --json title,body,files,baseRefName,headRefName,state 2>/dev/null | jq '{title,state,base:.baseRefName,head:.headRefName,files:[.files[].path]}'

echo "=== node-agent#811 ==="
gh pr view 811 --repo kubescape/node-agent --json title,body,files,baseRefName,headRefName,state 2>/dev/null | jq '{title,state,base:.baseRefName,head:.headRefName,files:[.files[].path]}'

echo "=== node-agent#812 ==="
gh pr view 812 --repo kubescape/node-agent --json title,body,files,baseRefName,headRefName,state 2>/dev/null | jq '{title,state,base:.baseRefName,head:.headRefName,files:[.files[].path]}'

echo "=== node-agent#810 (umbrella) ==="
gh pr view 810 --repo kubescape/node-agent --json title,body,files,baseRefName,headRefName,state 2>/dev/null | jq '{title,state,base:.baseRefName,head:.headRefName,fileCount:(.files|length)}'

Unrecoverable error: Failed to clone repository


🏁 Script executed:

#!/bin/bash
# Fetch all storage PRs - no clone needed for gh CLI
echo "=== storage#322 ==="
gh pr view 322 --repo kubescape/storage --json title,state,baseRefName,headRefName,files 2>/dev/null | jq '{title,state,base:.baseRefName,head:.headRefName,files:[.files[].path]}'

echo ""
echo "=== storage#323 ==="
gh pr view 323 --repo kubescape/storage --json title,state,baseRefName,headRefName,files 2>/dev/null | jq '{title,state,base:.baseRefName,head:.headRefName,files:[.files[].path]}'

echo ""
echo "=== storage#324 ==="
gh pr view 324 --repo kubescape/storage --json title,state,baseRefName,headRefName,files 2>/dev/null | jq '{title,state,base:.baseRefName,head:.headRefName,files:[.files[].path]}'

echo ""
echo "=== storage#325 ==="
gh pr view 325 --repo kubescape/storage --json title,state,baseRefName,headRefName,files 2>/dev/null | jq '{title,state,base:.baseRefName,head:.headRefName,files:[.files[].path]}'

echo ""
echo "=== node-agent#805 ==="
gh pr view 805 --repo kubescape/node-agent --json title,state,baseRefName,headRefName,files 2>/dev/null | jq '{title,state,base:.baseRefName,head:.headRefName,files:[.files[].path]}'

echo ""
echo "=== node-agent#806 ==="
gh pr view 806 --repo kubescape/node-agent --json title,state,baseRefName,headRefName,files 2>/dev/null | jq '{title,state,base:.baseRefName,head:.headRefName,files:[.files[].path]}'

echo ""
echo "=== node-agent#807 ==="
gh pr view 807 --repo kubescape/node-agent --json title,state,baseRefName,headRefName,files 2>/dev/null | jq '{title,state,base:.baseRefName,head:.headRefName,files:[.files[].path]}'

echo ""
echo "=== node-agent#808 ==="
gh pr view 808 --repo kubescape/node-agent --json title,state,baseRefName,headRefName,files 2>/dev/null | jq '{title,state,base:.baseRefName,head:.headRefName,files:[.files[].path]}'

echo ""
echo "=== node-agent#809 ==="
gh pr view 809 --repo kubescape/node-agent --json title,state,baseRefName,headRefName,files 2>/dev/null | jq '{title,state,base:.baseRefName,head:.headRefName,files:[.files[].path]}'

echo ""
echo "=== node-agent#811 ==="
gh pr view 811 --repo kubescape/node-agent --json title,state,baseRefName,headRefName,files 2>/dev/null | jq '{title,state,base:.baseRefName,head:.headRefName,files:[.files[].path]}'

echo ""
echo "=== node-agent#812 ==="
gh pr view 812 --repo kubescape/node-agent --json title,state,baseRefName,headRefName,files 2>/dev/null | jq '{title,state,base:.baseRefName,head:.headRefName,files:[.files[].path]}'

Unrecoverable error: Stream setup permanently failed: 14 UNAVAILABLE: Connection dropped


@entlein, the script environment hit a connectivity issue, so I'm working from the umbrella PR's AI summaries and your tier breakdown. Here's my atomicity assessment and cross-PR coupling analysis:


✅ Confirmed Atomic / Well-Scoped

PR Assessment
storage#322 (CompareExecArgs) ✅ Fully atomic — single new function + tests, no external dependencies within the set
storage#324 (networkmatch) ✅ Mostly clean — match_dns.go defines its own DNSWildcardLabel = "*" rather than importing from dynamicpathdetector, so it's decoupled from Tier 0
node-agent#808/809 (tamper/sign) ✅ Self-contained Tier 4 — no storage API types changes needed beyond what lower tiers provide

⚠️ Cross-PR Couplings Still Present

1. storage#325 → storage#323 (hard dependency)

collapse_config_from_crd.go (storage#325) introduces CollapseSettings and CollapseSettingsProvider, which wrap the CollapseConfig struct and DefaultCollapseConfigs() — both defined in types.go (storage#323). Similarly, applicationprofile_processor.go and containerprofile_processor.go call NewPathAnalyzerWithConfigs([]CollapseConfig, ...) which is also storage#323. storage#325 cannot merge before storage#323.

Action: Confirm this is already captured in your dependency map (storage#325 is Tier 2, storage#323 is Tier 0 — ordering is correct, but the dependency should be explicit in each PR's description).

2. cleanup.go (isUserManaged) — unassigned to any tier

The isUserManaged helper (checking ManagedByMetadataKey annotation) is in the umbrella but doesn't appear in any tiered PR description. From the semantics, it's likely a prerequisite for Tier 4 tamper detection (user-managed resources should be exempt from tamper alerts).

Action: Assign to storage#325 (CRD/processors tier) or create a standalone PR. It touches pkg/registry/file/cleanup.go which is orthogonal enough to be its own micro-PR.

3. go.mod downgrade — unassigned to any tier

The syft v1.42.3 → v1.32.0 and stereoscope v0.1.22 → v0.1.9 downgrades live only in the umbrella. No tiered PR description claims this.

Action: Determine which tier first requires the downgraded version (likely storage#325 if it exercises SBOM-related code paths). Either include it there or issue a standalone go.mod PR.

4. networkneighborhood/strategy.go validation → storage#324

The admission-time validation in networkneighborhood/strategy.go calls networkmatch.ValidateIPEntry and networkmatch.ValidateDNSEntry. This means strategy.go changes must be in the same PR as the networkmatch package (storage#324) or a dependent Tier 3+ PR.

Action: Confirm storage#324 includes pkg/registry/softwarecomposition/networkneighborhood/strategy.go (and its test). If not, it needs its own PR that lists storage#324 as a prereq.

5. network_types.go (IPAddresses field) + protobuf test — tier placement

The IPAddresses []string field addition and its protobuf roundtrip test feel like they belong in storage#324 alongside networkmatch. Confirm these are in storage#324 and not left only in the umbrella.

6. node-agent#811 → storage#323 (runtime dependency)

was_path_opened* CEL helpers in node-agent#811 will need storage#323's WildcardIdentifier and CompareDynamic to be deployed first. This is a correct runtime ordering (Tier 0 before Tier 0 node-agent) — just make sure the node-agent#811 PR description explicitly lists storage#323 as a deployment prereq.

7. Missing Tier 1 — intentional?

Your tier numbering jumps 0 → 2. Was Tier 1 merged/dropped, or is this intentional numbering (e.g., Tier 1 = "exec primitives" that got absorbed into Tier 2)?


Dependency Ordering Diagram

graph TD
    s323["storage#323\nTier 0: path-wildcards core\n(WildcardIdentifier, CollapseConfig API,\nanchored trailing-*, per-port key)"]
    s322["storage#322\nTier 2: CompareExecArgs\n(independent)"]
    s325["storage#325\nTier 2: CollapseConfig CRD + processors"]
    s324["storage#324\nTier 3: networkmatch + NN strategy validation"]
    na811["node-agent#811\nTier 0: was_path_opened* CEL"]
    na805["node-agent#805\nTier 2: resolveExecPath"]
    na807["node-agent#807\nTier 2: R0040 args consumer"]
    na812["node-agent#812\nTier 2: ExecsByPath"]
    na806["node-agent#806\nTier 3: network wildcards CEL"]
    na808["node-agent#808\nTier 4: projection/tamper/NN"]
    na809["node-agent#809\nTier 4: cosign sign/verify"]

    s323 -->|required by| s325
    s323 -->|runtime deploy before| na811
    s322 -->|required by| na805
    s322 -->|required by| na807
    s322 -->|required by| na812
    s324 -->|required by| na806
    s325 -->|required by| na808
    s324 -->|required by| na808
    na808 -->|required by| na809

    style s323 fill:rgba(34,197,94,0.5)
    style s322 fill:rgba(34,197,94,0.5)
    style s324 fill:rgba(59,130,246,0.5)
    style s325 fill:rgba(234,179,8,0.5)
    style na811 fill:rgba(34,197,94,0.5)
    style na808 fill:rgba(239,68,68,0.5)
    style na809 fill:rgba(239,68,68,0.5)
Loading

Summary of Actions Needed

  1. storage#325 description — explicitly call out the dependency on storage#323
  2. cleanup.go + go.mod — assign to a tier or create micro-PRs
  3. storage#324 — confirm it includes networkneighborhood/strategy.go, network_types.go (IPAddresses field), and the protobuf roundtrip test
  4. node-agent#811 description — note storage#323 must be deployed first
  5. Tier 1 gap — clarify if intentional

The split is structurally sound — the couplings above are manageable ordering constraints rather than true tangling. The cleanup.go / go.mod orphans are the most immediately actionable gaps.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@entlein

entlein commented May 16, 2026

Copy link
Copy Markdown
Contributor Author

the syft downgrade (etc) was now addressed in storage , we should be perfectly aligned with upstream, please recheck
I m replying to your Action: Assign the go.mod/go.sum change to one of the atomic PRs (storage#325 is the best fit as the infrastructure tier) or open a dedicated chore PR.

Signed-off-by: entlein <einentlein@gmail.com>
@matthyx matthyx moved this to WIP in KS PRs tracking May 26, 2026
@entlein

entlein commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

superseded by the other PRs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

1 participant