Skip to content

[windows] Fix PowerShell 4103 ContextInfo parsing for indented multi-line values - #20693

Merged
marc-gr merged 4 commits into
elastic:mainfrom
nfritts:fix/windows-4103-contextinfo-painless
Sep 1, 2026
Merged

[windows] Fix PowerShell 4103 ContextInfo parsing for indented multi-line values#20693
marc-gr merged 4 commits into
elastic:mainfrom
nfritts:fix/windows-4103-contextinfo-painless

Conversation

@nfritts

@nfritts nfritts commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

The logs-windows.powershell_operational pipeline fails on the PowerShell events with the ID
4103. Elasticsearch writes this message to error.message:

field [winlog.event_data.ContextInfo] does not contain value_split [[:=]]

The document goes to the data stream, but the pipeline does not enrich it.

Why the kv processor fails

winlog.event_data.ContextInfo is a block of indented <Key> = <Value> lines. One of the keys
is Host Application. Its value is the full command line of the PowerShell host process. If a
user starts PowerShell with powershell.exe -Command <script>, the full script goes into that
value. The script keeps its line breaks and its indents.

PR #16013 changed field_split from \n to \n(?!\n)\s+ for this reason. That change is not
complete. The pattern keeps a multi-line value together only if the subsequent lines start at
column 0, which is the format of the test data in PR #16013. But the lines of an embedded script
usually have an indent. Thus the kv processor makes a new key from each of these lines. If such
a line contains no : character and no = character, the processor fails.

The kv processor is also the first processor in the pipeline, and it has no ignore_failure
parameter. Therefore a failure stops the full pipeline, and all subsequent processors do not run.
This includes the logs-windows.powershell_operational@custom pipeline that Fleet adds. A user
reports that a custom drop processor does not run because of this failure.

What this PR does

This PR replaces the kv processor with a script processor. The same package already uses this
method for the events 4xx and 600 in
data_stream/forwarded/elasticsearch/ingest_pipeline/powershell.yml.

The script examines each line of ContextInfo:

  • If the line agrees with the key pattern, the script starts a new key.
  • If the line does not agree, the script adds the line to the value of the last key.

The key pattern is ^\s{8,}([A-Za-z][A-Za-z0-9 _.\-]*?)\s*[:=](.*)$. A key must have at least
eight leading spaces, and a key must start with a letter. Therefore the script does not make a
key from a line such as foreach ($i in $items) {, 'alpha',, Server=localhost, or an
indented assignment such as int x = 1;.

Parse failures append to error.message and do not stop later processors, including the
@custom pipeline that Fleet adds.

The change keeps the behavior of the kv processor:

  • The keys keep their spaces. A subsequent processor removes the spaces.
  • The separator can be = or :. Localized events in the existing tests already use :.
  • The script removes the space characters from the start and the end of each value.

There is one difference: the script splits on /\r?\n/ and thus also accepts CRLF line breaks.
The kv processor had trim_value: " \n\t", which does not contain \r, and thus kept a
carriage return at the end of each value on CRLF input. No test event uses CRLF, so no expected
file changes.

The script appends a line break with (char)10, because a Painless string literal cannot contain
"\n". This agrees with the other scripts in the repository: the entropy script in this same file
uses int lf = 10; and aws_securityhub uses String.valueOf((char)10).

The same change is made in the two identical copies of this pipeline:

  • data_stream/powershell_operational/elasticsearch/ingest_pipeline/default.yml
  • data_stream/forwarded/elasticsearch/ingest_pipeline/powershell_operational.yml

The new 4103 fixture is in both powershell_operational and forwarded pipeline tests.

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

Author's Checklist

  • The new test event is not user data. A Windows test VM made this event, with a synthetic script.
  • The full script stays in process.command_line (23 lines).
  • No line of the script becomes a field.
  • The 10 existing test events give the same result as before this change.

How to test this PR locally

elastic-package stack up -d
cd packages/windows
elastic-package test pipeline -v --data-streams powershell_operational
elastic-package test pipeline -v --data-streams forwarded

Alternatively, do these steps to see the problem and the correction:

  1. Get a PowerShell Operational event with the ID 4103. The Host Application value must contain
    a script with more than one line. The script must contain a line that has an indent and no :
    or = character. The 11th event in test-events.json is such an event.
  2. Send the event to POST _ingest/pipeline/logs-windows.powershell_operational-3.9.3/_simulate.
    The result contains error.message.
  3. Do the same test with the pipeline from this PR (package 3.9.4). The result contains no
    error.message, and process.command_line contains the full script.

Test results

Run against a live stack with elastic-package v0.126.0:

  • powershell_operational: PASS, and the ingest pipeline warnings test also passes.
  • forwarded: 200 PASS, 0 FAIL.
  • The expected output of the 10 existing events is identical to the output before this change.
  • The new test event gives process.command_line with all 23 lines of the script, no leaked
    fields, and no error.message.

Related issues

…line values

ContextInfo is a block of indented "<Key> = <Value>" lines. The value of
Host Application is the command line of the PowerShell host process. If a
user starts PowerShell with -Command <script>, the full script goes into
that value, and the script keeps its line breaks and its indents.

The kv processor made a new key from each indented line. If such a line
contained no ":" and no "=", the processor failed. Because the kv was the
first processor and had no ignore_failure, the failure stopped the full
pipeline. All subsequent processors did not run, which included the
@Custom pipeline that Fleet adds.

A script processor now parses ContextInfo. The script starts a new key
only when a line agrees with the key pattern. The script adds all other
lines to the value of the last key. The parameter ignore_failure is set,
thus a parse problem cannot stop the subsequent processors again.

The behavior of the kv processor stays the same for the existing events:
the keys keep their spaces, the separator can be "=" or ":", and the
script removes the spaces from the start and the end of each value. The
script also accepts \r\n line breaks, which the kv processor did not.

The new test event comes from a Windows test VM, not from a user.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@nfritts
nfritts force-pushed the fix/windows-4103-contextinfo-painless branch from a6f7d4a to 97ebb45 Compare August 12, 2026 21:13
@github-actions

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.

@marc-gr marc-gr self-assigned this Aug 24, 2026
…ntextinfo-painless

Bump the windows package to 3.9.3 so the PowerShell 4103 changelog entry sits on top of versions already released on main.
@elastic-vault-github-plugin-prod

elastic-vault-github-plugin-prod Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

🚀 Benchmarks report

Package windows 👍(6) 💚(0) 💔(4)

Expand to view
Data stream Previous EPS New EPS Diff (%) Result
powershell_operational 2314.81 1519.76 -795.05 (-34.35%) 💔
applocker_exe_and_dll 4424.78 3389.83 -1034.95 (-23.39%) 💔
applocker_packaged_app_execution 10101.01 3344.48 -6756.53 (-66.89%) 💔
forwarded 1223.99 865.05 -358.94 (-29.33%) 💔

To see the full report comment with /test benchmark fullreport

…peline

Recognize ContextInfo keys only at eight-or-more spaces so indented script
assignments are not treated as fields, record parse errors without aborting
the pipeline, and add the multiline 4103 fixture to forwarded tests.
@marc-gr marc-gr added bugfix Pull request that fixes a bug issue Integration:windows Windows Team:Security-Service Integrations Security Service Integrations team [elastic/security-service-integrations] labels Sep 1, 2026
@marc-gr
marc-gr requested a review from a team September 1, 2026 08:03
@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 @marc-gr

@marc-gr
marc-gr marked this pull request as ready for review September 1, 2026 08:24
@marc-gr
marc-gr requested a review from a team as a code owner September 1, 2026 08:24
@marc-gr
marc-gr requested review from belimawr and leehinman and a lite review from Copilot September 1, 2026 08:24
@infra-vault-gh-plugin-prod

Copy link
Copy Markdown

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

@marc-gr
marc-gr merged commit 7668c33 into elastic:main Sep 1, 2026
9 checks passed
@vera-review-bot

Copy link
Copy Markdown

@nfritts - 💤 This PR was approved before I picked it up, so I will leave it — automatic reviews are skipped on approved PRs. If you would still like a review, request one with a @vera-review-bot review comment (members and owners only).

Copilot AI 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.

🟡 Changes recommended

The new script parser’s documentation is currently inaccurate about “parse failures,” and the key regex is overly permissive in a way that can create false keys under plausible indented inputs.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR updates the Windows integration’s PowerShell Operational ingest pipelines to robustly parse Event ID 4103 winlog.event_data.ContextInfo when values contain indented multi-line scripts, preventing pipeline aborts and ensuring downstream enrichment (including Fleet @custom) still runs.

Changes:

  • Replace the kv processor used for 4103 ContextInfo parsing with a Painless script processor in both the powershell_operational and forwarded pipelines.
  • Add new 4103 fixtures and expected outputs to validate indented multi-line Host Application parsing in both pipeline test suites.
  • Bump package version to 3.9.4 and add a corresponding changelog entry.
File summaries
File Description
packages/windows/manifest.yml Bumps the Windows integration version to 3.9.4.
packages/windows/data_stream/powershell_operational/elasticsearch/ingest_pipeline/default.yml Replaces 4103 kv parsing with a script-based parser to handle indented multi-line values and avoid pipeline stoppage.
packages/windows/data_stream/forwarded/elasticsearch/ingest_pipeline/powershell_operational.yml Mirrors the same script-based 4103 parsing change for forwarded events.
packages/windows/data_stream/powershell_operational/_dev/test/pipeline/test-events.json Adds a 4103 test event with an indented multi-line script in Host Application.
packages/windows/data_stream/powershell_operational/_dev/test/pipeline/test-events.json-expected.json Adds expected output validating full command line preservation and no parsing failure.
packages/windows/data_stream/forwarded/_dev/test/pipeline/test-powershell-operational-events.json Adds the same 4103 test event for the forwarded pipeline tests.
packages/windows/data_stream/forwarded/_dev/test/pipeline/test-powershell-operational-events.json-expected.json Adds expected output for forwarded pipeline parsing behavior.
packages/windows/changelog.yml Adds release notes for 3.9.4 describing the 4103 parsing fix.
Review details

Suppressed comments (2)

packages/windows/data_stream/powershell_operational/elasticsearch/ingest_pipeline/default.yml:19

  • The key regex allows zero whitespace before the separator ("\s*[:=]"), so it will also treat lines like "Server=localhost" as a new key if they appear with >=8 leading spaces. Windows ContextInfo keys in the test fixtures use a space before ':' or '=', so requiring at least one whitespace here reduces false positives while matching observed input.
        def keyPattern = /^\s{8,}([A-Za-z][A-Za-z0-9 _.\-]*?)\s*[:=](.*)$/;

packages/windows/data_stream/forwarded/elasticsearch/ingest_pipeline/powershell_operational.yml:19

  • The key regex allows zero whitespace before the separator ("\s*[:=]"), so it will also treat lines like "Server=localhost" as a new key if they appear with >=8 leading spaces. Windows ContextInfo keys in the test fixtures use a space before ':' or '=', so requiring at least one whitespace here reduces false positives while matching observed input.
        def keyPattern = /^\s{8,}([A-Za-z][A-Za-z0-9 _.\-]*?)\s*[:=](.*)$/;
  • Files reviewed: 8/8 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +13 to +14
Parse failures are recorded on error.message without stopping the rest of the pipeline,
including the @custom pipeline that Fleet adds.
Comment on lines +13 to +14
Parse failures are recorded on error.message without stopping the rest of the pipeline,
including the @custom pipeline that Fleet adds.
@elastic-vault-github-plugin-prod

Copy link
Copy Markdown
Contributor

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

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:windows Windows 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.

[windows] The kv processor fails on ContextInfo when Host Application contains an indented script

3 participants