Skip to content

πŸ›‘οΈ Sentinel: [Medium] Fix unhandled json.Marshal error in API handlers#117

Open
mattjoyce wants to merge 1 commit into
mainfrom
sentinel-fix-json-marshal-errors-3485135590841703401
Open

πŸ›‘οΈ Sentinel: [Medium] Fix unhandled json.Marshal error in API handlers#117
mattjoyce wants to merge 1 commit into
mainfrom
sentinel-fix-json-marshal-errors-3485135590841703401

Conversation

@mattjoyce
Copy link
Copy Markdown
Owner

@mattjoyce mattjoyce commented Jun 6, 2026

🚨 Severity: MEDIUM
πŸ’‘ Vulnerability: Unhandled json.Marshal errors in internal/api/handlers.go could lead to empty or invalid payloads being queued.
🎯 Impact: Workers could crash or behave unpredictably when processing malformed payloads, leading to potential denial of service or data corruption.
πŸ”§ Fix: Explicitly check the json.Marshal error, log it securely, and return http.StatusInternalServerError.
βœ… Verification: Ensure the test suite passes successfully.


PR created automatically by Jules for task 3485135590841703401 started by @mattjoyce

Summary by CodeRabbit

Release Notes

  • Bug Fixes
    • Fixed unhandled serialization errors in API handlers. The system now properly detects and reports data serialization failures with appropriate error responses, preventing silent failures that could result in invalid payloads being processed.

In `internal/api/handlers.go`, the returned error from `json.Marshal(event)` was being explicitly ignored (assigned to `_`). This was a security and reliability risk. If marshaling failed, an empty byte slice or `nil` could be added to the queue, which could cause panics or application instability downstream.

This commit updates the code to explicitly check for marshaling errors. If an error occurs, it is securely logged using `s.logger.Error`, and an `http.StatusInternalServerError` is returned to the client using `s.writeError`. This ensures the API fails securely without exposing internal data.

Co-authored-by: mattjoyce <278869+mattjoyce@users.noreply.github.com>
@google-labs-jules
Copy link
Copy Markdown
Contributor

πŸ‘‹ Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a πŸ‘€ emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Jun 6, 2026

Deploying with Β Cloudflare Workers Β Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
βœ… Deployment successful!
View logs
ductile 3c1e88d Commit Preview URL

Branch Preview URL
Jun 06 2026, 11:40 AM

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 6, 2026

Review Change Stack

πŸ“ Walkthrough

Walkthrough

This PR fixes unhandled json.Marshal errors in two API trigger handlers (handlePipelineTrigger and handlePluginTrigger). Both handlers now capture marshaling errors, log them, and return HTTP 500 instead of proceeding with invalid payloads. The fix is documented in a sentinel entry.

Changes

JSON Marshal Error Handling

Layer / File(s) Summary
Error handling in event marshaling
internal/api/handlers.go, .jules/sentinel.md
handlePipelineTrigger and handlePluginTrigger now capture json.Marshal errors when wrapping protocol.Event payloads, log the error, and return HTTP 500 on failure. The change is documented in the sentinel as guidance to always handle and log marshaling failures.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐰 A marshal that once went unheard,
Now caught and logged, no silent word,
With errors faced and 500 sent,
The handlers are resilient bent!

πŸš₯ Pre-merge checks | βœ… 5
βœ… Passed checks (5 passed)
Check name Status Explanation
Description Check βœ… Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check βœ… Passed The title includes an emoji and severity tag that add noise, but clearly describes the main fix: handling unhandled json.Marshal errors in API handlers, which matches the changeset.
Docstring Coverage βœ… Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check βœ… Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check βœ… Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
πŸ“ Generate docstrings
  • Create stacked PR
  • Commit on current branch
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sentinel-fix-json-marshal-errors-3485135590841703401

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.

@qodo-code-review
Copy link
Copy Markdown

Review Summary by Qodo

Fix unhandled json.Marshal errors in API handlers

🐞 Bug fix

Grey Divider

Walkthroughs

Description
β€’ Fix unhandled json.Marshal errors in two API handlers
β€’ Add explicit error checking and logging for marshaling failures
β€’ Return HTTP 500 on marshal errors instead of silently failing
β€’ Add security learning documentation to .jules/sentinel.md
Diagram
flowchart LR
  A["json.Marshal call"] -->|"error ignored with _"| B["Empty/invalid payload enqueued"]
  B -->|"downstream processing"| C["Worker crash or data corruption"]
  A -->|"error now checked"| D["Error logged securely"]
  D -->|"HTTP 500 returned"| E["Request fails safely"]

Loading

Grey Divider

File Changes

1. internal/api/handlers.go 🐞 Bug fix +14/-2

Add error handling for json.Marshal calls

β€’ Replace ignored json.Marshal error with explicit error variable in handlePipelineTrigger
 function
β€’ Add error check that logs the error and returns HTTP 500 status on marshal failure
β€’ Apply same fix to handlePluginTrigger function for consistency
β€’ Prevent empty or malformed payloads from being enqueued to the queue

internal/api/handlers.go


2. .jules/sentinel.md πŸ“ Documentation +4/-0

Add security learning documentation

β€’ Document the vulnerability of ignoring json.Marshal errors
β€’ Explain the risk of empty or malformed byte slices being enqueued
β€’ Provide prevention guidance to always check and handle marshal errors
β€’ Record security learning for future reference

.jules/sentinel.md


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review Bot commented Jun 6, 2026

Code Review by Qodo

🐞 Bugs (1) πŸ“˜ Rule violations (0)

Context used
βœ… Compliance rules (platform): 46 rules

Grey Divider


Remediation recommended

1. Marshal log missing context 🐞 Bug β—” Observability
Description
In handlePipelineTrigger and handlePluginTrigger, the new json.Marshal failure log records only the
error and omits pipeline/plugin/command identifiers that are present in nearby failure logs. This
inconsistency makes it harder to correlate and diagnose which specific pipeline dispatch or direct
trigger caused the marshal failure.
Code

internal/api/handlers.go[R246-248]

+				s.logger.Error("failed to marshal event", "error", err)
+				s.writeError(w, http.StatusInternalServerError, "failed to marshal event")
+				return
Evidence
In both handlers, the marshal-error logging line includes only the error object, while a subsequent
enqueue-failure/enqueue-error log nearby includes structured context fields such as pipeline and/or
plugin and command. This side-by-side contrast in the cited regions shows the new marshal-failure
path is missing identifiers that are already available in scope and used elsewhere, reducing the
logs’ usefulness for debugging and incident triage.

internal/api/handlers.go[240-249]
internal/api/handlers.go[252-266]
internal/api/handlers.go[410-428]
internal/api/handlers.go[431-441]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`handlePipelineTrigger` and `handlePluginTrigger` log `failed to marshal event` with only the error object, while other failure logs in the same handlers include structured identifiers (pipeline/plugin/command, etc.) that are important for correlating failures to a specific dispatch/trigger.

## Issue Context
These marshal-error logs occur in code paths where the relevant identifiers are already in scope (e.g., pipeline name plus per-dispatch plugin/command and dispatch index in the pipeline dispatch loop; pluginName/commandName in the direct plugin trigger handler) and are already used in the subsequent enqueue failure logs. The goal is to make the marshal-error logs consistent with the enqueue-error logging style, improving diagnosability without logging raw/user payload contents.

## Fix Focus Areas
- internal/api/handlers.go[240-249]
- internal/api/handlers.go[252-266]
- internal/api/handlers.go[410-428]
- internal/api/handlers.go[431-441]

β“˜ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

CI Feedback 🧐

A test triggered by this PR failed. Here is an AI-generated analysis of the failure:

Action: docker-validation

Failed stage: Run Docker-backed staged tests [❌]

Failed test name: webhook-ingress

Failure summary:

The action failed during the test-docker workflow while running the webhook-ingress fixture.
- The
fixture webhook-ingress started the ductile process but then reported: FAIL: health endpoint did not
become ready (log line 273).
- This caused the step to exit with code 1, which failed the GitHub
Action (log line 274).

Relevant error logs:
1:  ##[group]Runner Image Provisioner
2:  Hosted Compute Agent
...

258:  ==> test-docker: fixture api-e2e
259:  [fixture:api-e2e] starting ductile process
260:  [fixture:api-e2e] triggering direct plugin execution via CLI
261:  [fixture:api-e2e] triggering pipeline execution via CLI
262:  [fixture:api-e2e] success
263:  ==> test-docker: building ductile binary
264:  ==> test-docker: fixture scheduler-recovery
265:  [fixture:scheduler-recovery] starting ductile process
266:  [fixture:scheduler-recovery] restarting service to trigger recovery
267:  [fixture:scheduler-recovery] starting ductile process
268:  [fixture:scheduler-recovery] success
269:  ==> test-docker: building ductile binary
270:  ==> test-docker: fixture webhook-ingress
271:  [fixture:webhook-ingress] refreshing fixture checksums
272:  [fixture:webhook-ingress] starting ductile process
273:  [fixture:webhook-ingress] FAIL: health endpoint did not become ready
274:  ##[error]Process completed with exit code 1.
275:  ##[group]Run actions/upload-artifact@v4

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

πŸ€– 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.

Inline comments:
In @.jules/sentinel.md:
- Around line 1-4: The markdown heading at the top ("2026-06-06 - Fix unhandled
json.Marshal errors in API handlers") is using an H2 and lacks required
surrounding blank lines; change the "##" to a top-level "#" and ensure there is
a single blank line before and after that heading (i.e., add an empty line above
the heading and one empty line below it) so the file conforms to MD041/MD022
rules.
πŸͺ„ Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 91d0fb59-da16-4c89-9d81-f42b5695287a

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 275d565 and 3c1e88d.

πŸ“’ Files selected for processing (2)
  • .jules/sentinel.md
  • internal/api/handlers.go

Comment thread .jules/sentinel.md
Comment on lines +1 to +4
## 2026-06-06 - Fix unhandled json.Marshal errors in API handlers
**Vulnerability:** In `internal/api/handlers.go`, errors from `json.Marshal` were explicitly ignored using `_` when wrapping event payloads.
**Learning:** Ignoring marshaling errors allows empty or malformed byte slices to be enqueued, which could lead to downstream panics, silent data corruption, or denial-of-service if workers cannot process the invalid payloads. This is a common pattern when developers assume internal structs will always marshal successfully.
**Prevention:** Always check and handle the `error` returned by `json.Marshal`. If it fails, log the error securely and return a generic 500 Internal Server Error without leaking details to the client.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟑 Minor | ⚑ Quick win

Fix markdownlint heading structure (MD041/MD022).

The file starts with an H2 and lacks the required blank-line spacing around the heading, which matches the static-analysis warnings.

Suggested patch
+# Sentinel Notes
+
 ## 2026-06-06 - Fix unhandled json.Marshal errors in API handlers
+
 **Vulnerability:** In `internal/api/handlers.go`, errors from `json.Marshal` were explicitly ignored using `_` when wrapping event payloads.
 **Learning:** Ignoring marshaling errors allows empty or malformed byte slices to be enqueued, which could lead to downstream panics, silent data corruption, or denial-of-service if workers cannot process the invalid payloads. This is a common pattern when developers assume internal structs will always marshal successfully.
 **Prevention:** Always check and handle the `error` returned by `json.Marshal`. If it fails, log the error securely and return a generic 500 Internal Server Error without leaking details to the client.
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
## 2026-06-06 - Fix unhandled json.Marshal errors in API handlers
**Vulnerability:** In `internal/api/handlers.go`, errors from `json.Marshal` were explicitly ignored using `_` when wrapping event payloads.
**Learning:** Ignoring marshaling errors allows empty or malformed byte slices to be enqueued, which could lead to downstream panics, silent data corruption, or denial-of-service if workers cannot process the invalid payloads. This is a common pattern when developers assume internal structs will always marshal successfully.
**Prevention:** Always check and handle the `error` returned by `json.Marshal`. If it fails, log the error securely and return a generic 500 Internal Server Error without leaking details to the client.
# Sentinel Notes
## 2026-06-06 - Fix unhandled json.Marshal errors in API handlers
**Vulnerability:** In `internal/api/handlers.go`, errors from `json.Marshal` were explicitly ignored using `_` when wrapping event payloads.
**Learning:** Ignoring marshaling errors allows empty or malformed byte slices to be enqueued, which could lead to downstream panics, silent data corruption, or denial-of-service if workers cannot process the invalid payloads. This is a common pattern when developers assume internal structs will always marshal successfully.
**Prevention:** Always check and handle the `error` returned by `json.Marshal`. If it fails, log the error securely and return a generic 500 Internal Server Error without leaking details to the client.
🧰 Tools
πŸͺ› markdownlint-cli2 (0.22.1)

[warning] 1-1: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 1-1: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

πŸ€– 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 @.jules/sentinel.md around lines 1 - 4, The markdown heading at the top
("2026-06-06 - Fix unhandled json.Marshal errors in API handlers") is using an
H2 and lacks required surrounding blank lines; change the "##" to a top-level
"#" and ensure there is a single blank line before and after that heading (i.e.,
add an empty line above the heading and one empty line below it) so the file
conforms to MD041/MD022 rules.

Source: Linters/SAST tools

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.

1 participant