Skip to content

ti_threatconnect: fix precision loss of indicator IDs above 2^53 - #19110

Merged
kcreddy merged 4 commits into
elastic:mainfrom
kcreddy:ti_threatconnect-precision-fix
May 22, 2026
Merged

kcreddy merged 4 commits into
elastic:mainfrom
kcreddy:ti_threatconnect-precision-fix

Conversation

@kcreddy

@kcreddy kcreddy commented May 21, 2026 •

Copy link
Copy Markdown
Contributor

Proposed commit message

ti_threatconnect: fix precision loss of indicator IDs above 2^53

The ThreatConnect API returns indicator IDs as JSON numbers. When
these exceed the IEEE 754 safe integer limit (2^53), the CEL
program's decode_json() rounds them through float64, causing
distinct IDs like 9007199254918487, 9007199254918488, and
9007199254918489 to all collapse to 9007199254918488.

Replace decode_json() with decode_json_string_numbers() so that
all JSON numbers are preserved as their literal string form. The
ingest pipeline already uses convert processors with explicit type
coercions for numeric fields, so string-valued numbers are handled
correctly downstream.

Add a script test that verifies indicator IDs above 2^53 are
preserved correctly. The test mock returns two Address indicators
whose IDs both round to the same float64 value and asserts that
both distinct values appear in threat_connect.indicator.id after
ingestion.

The minimum stack version is raised to 8.19.0/9.1.0, which is
the first version shipping a mito release that includes the
decode_json_string_numbers function.

Fixes elastic/integrations#19109

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

How to test this PR locally

Added script test (with large numbers) passes.

--- Test results for package: ti_threatconnect - START ---
╭──────────────────┬─────────────┬───────────┬────────────────────┬────────┬─────────────────╮
│ PACKAGE          │ DATA STREAM │ TEST TYPE │ TEST NAME          │ RESULT │    TIME ELAPSED │
├──────────────────┼─────────────┼───────────┼────────────────────┼────────┼─────────────────┤
│ ti_threatconnect │ indicator   │ script    │ env                │ PASS   │      46.96475ms │
│ ti_threatconnect │ indicator   │ script    │ large_id_precision │ PASS   │ 1m26.988814666s │
╰──────────────────┴─────────────┴───────────┴────────────────────┴────────┴─────────────────╯
--- Test results for package: ti_threatconnect - END   ---
Done

Related issues

Screenshots

Before (id is rounded)
Screenshot 2026-05-21 at 2 32 20 PM

After (id is precise)
Screenshot 2026-05-21 at 2 40 02 PM

kcreddy added 3 commits May 21, 2026 14:44
The ThreatConnect API returns indicator IDs as JSON numbers. When
these exceed the IEEE 754 safe integer limit (2^53), the CEL
program's decode_json() rounds them through float64, causing
distinct IDs like 9007199254918487, 9007199254918488, and
9007199254918489 to all collapse to 9007199254918488.

Replace decode_json() with decode_json_string_numbers() so that
all JSON numbers are preserved as their literal string form. The
ingest pipeline already uses convert processors with explicit type
coercions for numeric fields, so string-valued numbers are handled
correctly downstream.

The minimum stack version is raised to 8.19.0/9.1.0, which is
the first version shipping a mito release that includes the
decode_json_string_numbers function.

Fixes elastic#19109
@github-actions

github-actions Bot commented May 21, 2026 •

Copy link
Copy Markdown
Contributor

✅ Vale Linting Results

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.

@kcreddy kcreddy self-assigned this May 21, 2026
@kcreddy kcreddy added bugfix Pull request that fixes a bug issue Team:Security-Service Integrations Security Service Integrations team [elastic/security-service-integrations] Integration:ti_threatconnect ThreatConnect labels May 21, 2026
@kcreddy
kcreddy marked this pull request as ready for review May 21, 2026 09:50
@kcreddy
kcreddy requested review from a team as code owners May 21, 2026 09:50
@infra-vault-gh-plugin-prod

Copy link
Copy Markdown

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

@elastic-vault-github-plugin-prod

Copy link
Copy Markdown
Contributor

🚀 Benchmarks report

To see the full report comment with /test benchmark fullreport

}
}))).do_request().as(resp, resp.StatusCode == 200 ?
bytes(resp.Body).decode_json().as(body, {
bytes(resp.Body).decode_json_string_numbers().as(body, {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
bytes(resp.Body).decode_json_string_numbers().as(body, {
resp.Body.decode_json_string_numbers().as(body, {

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.

Updated in 74e813f

},
{
"id": 736759,
"id": 9007199254918489,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think we might need a script test to ensure that this is being handled correctly; as it is, we don't know whether we're getting a numeric truncation.

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.

Done in 74e813f

Add a script test that verifies indicator IDs above 2^53 are
preserved without float64 precision loss. The test mock returns
two Address indicators with IDs 9007199254918487 and
9007199254918489 (both round to 9007199254918488 under IEEE 754
double-precision) and asserts that both distinct values appear in
threat_connect.indicator.id after ingestion.

Also remove the unnecessary bytes() wrapper from the
decode_json_string_numbers call per review feedback.
@elasticmachine

Copy link
Copy Markdown

💚 Build Succeeded

History

cc @kcreddy

@kcreddy
kcreddy requested a review from efd6 May 21, 2026 10:43
@andrewkroh andrewkroh added the documentation Improvements or additions to documentation. Applied to PRs that modify *.md files. label May 21, 2026

@efd6 efd6 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM (float64 collision confirmation here)

@kcreddy
kcreddy merged commit 32d1f41 into elastic:main May 22, 2026
12 checks passed
@elastic-vault-github-plugin-prod

Copy link
Copy Markdown
Contributor

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

tejasc-metron pushed a commit to metron-labs/Doppel-Elastic-Security-SIEM that referenced this pull request May 25, 2026
…stic#19110)

The ThreatConnect API returns indicator IDs as JSON numbers. When
these exceed the IEEE 754 safe integer limit (2^53), the CEL
program's decode_json() rounds them through float64, causing
distinct IDs like 9007199254918487, 9007199254918488, and
9007199254918489 to all collapse to 9007199254918488.

Replace decode_json() with decode_json_string_numbers() so that
all JSON numbers are preserved as their literal string form. The
ingest pipeline already uses convert processors with explicit type
coercions for numeric fields, so string-valued numbers are handled
correctly downstream.

Add a script test that verifies indicator IDs above 2^53 are
preserved correctly. The test mock returns two Address indicators
whose IDs both round to the same float64 value and asserts that
both distinct values appear in threat_connect.indicator.id after
ingestion.

The minimum stack version is raised to 8.19.0/9.1.0, which is
the first version shipping a mito release that includes the
decode_json_string_numbers function.

Fixes elastic#19109
herrBez pushed a commit to herrBez/integrations that referenced this pull request Jun 1, 2026
…stic#19110)

The ThreatConnect API returns indicator IDs as JSON numbers. When
these exceed the IEEE 754 safe integer limit (2^53), the CEL
program's decode_json() rounds them through float64, causing
distinct IDs like 9007199254918487, 9007199254918488, and
9007199254918489 to all collapse to 9007199254918488.

Replace decode_json() with decode_json_string_numbers() so that
all JSON numbers are preserved as their literal string form. The
ingest pipeline already uses convert processors with explicit type
coercions for numeric fields, so string-valued numbers are handled
correctly downstream.

Add a script test that verifies indicator IDs above 2^53 are
preserved correctly. The test mock returns two Address indicators
whose IDs both round to the same float64 value and asserts that
both distinct values appear in threat_connect.indicator.id after
ingestion.

The minimum stack version is raised to 8.19.0/9.1.0, which is
the first version shipping a mito release that includes the
decode_json_string_numbers function.

Fixes elastic#19109
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 documentation Improvements or additions to documentation. Applied to PRs that modify *.md files. Integration:ti_threatconnect ThreatConnect 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.

ti_threatconnect: indicator IDs above 2^53 lose precision due to JSON float64 decoding

4 participants