Skip to content

[MINOR] Tighten origin and content-type handling in REST/WebSocket layer#5251

Merged
jongyoul merged 1 commit into
apache:branch-0.12from
jongyoul:minor-cors-hardening-0.12
May 18, 2026
Merged

[MINOR] Tighten origin and content-type handling in REST/WebSocket layer#5251
jongyoul merged 1 commit into
apache:branch-0.12from
jongyoul:minor-cors-hardening-0.12

Conversation

@jongyoul
Copy link
Copy Markdown
Member

Backport of #5229 to branch-0.12 for the upcoming 0.12.1 security release.

What changes

Cherry-pick of the squash commit 9da7f2a from master. Tightens default security behavior in the REST/WebSocket request-handling layer:

  • CORS: block disallowed cross-origin preflights and state-changing requests; only emit Access-Control-Allow-Credentials for allowed origins; default zeppelin.server.allowed.origins becomes empty.
  • New Jersey filter (AllowedContentTypeFilter) rejects state-changing REST requests whose Content-Type is not in the allow-list (application/json, application/x-www-form-urlencoded, multipart/form-data) with 415.
  • Shiro template: default cookie.sameSite = LAX.
  • ZeppelinClient: send explicit application/json Content-Type on all body-carrying calls.

Notes for 0.12.1 release

This is a breaking change for some external integrations and must be called out in the 0.12.1 release notes:

  1. zeppelin.server.allowed.origins default changed from * to empty. Same-host and localhost requests still pass via shortcuts, but cross-domain SPAs that called Zeppelin REST without explicit origin allow-listing will need to set this property.
  2. State-changing REST requests must now send a supported Content-Type or they will be rejected with 415. Browser/Angular UI traffic and ZeppelinClient are unaffected; only third-party clients sending bodies without Content-Type (or with text/plain etc.) will see this.

Verification

  • Cherry-pick applied cleanly to branch-0.12 (no conflicts).
  • Local mvn test on the affected modules: AllowedContentTypeFilterTest, CorsFilterTest, CorsUtilsTest, ZeppelinConfigurationTest, NotebookServiceTest#testNormalizeNotePath — 33 tests pass.

## What is this PR for?

Apply stricter defaults to the request-handling layer for tighter out-of-the-box behavior:

- `CorsFilter` blocks state-changing methods (POST/PUT/DELETE/PATCH) and cross-origin preflight requests when the `Origin` header is not in the configured allow-list. `Access-Control-Allow-Credentials` is only sent when the `Origin` is allowed.
- The default value of `zeppelin.server.allowed.origins` changes from `*` to empty so cross-origin browser access must be explicitly enabled. **Operators relying on the previous default need to set this back to `*` or to specific origin(s).** Same-origin / same-host and non-browser clients are unaffected.
- A new Jersey request filter restricts REST request bodies on state-changing methods to `application/json`, `application/x-www-form-urlencoded`, or `multipart/form-data`; other media types are rejected with `415`.
- The default `shiro.ini.template` now sets `cookie.sameSite = LAX`.
- `ZeppelinClient.addParagraph` and `updateParagraph` now send an explicit `Content-Type: application/json` header so they pass the new filter.
- `CorsUtils.isValidOrigin` normalizes the `Origin` header to lowercase before the allow-list membership check, mirroring how the configured origins are stored, so case differences in the `Origin` header do not produce false rejections.
- A small `HttpMethods` utility holds the shared `STATE_CHANGING` method set used by both the servlet filter and the Jersey filter.

## What type of PR is it?

Improvement

## Todos

- [ ] CI green

## Questions

- None

## Screenshots (if appropriate)

N/A

Closes apache#5229 from jongyoul/minor-cors-hardening.

Signed-off-by: Jongyoul Lee <jongyoul@gmail.com>
(cherry picked from commit 9da7f2a)
Signed-off-by: Jongyoul Lee <jongyoul@gmail.com>
@jongyoul jongyoul merged commit 1a7f550 into apache:branch-0.12 May 18, 2026
19 checks passed
@jongyoul jongyoul deleted the minor-cors-hardening-0.12 branch May 18, 2026 13:41
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