Skip to content

🐛 llx: stop array contains/difference builtins panicking on a null argument#8320

Open
tas50 wants to merge 2 commits into
mainfrom
worktree-fix-pam-containsall-panic
Open

🐛 llx: stop array contains/difference builtins panicking on a null argument#8320
tas50 wants to merge 2 commits into
mainfrom
worktree-fix-pam-containsall-panic

Conversation

@tas50

@tas50 tas50 commented Jun 10, 2026

Copy link
Copy Markdown
Member

Fixes #8319

Problem

A surge of client scan panics (panic: interface conversion: interface {} is nil, not []interface {}) traced to the array contains*/difference builtins.

arrayContainsAll, arrayContainsNone, and arrayDifferenceV2 guard the receiver array against null but then perform an unchecked arg.Value.([]any) on the argument. When the argument resolves to a typed null array — e.g. a map[string][]T key miss like pam.conf.services["su"] on hosts with no /etc/pam.d (container-optimized k8s node OSes: COS, Flatcar, Bottlerocket) — that type assertion panics.

Because the MQL executor runs blocks in goroutines, the panic is unrecoverable by the caller and crashes the entire scan rather than failing the single check. The dict variants (dictContainsAll/dictContainsNone) already use the safe comma-ok form, so only the array variants were affected.

Fix

Guard the argument the same way the receiver is already guarded: a null argument propagates as null (placed before the type check so an untyped null short-circuits cleanly too). The compiled … == [] wrapper then resolves the check to a clean pass/fail.

After the fix, realArray.containsAll(nullArg) returns null → the check resolves to false (fails cleanly) instead of crashing. Whether a pam-absent host should pass or fail the check remains a policy decision; the engine's responsibility here is simply to not panic.

Testing

  • Reproduced the exact panic with a = {a: [1,2]}; [1,2,3].containsAll(a['b']) (typed-null arg via map key miss); confirmed crash pre-fix, clean result post-fix.
  • Added regression cases for containsAll / containsNone / difference to TestArray.
  • go test ./llx/ and the full ./providers/core/resources/ suite pass.

…gument

`arrayContainsAll`, `arrayContainsNone`, and `arrayDifferenceV2` guarded the
receiver array against null but then did an unchecked `arg.Value.([]any)` on
the argument. When the argument resolves to a typed null array — e.g. a
`map[string][]T` key miss such as `pam.conf.services["su"]` on a host with no
`/etc/pam.d` (COS, Flatcar, Bottlerocket k8s nodes) — that assertion panics
with `interface conversion: interface {} is nil, not []interface {}`.

Because the executor runs blocks in goroutines the panic is unrecoverable and
crashes the entire scan rather than failing the single check. The dict
variants already use the safe comma-ok form; only the array variants were
affected.

Guard the argument the same way the receiver is guarded: a null argument
propagates as null. The compiled `… == []` wrapper then resolves the check to
a clean pass/fail instead of crashing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@mondoo-code-review mondoo-code-review 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.

Fixes scan crashes when array builtins (containsAll, containsNone, difference) receive a null argument

@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Test Results

9 872 tests  +4   9 866 ✅ +4   4m 52s ⏱️ + 1m 41s
  543 suites ±0       6 💤 ±0 
   40 files   ±0       0 ❌ ±0 

Results for commit bef0ef7. ± Comparison against base commit 1e52755.

♻️ This comment has been updated with latest results.

@jaym

jaym commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Fixes #8319

mondoo-linux-security's su-restriction check relies on
`groups.containsAll(suRestrictedGroups)` being true when suRestrictedGroups is
an empty (typed, non-null) []string. Add a regression test pinning that
containsAll of an empty list is vacuously satisfied, distinct from the null-arg
case which propagates null.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

panic in llx.arrayContainsAll when containsAll argument evaluates to null (interface conversion: interface {} is nil)

2 participants