Skip to content

Crowdstrike: use inclusive >= cursor boundary for host data stream - #20524

Merged
chemamartinez merged 3 commits into
elastic:mainfrom
chemamartinez:crowdstrike-host-fix-cursor-boundary
Aug 5, 2026
Merged

Crowdstrike: use inclusive >= cursor boundary for host data stream#20524
chemamartinez merged 3 commits into
elastic:mainfrom
chemamartinez:crowdstrike-host-fix-cursor-boundary

Conversation

@chemamartinez

Copy link
Copy Markdown
Contributor

Proposed commit message

crowdstrike/data_stream/host: use inclusive >= cursor boundary in CEL program

Strict > on modified_timestamp permanently skips records that share a
boundary timestamp when a page or error boundary falls mid-group.
Switch to >= in both the GovCloud and commercial-CID branches so
same-timestamp records are always re-queried on the next poll.

Re-fetched boundary records are absorbed without creating duplicates:
the host ingest pipeline runs a fingerprint processor that includes
modified_timestamp, so events that were already ingested are dropped.

Follows up on https://github.com/elastic/integrations/pull/20190,
applying the same fix to the host data stream.

Checklist

  • I have reviewed tips for building integrations and this pull request is aligned with them.
  • I have verified that all data streams collect metrics or logs.
  • I have added an entry to my package's changelog.yml file.
  • I have verified that Kibana version constraints are current according to guidelines.
  • I have verified that any added dashboard complies with Kibana's Dashboard good practices

Related issues

@chemamartinez chemamartinez self-assigned this Aug 4, 2026
@chemamartinez chemamartinez added Integration:crowdstrike CrowdStrike bugfix Pull request that fixes a bug issue Team:Security-Service Integrations Security Service Integrations team [elastic/security-service-integrations] labels Aug 4, 2026
@chemamartinez
chemamartinez marked this pull request as ready for review August 4, 2026 15:58
@chemamartinez
chemamartinez requested review from a team as code owners August 4, 2026 15:59
@infra-vault-gh-plugin-prod

Copy link
Copy Markdown

Pinging @elastic/security-service-integrations (Team:Security-Service Integrations)

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

✅ Elastic Docs Style Checker (Vale)

No issues found on modified lines!


The Vale linter checks documentation changes against the Elastic Docs style guide. To use Vale locally or report issues, refer to Elastic style guide for Vale.

// Inclusive lower bound: records sharing the boundary timestamp can span a page
// or error boundary, so ">=" avoids permanently skipping same-timestamp records.
// Re-fetched records are de-duplicated downstream by the fingerprint _id
?filter.optMap(f, "modified_timestamp:>=\"" + f + "\""),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Severity: 🟠 High confidence: medium path: packages/crowdstrike/data_stream/host/agent/stream/cel.yml.hbs:70

The inclusive >= boundary fixes timestamp skipping, but the GovCloud branch still permanently skips records at an error boundary because state.offset is never reset on the error paths; add "offset": 0 to both GovCloud error returns.

Details

This change makes the timestamp lower bound inclusive so same-timestamp records are not skipped across page/error boundaries. In the GovCloud branch that fix is incomplete, because pagination here is offset-based and state.offset survives the error paths.

state.with() merges keys, and neither GovCloud error return sets offset, so the previous value is preserved:

  • GET error (lines 93-108) returns {events, want_more: false, next: {}} - offset keeps whatever the previous execution left.
  • POST error (lines 140-155) is reached after the GET success block already advanced offset to int(state.offset) + body.resources.size() (line 87), so offset is left pointing past the records that were never published.

offset is only reset to 0 on the success path when want_more is false. On the next execution want_more is false, so the filter is rebuilt from state.cursor.last_timestamp (or, if the object-shaped error caused the agent to drop the cursor, from now - initial_interval) - a fresh, much narrower result set - while offset is still N. The API then skips the first N records of that new result set, and nothing ever comes back for them. A single transient 5xx on the entities POST during the first page therefore drops that entire page permanently.

The commercial branch does not have this problem: its GET error return sets next: {}, which clears next.page_token and restarts pagination cleanly. The GovCloud branch should reset its pagination state the same way.

Recommendation:

Reset offset to 0 in both GovCloud error returns so a failed execution restarts pagination from the top of the freshly filtered result set:

{
  "events": {
    "error": {
      "code": string(get_resp.StatusCode),
      "id": string(get_resp.Status),
      "message": "GET: " + (
        (size(get_resp.Body) != 0) ?
          string(get_resp.Body)
        :
          string(get_resp.Status) + " (" + string(get_resp.StatusCode) + ")"
      ),
    },
  },
  "offset": 0,
  "want_more": false,
  "next": {},
}

and likewise for the entities POST error return:

{
  "events": {
    "error": {
      "code": string(post_resp.StatusCode),
      "id": string(post_resp.Status),
      "message": "POST: " + (
        (size(post_resp.Body) != 0) ?
          string(post_resp.Body)
        :
          string(post_resp.Status) + " (" + string(post_resp.StatusCode) + ")"
      ),
    },
  },
  "offset": 0,
  "want_more": false,
  "next": {},
}

Regenerate _dev/test/policy/test-default.expected after the change.


🤖 AI-Generated Review | Vera Review Bot | 📚 Knowledge base: integration-skills

⚠️ Automated review — verify suggestions before applying.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This seems to be a valid concern.

@vera-review-bot

Copy link
Copy Markdown

Review summary

Issues found across the latest commits 4fa9876 — 1 high
  • 🟠 The inclusive >= boundary fixes timestamp skipping, but the GovCloud branch still permanently skips records at an error boundary because state.offset is never reset on the error paths (link) (Unresolved)

A new commit triggers another review — at most once every 15 minutes. I skip the PR while it's approved or has merge conflicts.

🤖 AI-Generated Review | Vera Review Bot | 📚 Knowledge base: integration-skills

⚠️ Automated review — verify suggestions before applying.

@mergify

mergify Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Tick the box to add this pull request to the merge queue (same as @mergifyio queue).

  • Queue this pull request

@elastic-vault-github-plugin-prod

Copy link
Copy Markdown
Contributor

✅ All changelog entries have the correct PR link.

@infra-vault-gh-plugin-prod

Copy link
Copy Markdown

💚 Build Succeeded

History

cc @chemamartinez

@chemamartinez
chemamartinez merged commit f5b3f90 into elastic:main Aug 5, 2026
9 checks passed
@chemamartinez
chemamartinez deleted the crowdstrike-host-fix-cursor-boundary branch August 5, 2026 10:48
@elastic-vault-github-plugin-prod

Copy link
Copy Markdown
Contributor

Package crowdstrike - 4.5.1 containing this change is available at https://epr.elastic.co/package/crowdstrike/4.5.1/

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

Labels

bugfix Pull request that fixes a bug issue Integration:crowdstrike CrowdStrike Team:Security-Service Integrations Security Service Integrations team [elastic/security-service-integrations]

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants