Skip to content

Validate that every %{ in a grok processor is a grok token (SVR00011) - #1244

Open
ilyannn wants to merge 3 commits into
elastic:mainfrom
ilyannn:pipeline-grok-malformed-tokens
Open

Validate that every %{ in a grok processor is a grok token (SVR00011)#1244
ilyannn wants to merge 3 commits into
elastic:mainfrom
ilyannn:pipeline-grok-malformed-tokens

Conversation

@ilyannn

@ilyannn ilyannn commented Sep 7, 2026

Copy link
Copy Markdown

What does this PR do?

Adds semantic validation rule SVR00011: every %{ in a grok processor's patterns and pattern_definitions must start a grok token.

The token grammar is transcribed from GROK_PATTERN in org.elasticsearch.grok.Grok (including its [A-z0-9] pattern-name class, so nothing Elasticsearch accepts is rejected here). Grok processors inside foreach and inside processor-level and pipeline-level on_failure handlers are covered. The excerpt in the message runs from the %{ to the first } after it, so the author sees exactly the text grok saw.

file ".../ingest_pipeline/default.yml" is invalid: grok processor at line 55 has "%{WORD_tmp.outcome}" in patterns[4], which is not a grok token and is matched as literal text (SVR00011)

Following ValidateMinimumKibanaVersion, the rule is registered twice: as a warning for packages below 3.7.0 and as an error from 3.7.0. Existing packages see the finding in elastic-package lint output today without anything breaking; the six affected packages are already fixed or tracked (below).

Why is it important?

Grok does not report text that fails to parse as a %{...} token. It leaves it in the regular expression as-is, so the processor compiles, runs, and simply never captures what the author wrote. There is no exception and no missing-pattern message; in practice a catch-all pattern or ignore_failure: true sits nearby and absorbs the miss, and pipeline tests pass because their expected output was generated from the broken behaviour. The only way to find one is to look.

Six shipped packages in elastic/integrations have one today, five of them silently losing a field: elastic/integrations#21081. The shapes are an alternation inside a pattern name (%{USERNAME|EMAILADDRESS:...}), a character class where a name goes (%{[A-Fa-f0-9]{32}:...}), a missing closing brace (%{GREEDYDATA:x.error\]), a missing colon (%{WORD_tmp.outcome}) and a > for a } in a definition. Each of them is one keystroke from correct, which is why they slipped past review.

Run over all 485 packages in that repository, this rule reports exactly those six sites and nothing else.

What it looks like

elastic-package lint built against this branch, on pulse_connect_secure from elastic/integrations main (the missing colon).

As shipped today, format_version: 3.0.3 — a warning, exit 0:

Lint the package
2026/09/07 17:35:33 Warning: file "pulse_connect_secure/data_stream/log/elasticsearch/ingest_pipeline/default.yml" is invalid: grok processor at line 55 has "%{WORD_tmp.outcome}" in patterns[4], which is not a grok token and is matched as literal text (SVR00011)
2026/09/07 17:35:33 Warning: validation mode 'source' is in technical preview
Done

The same package on format_version: 3.7.0 — an error, exit 1. Lifting a 3.0-era package to 3.7 also trips the tag and on_failure rules, so the full list is 33 items; the last is this one:

Error: linting package failed: found 33 validation errors:
   1. file "pulse_connect_secure/manifest.yml": package with GA version (2.6.1) is using an unreleased version of the spec (3.7.0-next) (PSR00001)
   ...
  16. file "pulse_connect_secure/data_stream/log/elasticsearch/ingest_pipeline/default.yml" is invalid: grok processor at line 55 missing required tag (SVR00006)
   ...
  33. file "pulse_connect_secure/data_stream/log/elasticsearch/ingest_pipeline/default.yml" is invalid: grok processor at line 55 has "%{WORD_tmp.outcome}" in patterns[4], which is not a grok token and is matched as literal text (SVR00011)

Line 55 is the grok processor's own line in the YAML, patterns[4] picks the pattern within it, and the quoted text is the span grok saw, cut at the first }.

Checklist

  • I have added test packages to test/packages that prove my change is effective. (bad_pipeline_grok, asserted in TestValidateIngestPipelines; plus unit tests for each of the real-world shapes, foreach and on_failure nesting, and the token grammar's edge cases.)
  • I have added an entry in spec/changelog.yml.
  • Documented in docs/validations.md.

Related issues

Note: drafted with 🤖 Cursor/Fable 5.1, under my supervision.

Grok does not report text that fails to parse as a %{...} token. It
leaves it in the regular expression as-is, so the processor compiles
and runs and the capture the author wrote never exists. Because a
catch-all pattern or ignore_failure is usually nearby, nothing
downstream reports it either, and pipeline tests pass because their
expectations are generated from the broken output.

Six shipped packages in elastic/integrations have one: an alternation
inside a pattern name, a character class where a name goes, a missing
closing brace, a missing colon, a > for a }. Five of them silently lose
a field (elastic/integrations#21081). Run over all 485 packages, this
rule reports exactly those six and nothing else.

The token grammar is transcribed from GROK_PATTERN in Grok.java,
including its [A-z0-9] pattern-name class. Grok inside foreach and in
on_failure handlers is covered. Reported as a warning below 3.7.0 and
as an error from 3.7.0, following ValidateMinimumKibanaVersion.
@ilyannn
ilyannn requested a review from a team as a code owner September 7, 2026 15:18
{fn: semantic.ValidateStaticHandlebarsFiles, types: []string{"integration", "input"}},
{fn: semantic.ValidateKibanaTagDuplicates},
{fn: semantic.ValidatePipelineOnFailure, types: []string{"integration"}, since: semver.MustParse("3.6.0")},
{fn: warnOn(semantic.ValidatePipelineGrok), types: []string{"integration"}, until: semver.MustParse("3.7.0")},

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.

pinning this to 3.7 will just run for packages on this version; do we want to validate packages across all spec versions for this? is there a reason to pin it to 3.7?

@ilyannn ilyannn Sep 9, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

It does run across all spec versions — this line pairs with the one above it. Below 3.7.0 the same function is registered through warnOn, so every package gets the finding in lint output today as a warning; from 3.7.0 it becomes an error. I copied the shape from ValidateMinimumKibanaVersion (warning until 3.0.0, error since).

The reason for not making it an error everywhere: six shipped packages in elastic/integrations trip it right now (elastic/integrations#21081), and an unconditional error would fail their lint the moment elastic-package picks up this release. Three have fix PRs open (#21082, #21083, #21084); the other three (hid_bravura_monitor, nats, stan) belong to other teams and are only reported so far.

That said, every one of the six is a real bug that loses data, so an error for all versions is defensible. If you'd rather have that, I'll drop the warnOn line and the since, and the changelog entry already says breaking-change. Your call.

Note: drafted with 🤖 Cursor/Fable 5.1, under my supervision.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

(I really don't know what we usually do when we add a rule)

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.

we usually have a file under the packages to exclude rules (eg https://github.com/elastic/integrations/blob/831ce67b4dffcb722156640267a9e235bf35ebb0/packages/aws/validation.yml)

So i was thinking that this is something we want to align which is currently broken, we should enable it regardless the version. From my perspective, the spec establishes what should happen; if the package is wrong it can use the validation file to exclude until is fixed. When we release breaking changes on elastic-package we usually fix the packages alongside the bump.

Also, related to the version target; we can add this to the next patch as we don't have a 3.7 horizon right now.

cc @mrodm

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.

Also, related to the version target; we can add this to the next patch as we don't have a 3.7 horizon right now.

Yes, I think this could be released adding a new version entry as 3.6.7-next.

So i was thinking that this is something we want to align which is currently broken, we should enable it regardless the version. From my perspective, the spec establishes what should happen; if the package is wrong it can use the validation file to exclude until is fixed. When we release breaking changes on elastic-package we usually fix the packages alongside the bump.

I guess this was done to avoid breaking changes, that it is good (warning before a spec version and failing starting in that spec).
How could this issue affect to the packages that are not fixed @ilyannn ? Are there GitHub issues or pull requests created to fix those packages?

Options that I could think of:

  • Keep the current until/since with the warnings
  • Keep the current until/since but setting as spec threshold 3.0.0:
    • old packages (<3.0.0) would not be affected
    • tested locally and the packages that are failing right now are stan and nats, that set spec 3.0.4
  • Keep the current until/since but setting as spec threshold 3.1.0:
    • old packages (<3.1.0) would not be affected, but most of the new packages will apply this validation rule
    • no packages would fail
    • lint in stan and nats would report warnings. Example:
      2026/09/11 10:26:06 Warning: file "/home/mariorodriguez/Coding/work/integrations-upstream-main/packages/nats/data_stream/log/elasticsearch/ingest_pipeline/default.yml" is invalid: grok processor at line 31 has "%{GREEDYDATA:nats.log.msg.error\\]" in patterns[7], which is not a grok token and is matched as literal text (SVR00011)
      
  • Apply everywhere this new validation.
    • stan and nats packages will fail because of lint step

WDYT @teresaromero @ilyannn ?

Comment thread docs/validations.md
| [SVR00007] | Kibana tag is duplicate |
| [SVR00008] | Pipeline failure handler must set event.kind |
| [SVR00009] | Pipeline failure handler must set error.message |
| [SVR00011] | Grok pattern contains text that is not a token |

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.

SVR00010 is missing from the docs #1135

@ilyannn ilyannn Sep 9, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Added in cd0ae71 — table row plus a section, based on the name description in manifest.spec.yml and the changelog entry for #1135 (shipped in 3.6.1).

Note: drafted with 🤖 Cursor/Fable 5.1, under my supervision.

@ilyannn
ilyannn requested a review from teresaromero September 9, 2026 23:49
@infra-vault-gh-plugin-prod

Copy link
Copy Markdown

💚 Build Succeeded

History

{fn: semantic.ValidateStaticHandlebarsFiles, types: []string{"integration", "input"}},
{fn: semantic.ValidateKibanaTagDuplicates},
{fn: semantic.ValidatePipelineOnFailure, types: []string{"integration"}, since: semver.MustParse("3.6.0")},
{fn: warnOn(semantic.ValidatePipelineGrok), types: []string{"integration"}, until: semver.MustParse("3.7.0")},

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.

Also, related to the version target; we can add this to the next patch as we don't have a 3.7 horizon right now.

Yes, I think this could be released adding a new version entry as 3.6.7-next.

So i was thinking that this is something we want to align which is currently broken, we should enable it regardless the version. From my perspective, the spec establishes what should happen; if the package is wrong it can use the validation file to exclude until is fixed. When we release breaking changes on elastic-package we usually fix the packages alongside the bump.

I guess this was done to avoid breaking changes, that it is good (warning before a spec version and failing starting in that spec).
How could this issue affect to the packages that are not fixed @ilyannn ? Are there GitHub issues or pull requests created to fix those packages?

Options that I could think of:

  • Keep the current until/since with the warnings
  • Keep the current until/since but setting as spec threshold 3.0.0:
    • old packages (<3.0.0) would not be affected
    • tested locally and the packages that are failing right now are stan and nats, that set spec 3.0.4
  • Keep the current until/since but setting as spec threshold 3.1.0:
    • old packages (<3.1.0) would not be affected, but most of the new packages will apply this validation rule
    • no packages would fail
    • lint in stan and nats would report warnings. Example:
      2026/09/11 10:26:06 Warning: file "/home/mariorodriguez/Coding/work/integrations-upstream-main/packages/nats/data_stream/log/elasticsearch/ingest_pipeline/default.yml" is invalid: grok processor at line 31 has "%{GREEDYDATA:nats.log.msg.error\\]" in patterns[7], which is not a grok token and is matched as literal text (SVR00011)
      
  • Apply everywhere this new validation.
    • stan and nats packages will fail because of lint step

WDYT @teresaromero @ilyannn ?

Comment on lines +130 to +131
fmt.Errorf("file %q is invalid: grok processor at line %d has %q in %s, which is not a grok token and is matched as literal text",
filename, proc.position.line, malformedTokenExcerpt(text[start:]), where),

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.

How is this line obtained ? I see discrepancies between what it is reported (line number) and the actual line in the ingest pipeline.

Testing this branch with the packages in integrations fails for nats package for instance.

The error reported in

 Error: linting package failed: found 1 validation error:
   1. file "/home/mariorodriguez/Coding/work/integrations-upstream-main/packages/nats/data_stream/log/elasticsearch/ingest_pipeline/default.yml" is invalid: grok processor at line 31 has "%{GREEDYDATA:nats.log.msg.error\\]" in patterns[7], which is not a grok token and is matched as literal text (SVR00011)

But at that line there is no such string:

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.

3 participants