Skip to content

out_cloudwatch_logs: Ensure escaping backslashes on cloudwatch API requests' body#11933

Open
cosmo0920 wants to merge 5 commits into
masterfrom
cosmo0920-ensure-escape-backslashes-on-cloudwatch
Open

out_cloudwatch_logs: Ensure escaping backslashes on cloudwatch API requests' body#11933
cosmo0920 wants to merge 5 commits into
masterfrom
cosmo0920-ensure-escape-backslashes-on-cloudwatch

Conversation

@cosmo0920

@cosmo0920 cosmo0920 commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

In the current implementation of cloudwatch logs does not ensure escaping special characters to create log stream.
This causes request failures for creating streams.
This PR fixes this issue.

Closes #11931.


Enter [N/A] in the box, if an item is not applicable to your change.

Testing
Before we can approve your change; please submit the following in a comment:

  • Example configuration file for the change
  • Debug log output from testing the change
  • Attached Valgrind output that shows no leaks or memory corruption was found

If this is a change to packaging of containers or native binaries then please confirm it works for all targets.

  • Run local packaging test showing all targets (including any new ones) build.
  • Set ok-package-test label to test for all targets (requires maintainer to do).

Documentation

  • Documentation required for this feature

Backporting

  • Backport to latest stable release.

Fluent Bit is licensed under Apache 2.0, by submitting this pull request I understand that this code will be released under the terms of that license.

Summary by CodeRabbit

  • Bug Fixes

    • Stream and group names are now correctly JSON-escaped in create-stream and put-events requests to prevent malformed payloads.
  • Refactor

    • Centralized payload construction and escaping, with improved buffer sizing and cleanup to reduce memory issues.
  • Tests

    • Added runtime tests validating JSON escaping for stream names in create-stream and put-events flows.
  • Chores

    • Windows build matrix updated to select runners per architecture and conditionally install Arm64 tooling.

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b6a38e20-5af5-48cd-b476-0ae974f3f99e

📥 Commits

Reviewing files that changed from the base of the PR and between 7308334 and 265b710.

📒 Files selected for processing (1)
  • .github/workflows/call-build-windows.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/call-build-windows.yaml

📝 Walkthrough

Walkthrough

Centralizes JSON escaping for CloudWatch log group and stream names, adds builders for CreateLogStream and PutLogEvents payloads that use escaped names (with sizing fixes), adds runtime tests validating escaping, and updates Windows CI matrix to choose OS per matrix entry and add an ARM64 runner and conditional WiX install.

Changes

CreateLogStream and PutLogEvents JSON escaping

Layer / File(s) Summary
API declaration and CreateLogStream body builder
plugins/out_cloudwatch_logs/cloudwatch_api.h, plugins/out_cloudwatch_logs/cloudwatch_api.c
Declare and implement flb_cloudwatch_create_log_stream_body which constructs the CreateLogStream JSON request using escaped logGroupName and logStreamName and returns an flb_sds_t or NULL.
PutLogEvents initializer and sizing
plugins/out_cloudwatch_logs/cloudwatch_api.c
Add escape_stream_names, replace inline PutLogEvents header construction with flb_cloudwatch_init_put_payload (now public), update reset_flush_buf to size buffers using escaped-name lengths, and update callers to use the new initializer.
Runtime tests for escaping
tests/runtime/out_cloudwatch.c
Add two tests: one asserting exact JSON output from flb_cloudwatch_create_log_stream_body for a name containing \x2d, and another validating the escaped logStreamName prefix and buffer sizing for flb_cloudwatch_init_put_payload; register tests in TEST_LIST.

Windows CI matrix update

Layer / File(s) Summary
Workflow matrix and runner selection
.github/workflows/call-build-windows.yaml
Make call-build-windows-package.runs-on driven by matrix.config.os, add os values for each matrix config (32/64 → windows-latest, ARM64 → windows-11-arm), and add a conditional WiX Toolset install step for the ARM64 config.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant send_log_events
  participant flb_cloudwatch_init_put_payload
  participant escape_stream_names
  participant HTTP_Buffer
  Client->>send_log_events: trigger flush
  send_log_events->>flb_cloudwatch_init_put_payload: init PutLogEvents header
  flb_cloudwatch_init_put_payload->>escape_stream_names: request escaped group/name
  escape_stream_names->>flb_cloudwatch_init_put_payload: return escaped strings
  flb_cloudwatch_init_put_payload->>HTTP_Buffer: write header with escaped names
  flb_cloudwatch_init_put_payload->>send_log_events: return offset/size
  send_log_events->>HTTP_Buffer: append events and send HTTP request
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • fluent/fluent-bit#10585: Modifies PutLogEvents JSON payload construction in cloudwatch_api.c, overlapping serialization logic with this PR.
  • fluent/fluent-bit#10931: Updates Windows workflow to add/use ARM64 runner and matrix-driven runs-on, similar CI changes.

Suggested reviewers

  • niedbalski
  • patrick-stephens
  • celalettin1286

Poem

🐰 I nudged the strings and doubled each slash,
JSON now safe from every backslash clash.
Streams built and events sent all night,
Escaped and tidy, every payload's right.
🥕

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Out of Scope Changes check ❓ Inconclusive The cloudwatch_api.c/h changes directly address the linked issue, but the .github/workflows/call-build-windows.yaml modifications (adding Arm64 support and WiX toolset configuration) appear unrelated to JSON escaping requirements. Clarify whether the Windows build workflow changes are intentional and unrelated, or if they should be separated into a distinct PR to maintain clear scope.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly summarizes the main change: implementing JSON escaping for backslashes in CloudWatch API request bodies.
Linked Issues check ✅ Passed The PR implements JSON escaping for log stream/group names in cloudwatch_api.c, adds helper functions for payload construction, includes runtime tests validating JSON escaping, and addresses all coding requirements from issue #11931.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cosmo0920-ensure-escape-backslashes-on-cloudwatch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c5b8657cdb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/out_cloudwatch_logs/cloudwatch_api.c Outdated
Signed-off-by: Hiroshi Hatake <hiroshi@chronosphere.io>
Signed-off-by: Hiroshi Hatake <hiroshi@chronosphere.io>
Signed-off-by: Hiroshi Hatake <hiroshi@chronosphere.io>
Signed-off-by: Hiroshi Hatake <hiroshi@chronosphere.io>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
plugins/out_cloudwatch_logs/cloudwatch_api.c (1)

1852-1852: ⚠️ Potential issue | 🟠 Major

Escaping is missing for logGroupName in CreateLogGroup / PutRetentionPolicy JSON bodies

  • create_log_group() builds {"logGroupName":"%s"} using raw stream->group (e.g., cloudwatch_api.c:1852) without applying escape_stream_names().
  • set_log_group_retention() builds {"logGroupName":"%s","retentionInDays":%d} using raw stream->group (e.g., cloudwatch_api.c:1786) with the same lack of escaping.
  • escape_stream_names() is used for PutLogEvents (flb_cloudwatch_init_put_payload), so these requests should apply the same escaping when interpolating stream->group into JSON to avoid invalid payloads when names contain JSON-sensitive characters.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugins/out_cloudwatch_logs/cloudwatch_api.c` at line 1852,
create_log_group() and set_log_group_retention() interpolate stream->group
directly into JSON bodies which can produce invalid payloads; use the existing
escape_stream_names() (the same escaping applied by
flb_cloudwatch_init_put_payload for PutLogEvents) before formatting the JSON.
Modify create_log_group() and set_log_group_retention() to call
escape_stream_names(&escaped, stream->group) (or equivalent existing API), use
the escaped value when building the body (instead of stream->group), and free
the escaped buffer after use to avoid leaks.
🧹 Nitpick comments (2)
.github/workflows/call-build-windows.yaml (2)

210-214: ⚡ Quick win

Document the WiX pre-installation assumption.

This step installs WiX only for ARM64, implying that WiX is pre-installed on windows-latest but not on windows-11-arm. This assumption is fragile and could break silently if GitHub runner images change.

📝 Suggested improvement

Add a comment documenting the assumption:

+      # WiX is pre-installed on windows-latest runners but not on windows-11-arm
+      # Install WiX explicitly for ARM64 builds to ensure MSI packaging works
       - name: Get WiX Toolset w/ chocolatey
         if: ${{ matrix.config.arch == 'amd64_arm64' }}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/call-build-windows.yaml around lines 210 - 214, Add an
explicit comment above the "Get WiX Toolset w/ chocolatey" job step (the step
using crazy-max/ghaction-chocolatey with args: install wixtoolset -y and guarded
by if: ${{ matrix.config.arch == 'amd64_arm64' }}) documenting the assumption
that the windows-latest runner already includes WiX while the windows-11-arm
runner does not; note that this is a fragile image-specific assumption and call
out that the conditional intentionally restricts installation to the ARM64
matrix case so future maintainers know why the install is skipped for other
runners.

210-214: ⚡ Quick win

Consider verifying WiX availability for all configurations.

Since MSI packages are created for all architectures (line 277: *-bit-*.msi), WiX must be available for all builds, not just ARM64. The current approach assumes WiX is pre-installed on windows-latest but provides no verification. If that assumption breaks, x86/x64 builds could fail with unclear errors.

🛡️ Suggested verification step

Add a verification step after WiX installation (for all configs or just ARM64) to ensure the tool is available:

      - name: Verify WiX Toolset availability
        run: |
          if (-not (Test-Path "$ENV:WIX\bin\candle.exe")) {
            throw "WiX Toolset not found. Expected at: $ENV:WIX\bin\candle.exe"
          }
          Write-Host "WiX Toolset found at: $ENV:WIX"
          & "$ENV:WIX\bin\candle.exe" -?
        shell: pwsh

Alternatively, install WiX explicitly for all configurations to remove the pre-installation dependency:

       - name: Get WiX Toolset w/ chocolatey
-        if: ${{ matrix.config.arch == 'amd64_arm64' }}
         uses: crazy-max/ghaction-chocolatey@dff3862348493b11fba2fbc49147b6d2dfe09b66 # v4.0.0
         with:
           args: install wixtoolset -y
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/call-build-windows.yaml around lines 210 - 214, The
workflow currently only installs WiX in the "Get WiX Toolset w/ chocolatey" step
for the amd64_arm64 matrix and assumes WiX exists for other Windows runners,
which can cause unclear failures when producing the '*-bit-*.msi' artifacts;
either install WiX for all Windows configs (remove the if: condition on the
crazy-max/ghaction-chocolatey step) or add a verification step after
installation that uses the WIX environment variable to check
"$ENV:WIX\bin\candle.exe" exists and exercises it (e.g., run candle.exe -?) so
the build fails fast with a clear error if WiX is missing.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@plugins/out_cloudwatch_logs/cloudwatch_api.c`:
- Line 1852: create_log_group() and set_log_group_retention() interpolate
stream->group directly into JSON bodies which can produce invalid payloads; use
the existing escape_stream_names() (the same escaping applied by
flb_cloudwatch_init_put_payload for PutLogEvents) before formatting the JSON.
Modify create_log_group() and set_log_group_retention() to call
escape_stream_names(&escaped, stream->group) (or equivalent existing API), use
the escaped value when building the body (instead of stream->group), and free
the escaped buffer after use to avoid leaks.

---

Nitpick comments:
In @.github/workflows/call-build-windows.yaml:
- Around line 210-214: Add an explicit comment above the "Get WiX Toolset w/
chocolatey" job step (the step using crazy-max/ghaction-chocolatey with args:
install wixtoolset -y and guarded by if: ${{ matrix.config.arch == 'amd64_arm64'
}}) documenting the assumption that the windows-latest runner already includes
WiX while the windows-11-arm runner does not; note that this is a fragile
image-specific assumption and call out that the conditional intentionally
restricts installation to the ARM64 matrix case so future maintainers know why
the install is skipped for other runners.
- Around line 210-214: The workflow currently only installs WiX in the "Get WiX
Toolset w/ chocolatey" step for the amd64_arm64 matrix and assumes WiX exists
for other Windows runners, which can cause unclear failures when producing the
'*-bit-*.msi' artifacts; either install WiX for all Windows configs (remove the
if: condition on the crazy-max/ghaction-chocolatey step) or add a verification
step after installation that uses the WIX environment variable to check
"$ENV:WIX\bin\candle.exe" exists and exercises it (e.g., run candle.exe -?) so
the build fails fast with a clear error if WiX is missing.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 354e4ece-c52e-4690-bdbf-7181610c3886

📥 Commits

Reviewing files that changed from the base of the PR and between 1baae41 and 7308334.

📒 Files selected for processing (4)
  • .github/workflows/call-build-windows.yaml
  • plugins/out_cloudwatch_logs/cloudwatch_api.c
  • plugins/out_cloudwatch_logs/cloudwatch_api.h
  • tests/runtime/out_cloudwatch.c
🚧 Files skipped from review as they are similar to previous changes (2)
  • plugins/out_cloudwatch_logs/cloudwatch_api.h
  • tests/runtime/out_cloudwatch.c

Signed-off-by: Hiroshi Hatake <hiroshi@chronosphere.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Journal logs containing backslashes fail to get written to CloudWatch Logs

1 participant