Skip to content

[ZEPPELIN-6556] Personalized mode leaks a non-owner's paragraph edits into the shared master paragraph - #5360

Open
xhaktm00 wants to merge 2 commits into
apache:masterfrom
xhaktm00:ZEPPELIN-6556
Open

[ZEPPELIN-6556] Personalized mode leaks a non-owner's paragraph edits into the shared master paragraph#5360
xhaktm00 wants to merge 2 commits into
apache:masterfrom
xhaktm00:ZEPPELIN-6556

Conversation

@xhaktm00

@xhaktm00 xhaktm00 commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

What is this PR for?

A note can be switched to personalized mode so that each user gets their own copy of a paragraph and one user's form values and results do not affect another's.

However, NotebookService.runParagraph writes the caller's params, text, title and config into the shared master paragraph before it checks whether the note is personalized:

p.setText(text);
p.setTitle(title);
p.setAuthenticationInfo(context.getAutheInfo());
if (params != null && !params.isEmpty()) {
  p.settings.setParams(params);       // master paragraph
}
if (config != null && !config.isEmpty()) {
  p.mergeConfig(config);              // master paragraph
}

if (note.isPersonalizedMode()) {
  p = p.getUserParagraph(context.getAutheInfo().getUser());
  ...                                 // the user copy gets the same values
}

notebook.saveNote(...) then persists the polluted master. The same ordering exists in updateParagraph, and setParagraphUsingMessage is worse: its personalized branch re-fetches the master via note.getParagraph(paragraphId) instead of resolving the user copy, so it writes the same values into the master twice and never touches the user copy at all.

So in personalized mode, a non-owner who edits a dynamic form and runs the paragraph silently overwrites the shared original.

Because Paragraph.userParagraphMap is transient, the per-user copies do not survive a restart. The corruption stays invisible while the copies exist and surfaces later:

  • after a server restart the user copies are gone and every user sees whatever the last runner wrote
  • turning personalized mode off (Note.clearUserParagraphs) exposes the polluted master
  • a user opening the note for the first time clones the polluted master

The fix: resolve the target paragraph first — when the note is personalized, switch to getUserParagraph(user) before any write — so the master paragraph is never mutated by another user's run or update. Applied to runParagraph, updateParagraph and setParagraphUsingMessage. Since the two branches wrote identical values, this also removes the duplicated write blocks.

The only caller of setParagraphUsingMessage is spell(), which now records the spell result on the user copy in personalized mode — the intended behavior — instead of on the shared master.

Note: PersonalizeActionsIT.testDynamicFormAction asserts the correct behavior (a non-owner's edit must not leak) but was passing against the old server behavior only because a late WebSocket broadcast reverted the typed form value before the run.

What type of PR is it?

Bug Fix

Todos

  • Resolve the user paragraph before writing params/text/title/config in runParagraph, updateParagraph and setParagraphUsingMessage
  • Fix setParagraphUsingMessage re-fetching the master in its personalized branch
  • Add a unit test that asserts master paragraph integrity in personalized mode

What is the Jira issue?

How should this be tested?

New test NotebookServiceTest#testRunParagraphInPersonalizedModeDoesNotPolluteMasterParagraph: on a personalized note, it runs and then updates a paragraph as user1 with new params/title, and asserts that the master paragraph's params and title are unchanged while getUserParagraph("user1") picks up the new values.

./mvnw -pl zeppelin-server test -Dtest=NotebookServiceTest -DfailIfNoTests=false

Result with the fix: Tests run: 6, Failures: 0, Errors: 0.

Manual verification: create a note with %sh echo "hello, ${name=original}", run it, enable personalized mode, log in as a second user, change the form value and run. Then turn personalized mode off (or restart the server): the paragraph must still show original.

Screenshots (if appropriate)

N/A

Questions:

  • Does the license files need to update? No
  • Is there breaking changes for older versions? No
  • Does this needs documentation? No

@xhaktm00
xhaktm00 force-pushed the ZEPPELIN-6556 branch 2 times, most recently from 42c570e to 2cc99e3 Compare August 2, 2026 05:17
…personalized mode

PersonalizeActionsIT.testGraphAction showed that blocking every master-paragraph
write in personalized mode also blocked the note owner's changes, so new users
no longer inherited them. Guard the master write with an owner check instead:
the owner's changes update both the master and their personal copy (previous
behavior), while a non-owner's changes stay in their personal copy only.
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