elastic / elastic/integrations
[bug-hunter] CrowdStrike identity assessment stream can stall after low remainingPoints
- Dominant language
- Handlebars
- Stars
- 333
- Forks
- 647
- Avg merge
- 3d 4h
- Merged PRs (30d)
- 209
Description
## Impact
The CrowdStrike `identity_protection_assessment` stream can stop ingesting assessment events and never recover after one low-point response. Affected users silently stop receiving new identity assessment data.
## Reproduction Steps
1. From repository root, run this new minimal failing test:
```python
# repro_identity_assessment_stall.py
state = {
'worklist': ['d1', 'd2'],
'next': 0,
'last_remaining': 50,
'min_remaining_points': 100,
}
def step(s):
s = dict(s)
# Mirrors packages/crowdstrike/.../cel.yml.hbs logic.
if not ('worklist' in s and len(s['worklist']) > 0):
s.update({'worklist': ['new-domain'], 'next': 0, 'last_remaining': 500000})
if ('worklist' not in s) or len(s['worklist']) == 0:
return s
if int(s.get('next', 0)) >= len(s['worklist']):
out = dict(s); out.update({'events': [], 'want_more': False})
out.pop('worklist', None); out.pop('next', None); out.pop('last_remaining', None)
return out
if ('last_remaining' in s) and int(s['last_remaining']) < int(s['min_remaining_points']):
out = dict(s); out.update({'events': [], 'want_more': False})
return out
return dict(s, events=[{'ok': True}], next=int(s['next']) + 1, want_more=int(s['next']) + 1 < len(s['worklist']))
s1 = step(state)
s2 = step(s1)
# Expected recovery path: throttled state should be reset so next tick can re-fetch domains.
assert 'worklist' not in s2, f"BUG: stale worklist persists and stream stalls: {s2}"
```
2. Execute:
```bash
python repro_identity_assessment_stall.py
```
## Expected vs Actual
**Expected:** After throttling (`remainingPoints < min_remaining_points`), stream state is reset so a later tick can re-run domains discovery and resume ingestion.
**Actual:** `worklist`, `next`, and `last_remaining` persist unchanged; each subsequent tick re-enters the same throttled branch and emits no events forever.
Observed output:
```text
Traceback (most recent call last):
File "repro_identity_assessment_stall.py", line 30, in
assert 'worklist' not in s2, f"BUG: stale worklist persists and stream stalls: {s2}"
AssertionError: BUG: stale worklist persists and stream stalls: {'worklist': ['d1', 'd2'], 'next': 0, 'last_remaining': 50, 'min_remaining_points': 100, 'events': [], 'want_more': False}
```
## Failing Test
```python
state = {
'worklist': ['d1', 'd2'],
'next': 0,
'last_remaining': 50,
'min_remaining_points': 100,
}
def step(s):
s = dict(s)
if not ('worklist' in s and len(s['worklist']) > 0):
s.update({'worklist': ['new-domain'], 'next': 0, 'last_remaining': 500000})
if ('worklist' not in s) or len(s['worklist']) == 0:
return s
if int(s.get('next', 0)) >= len(s['worklist']):
out = dict(s); out.update({'events': [], 'want_more': False})
out.pop('worklist', None); out.pop('next', None); out.pop('last_remaining', None)
return out
if ('last_remaining' in s) and int(s['last_remaining']) < int(s['min_remaining_points']):
out = dict(s); out.update({'events': [], 'want_more': False})
return out
return dict(s, events=[{'ok': True}], next=int(s['next']) + 1, want_more=int(s['next']) + 1 < len(s['worklist']))
s1 = step(state)
s2 = step(s1)
assert 'worklist' not in s2, f"BUG: stale worklist persists and stream stalls: {s2}"
```
## Evidence
- `packages/crowdstrike/data_stream/identity_protection_assessment/agent/stream/cel.yml.hbs:43-46` skips the domains request whenever `state.worklist` exists.
- `packages/crowdstrike/data_stream/identity_protection_assessment/agent/stream/cel.yml.hbs:135-141` handles low remaining points by setting `events`/`want_more` but does **not** drop `worklist`, `next`, or `last_remaining`.
- `packages/crowdstrike/data_stream/identity_protection_assessment/agent/stream/cel.yml.hbs:126-141` then repeats the same branch on the next run, creating a stable no-progress state.
> [!NOTE]
>
> 🔒 Integrity filter blocked 1 item
>
> The following item were blocked because they don't meet the GitHub integrity level.
>
> - [#17846](https://github.com/elastic/integrations/issues/17846) `search_issues`: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
>
> To allow these resources, lower `min-integrity` in your GitHub frontmatter:
>
> ```yaml
> tools:
> github:
> min-integrity: approved # merged | approved | unapproved | none
> ```
>
>
---
[What is this?](https://ela.st/github-ai-tools) | [From workflow: Bug Hunter](https://github.com/elastic/integrations/actions/runs/25915826626)
Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.
> - [x] expires on May 22, 2026, 11:49 AM UTC
Contributor guide
Assessment
This issue has not been assessed yet.