Skip to content

rebase storage, CRDs, exec arg wildcard#27

Merged
entlein merged 3 commits into
mainfrom
merge/exec-arg-wildcards
May 9, 2026
Merged

rebase storage, CRDs, exec arg wildcard#27
entlein merged 3 commits into
mainfrom
merge/exec-arg-wildcards

Conversation

@entlein
Copy link
Copy Markdown

@entlein entlein commented May 4, 2026

…in exec arg vectors

User-defined ApplicationProfile entries can now express argument-vector patterns containing two wildcard tokens, exposed via the existing constants:

DynamicIdentifier ("⋯") — matches exactly one argument position.
WildcardIdentifier ("*") — matches zero or more consecutive args.

Anything else is a literal-equality match. The match is anchored at both ends — every runtime arg must be consumed by the profile vector, either by a literal, a single-position ⋯, or a *-absorbing run.

Implementation is recursive backtracking. Real exec arg vectors are short (typically ≤ a dozen entries) with at most a handful of wildcards, so the worst case stays well below a regex compile and we avoid the ReDoS surface that comes with regex.

40 unit subtests cover empty/literal/dynamic/wildcard/mixed/realistic patterns; matcher is consumer-ready for node-agent's CEL exec rule.

Sorry, we do not accept changes directly against this repository. Please see
CONTRIBUTING.md for information on where and how to contribute instead.

…in exec arg vectors

User-defined ApplicationProfile entries can now express argument-vector
patterns containing two wildcard tokens, exposed via the existing
constants:

  DynamicIdentifier  ("⋯") — matches exactly one argument position.
  WildcardIdentifier ("*") — matches zero or more consecutive args.

Anything else is a literal-equality match. The match is anchored at
both ends — every runtime arg must be consumed by the profile vector,
either by a literal, a single-position ⋯, or a *-absorbing run.

Implementation is recursive backtracking. Real exec arg vectors are
short (typically ≤ a dozen entries) with at most a handful of
wildcards, so the worst case stays well below a regex compile and we
avoid the ReDoS surface that comes with regex.

40 unit subtests cover empty/literal/dynamic/wildcard/mixed/realistic
patterns; matcher is consumer-ready for node-agent's CEL exec rule.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 4, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f1fe360d-3058-4a5d-ad8b-58d1a0b2af18

📥 Commits

Reviewing files that changed from the base of the PR and between b0d68d3 and 9f08740.

📒 Files selected for processing (2)
  • pkg/registry/file/dynamicpathdetector/compare_exec_args.go
  • pkg/registry/file/dynamicpathdetector/tests/compare_exec_args_test.go

📝 Walkthrough

Walkthrough

Adds CompareExecArgs(profileArgs, runtimeArgs []string) bool to perform anchored matching between a profile argv vector and a runtime argv vector using literal tokens plus two special tokens: (exactly one argument) and * (zero-or-more arguments). Empty profileArgs matches any runtimeArgs.

Changes

Argument Vector Matching

Layer / File(s) Summary
API / Entry
pkg/registry/file/dynamicpathdetector/compare_exec_args.go
Adds exported CompareExecArgs(profileArgs, runtimeArgs []string) bool. Special-case: empty profileArgs returns true (no argv constraint).
Core Matcher
pkg/registry/file/dynamicpathdetector/compare_exec_args.go
Implements unexported matchExecArgs with anchored recursive matching: * tries 0..N runtime consumptions with backtracking, consumes exactly one runtime element, literals require equality, success only when both slices are fully consumed. Uses memoization to avoid exponential backtracking.
Tests
pkg/registry/file/dynamicpathdetector/tests/compare_exec_args_test.go
Adds comprehensive table-driven tests covering literal matches, , *, mixed-token interactions, realistic CLI patterns, edge cases (empty profile/runtime), adjacent tokens, and a ReDoS-resistance timing test to assert memoisation prevents exponential blow-up.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title partially relates to the changeset—it mentions 'exec arg wildcard' which is present, but obscures the main contribution with unrelated items ('rebase storage, CRDs'). Clarify the title to focus on the primary change: consider 'Add exec argument vector matching with wildcard support' or similar.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The description clearly explains the exec arg wildcard matching feature, implementation details, and test coverage, directly relating to the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch merge/exec-arg-wildcards

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/registry/file/dynamicpathdetector/compare_exec_args.go`:
- Around line 26-33: The wildcard branch in CompareExecArgs can cause
exponential backtracking; add memoization keyed by (profileIndex, runtimeIndex)
to avoid re-evaluating the same subproblem. Implement a small helper (e.g.,
compareExecArgsMemo or make CompareExecArgs accept indices) that takes
profileArgs, runtimeArgs, current indices (i, j) and a memo map[uint64]bool or
map[string]bool, check the memo at the start and return cached result if
present, compute the result (including the WildcardIdentifier loop), store the
result in memo before returning, and have CompareExecArgs call this helper—use
the pair (i,j) as the unique key to identify subcalls.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: c0f9768b-8f84-4d37-9995-6a7cdcc0be60

📥 Commits

Reviewing files that changed from the base of the PR and between aaed917 and 43795bb.

📒 Files selected for processing (2)
  • pkg/registry/file/dynamicpathdetector/compare_exec_args.go
  • pkg/registry/file/dynamicpathdetector/tests/compare_exec_args_test.go

Comment thread pkg/registry/file/dynamicpathdetector/compare_exec_args.go Outdated
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 4, 2026

Summary:

  • License scan: failure
  • Credentials scan: skipped
  • Vulnerabilities scan: skipped
  • Unit test: success
  • Go linting: failure

CodeRabbit (node-agent PR kubescape#38). Path-only Execs entries in user-defined
ApplicationProfiles (the common case) carry a nil/empty Args slice. The
strict empty-vs-empty semantics caused R0040 to fire on every legit exec
of those paths because was_executed_with_args returned false even when
the profile had explicitly allowed the path.

Split CompareExecArgs into a thin outer wrapper (empty profile → match)
and a strict inner matcher (matchExecArgs, retains the original empty-
empty anchor). This preserves the recursive backtracking's anchoring
contract — profile fully consumed in the middle of recursion still
fails when runtime has args left — while letting the public API treat
empty input as 'no constraint'.

Test pin: empty profile + multi-arg runtime returns true; both-empty
still true (degenerate); non-empty profile + empty runtime stays false.
Existing 30+ subtests for literal/dynamic/wildcard/mixed all pass.
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 4, 2026

Summary:

  • License scan: failure
  • Credentials scan: skipped
  • Vulnerabilities scan: skipped
  • Unit test: success
  • Go linting: failure

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 4, 2026

Test Results

 9 files   9 suites   1h 6m 43s ⏱️
10 tests  7 ✅ 0 💤 3 ❌
18 runs  14 ✅ 0 💤 4 ❌

For more details on these failures, see this check.

Results for commit b0d68d3.

♻️ This comment has been updated with latest results.

CodeRabbit Major finding on storage PR #27 (compare_exec_args.go:56).
Naïve recursive backtracking on '[*, *, *, …, literal]' patterns
re-explores every prefix split before the trailing-literal mismatch
surfaces, degrading to exponential time on adversarial inputs. This
is the canonical ReDoS-style hazard for wildcard matchers.

Switch to index-based recursion with memoisation on (profileIndex,
runtimeIndex) state pairs. Both indices only shrink during recursion
so the reachable state space is bounded by (len(profile)+1) *
(len(runtime)+1), giving O(P*R) total work.

Behaviour unchanged: all 30+ existing subtests across literal /
DynamicIdentifier / WildcardIdentifier / mixed / realistic groups
still pass. Outer empty-profile-as-wildcard short-circuit retained.

Add TestCompareExecArgs_ReDoSResistance: 20 leading wildcards + a
non-matching trailing literal vs a 50-element runtime. The naïve
matcher would take seconds (~2^20 path splits); the memoised matcher
completes in microseconds. Test asserts <100ms — generous budget that
catches any regression to the unmemoised form.
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 6, 2026

Summary:

  • License scan: failure
  • Credentials scan: skipped
  • Vulnerabilities scan: skipped
  • Unit test: success
  • Go linting: failure

@entlein entlein merged commit a7e6234 into main May 9, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant