[Bounty proposal] security: omi-dropbox-app reflects raw uid into setup-page HTML (reflected XSS) + stored folder_name sink ($75 proposed)
Symptom
plugins/omi-dropbox-app/main.py → GET / is unauthenticated and reflects the uid query parameter, unescaped, into the HTML it returns. Opening
https://<dropbox-app-host>/?uid=%22%3E%3Cscript%3Ealert(1)%3C/script%3Ereturns markup whose retry link is
<a href="/auth/dropbox?uid="><script>alert(1)</script>" class="btn">Connect Dropbox</a>so the script runs in the victim's browser on the plugin's origin (reflected XSS). No login or prior state is needed — the disconnected branch renders for any uid with no stored tokens, which is every attacker-chosen value. A benign & or # in uid corrupts the link the same way.
Second sink: stored, not just reflected
folder_name is set by the user through POST /settings and rendered straight back into an attribute on the same page:
<input type="text" id="folder_name" name="folder_name" value="{settings.get('folder_name', 'Omi Conversations')}" ...>A folder_name containing "> closes the attribute and the tag. Unlike the uid case this persists in the user's stored settings and fires on every subsequent page load.
display_name and email (from the Dropbox API) and the /auth/dropbox/callback error page — which interpolates str(e) raw into HTML — have the same shape.
Evidence
plugins/omi-dropbox-app/main.py on current main: the module imports no escaping helper at all (no html, no quote), and get_home_page_html() interpolates {uid} into three attributes (/settings, /disconnect, /auth/dropbox), plus the value= sink above.
Relationship to #13658
#13658 fixes exactly this class — "encode reflected uid in setup/auth pages" — across six apps: omi-clickup-app, omi-github-app, omi-notion-app, omi-slack-app, omi-twitter-chat-tools-app, omi-whoop-app. omi-dropbox-app was not in that set and still carries the defect.
Acceptance criteria
uidis percent-encoded (quote(uid, safe="")) everywhere it reaches a URL — the three HTML attributes and the threeRedirectResponsetargets.folder_name,display_name,email, and the callback error text are HTML-escaped./?uid=abc123still renders/auth/dropbox?uid=abc123unchanged.- A registered hermetic regression suite proves red→green against the pre-fix module.
Fix
PR pending — implemented in the same session as this report, so nothing here is left as an unclaimed specification.
Bounty
$75 proposed. For comparables: #14350 proposes $25 for a single reflected-XSS sink in omi-twitter-app, while the plugin security issues in the current batch (#14430, #14442, #14444, #14446, #14451, #14453) are proposed at $150–$200. This one covers a reflected sink on an unauthenticated route, a stored sink, and four more, with a registered regression suite — so it sits between the two. Your number is the number.
Source: BasedHardware/omi