Skip to content

fix(server): decode base64 Lambda Function URL request bodies before parsing (follow-up to #889) - #1483

Merged
cristim merged 1 commit into
mainfrom
fix/889-lambda-base64-body-decode
Jul 22, 2026
Merged

fix(server): decode base64 Lambda Function URL request bodies before parsing (follow-up to #889)#1483
cristim merged 1 commit into
mainfrom
fix/889-lambda-base64-body-decode

Conversation

@cristim

@cristim cristim commented Jul 21, 2026

Copy link
Copy Markdown
Member

Summary

  • Follow-up to feat(email): post-execution notification with one-click revoke (closes #291) #889 (one-click purchase-revoke confirmation flow). AWS Lambda Function URLs base64-encode POST bodies whenever the Content-Type isn't recognized as plain text, which is the case for the confirmation form's application/x-www-form-urlencoded POST. handleLambdaHTTPEvent never checked request.IsBase64Encoded, so resolveApprovalToken received a base64 blob instead of token=... and every revoke via the email link 401'd in Lambda Function URL mode -- the primary deploy mode for this app. The HTTP/Fargate adapter was unaffected since it builds its own request with IsBase64Encoded always false.
  • Fix: decode the body once, centrally, in internal/server/lambda.go's handleLambdaHTTPEvent, right after the raw event is unmarshaled and before anything downstream (OIDC, static files, the API router) reads request.Body. A decode failure returns the same 400 response already used for a malformed event, instead of silently proceeding with garbage.
  • No other handler in internal/api/ does its own base64 decode of the inbound body (confirmed via git grep -n IsBase64Encoded and a scan of every .Body usage), so centralizing the decode here fixes this class of bug for any other Content-Type-sensitive body parsing on the Lambda path too, without any double-decode risk.

Test plan

  • Added TestHandleLambdaHTTPEvent_DecodesBase64FormBody in internal/server/lambda_coverage_test.go, driving the real failing scenario: a base64-encoded, form-urlencoded POST body hitting POST /api/purchases/revoke/{execID}. Confirmed it FAILS against the pre-fix code (401 "sign in or use the revocation link...") and PASSES after the fix (401 "sign in with the account's contact email...", proving the token was correctly resolved from the decoded body).
  • go build ./... -- exit 0
  • go vet ./... -- exit 0
  • go test ./... -- 5898 passed in 38 packages, exit 0
  • golangci-lint run at the CI-pinned v2.10.1 (both ./internal/server/... ./internal/api/... and the full ./...) -- 0 issues, exit 0
  • gocyclo -over 10 -ignore "_test\.go" on the touched packages -- exit 0, no findings

Summary by CodeRabbit

  • Bug Fixes

    • Improved handling of base64-encoded request bodies for Lambda Function URLs.
    • Added validation for malformed encoded requests, returning a clear 400 error instead of processing invalid data.
    • Preserved the behavior of standard, non-encoded request bodies.
  • Tests

    • Added coverage for encoded, plain-text, and malformed request body scenarios.

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 15 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 33181a1d-00cb-46fb-85c0-8fbab0c1bb29

📥 Commits

Reviewing files that changed from the base of the PR and between d23b270 and 278a5e7.

📒 Files selected for processing (2)
  • internal/server/lambda.go
  • internal/server/lambda_coverage_test.go
📝 Walkthrough

Walkthrough

Lambda Function URL handling now decodes base64-encoded request bodies before downstream processing, rejects malformed input with HTTP 400, and preserves plain bodies. Tests cover encoded, plain, and invalid base64 form submissions.

Changes

Lambda body decoding

Layer / File(s) Summary
Decode Lambda request bodies
internal/server/lambda.go
handleLambdaHTTPEvent decodes flagged request bodies, clears the encoding flag after success, and returns a secured 400 response for decoding failures.
Validate encoded and plain body handling
internal/server/lambda_coverage_test.go
Regression tests verify base64 form decoding, unchanged plain form bodies, and malformed base64 rejection.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant LambdaFunctionURL
  participant handleLambdaHTTPEvent
  participant Base64Decoder
  participant DownstreamProcessing
  LambdaFunctionURL->>handleLambdaHTTPEvent: request body and IsBase64Encoded
  handleLambdaHTTPEvent->>Base64Decoder: decode flagged body
  Base64Decoder-->>handleLambdaHTTPEvent: decoded body or decode error
  handleLambdaHTTPEvent->>DownstreamProcessing: decoded request body
Loading
🚥 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 clearly summarizes the main change: decoding base64 Lambda Function URL request bodies before parsing.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/889-lambda-base64-body-decode

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

@cristim cristim added triaged Item has been triaged priority/p0 Drop everything; same-day fix severity/critical Major harm when it happens urgency/now Drop other things impact/all-users Affects every user effort/s Hours type/bug Defect labels Jul 21, 2026
@cristim

cristim commented Jul 21, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@cristim
cristim force-pushed the fix/889-lambda-base64-body-decode branch from 30a843a to d23b270 Compare July 22, 2026 20:42
@cristim

cristim commented Jul 22, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

…parsing

AWS Lambda Function URLs base64-encode POST bodies whenever the
Content-Type isn't recognized as plain text, which is the case for the
one-click revoke confirmation form's application/x-www-form-urlencoded
POST added in #889. handleLambdaHTTPEvent never checked
request.IsBase64Encoded, so resolveApprovalToken received a base64 blob
instead of "token=...", and every revoke via the email link 401'd in
Lambda mode (the primary deploy mode). The HTTP/Fargate adapter was
unaffected since it builds its own request with IsBase64Encoded always
false.

Decode the body once, centrally, right after the raw event is
unmarshaled and before anything downstream (OIDC, static files, the API
router) reads it. A decode failure returns the same 400 response
already used for a malformed event instead of silently proceeding with
garbage.
@cristim
cristim force-pushed the fix/889-lambda-base64-body-decode branch from d23b270 to 278a5e7 Compare July 22, 2026 21:26
@cristim
cristim merged commit f8cdea6 into main Jul 22, 2026
19 checks passed
@cristim
cristim deleted the fix/889-lambda-base64-body-decode branch July 27, 2026 11:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/s Hours impact/all-users Affects every user priority/p0 Drop everything; same-day fix severity/critical Major harm when it happens triaged Item has been triaged type/bug Defect urgency/now Drop other things

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant