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 %md 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.
@tbonelee

tbonelee commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

I think there are two separate concerns mixed in here: fixing the leak itself, and deciding what the permission policy for personalized mode should be.

If personalized mode is meant to give each user their own view of the note, then arguably even the note owner should not affect the master paragraph while the mode is on. The earlier commit (ac76546) looks closer to that.

One thing worth checking before settling on the owner-based gate is the testGraphAction failure that motivated it. In the original test (ZEPPELIN-2661) the owner set the chart type before turning personalized mode on, so nothing was written to the master paragraph while the mode was active. That order was flipped in ZEPPELIN-4361 ("Fix broken tests"), and the test now sets the chart type after the mode is on and asserts that a new user inherits it. So the assertion the earlier commit broke may not be describing the originally intended behavior.

@jongyoul you worked on the original implementation, so you may have the context here. Was the intent that the master paragraph stays frozen while personalized mode is on?

tbonelee

This comment was marked as outdated.

@tbonelee
tbonelee dismissed their stale review August 5, 2026 16:37

Posting as a plain comment instead

@xhaktm00

xhaktm00 commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@tbonelee Thank you for the careful review. I've updated the manual verification steps to use %md, since ShellInterpreter returns FormType.NATIVE as you noted.

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.

2 participants