-
-
Notifications
You must be signed in to change notification settings - Fork 11.4k
Description
Issue Summary
Description
The fetchQueryStrData() function in apps/portal/src/app.js calls JSON.parse(value) on several URL hash parameters without try/catch protection. If a preview URL contains malformed JSON in any of these parameters, the Portal widget either fails to initialize or crashes entirely.
This affects 9 parameters: button, name, isFree, isMonthly, isYearly, portalProducts, disableBackground, signupCheckboxRequired, and transistorPortalSettings.
Steps to Reproduce
- Run Ghost v6.19.0 with Portal enabled (default)
- Visit any page with a malformed preview hash, e.g.:
https://your-ghost-site.com/#preview?button={INVALID
- The Portal widget does not render
For the hashchange crash path:
- Load a Ghost page normally (Portal renders in bottom-right)
- Change the URL hash to
#preview?button={INVALID - The Portal widget crashes and disappears —
updateStateForPreviewLinks()(line 745) has no try/catch, so the exception propagates uncaught into React
Root Cause
fetchQueryStrData() (lines ~367–412) passes user-supplied URL parameter values directly to JSON.parse() with no validation or error handling:
if (key === 'button') {
data.site.portal_button = JSON.parse(value);
} else if (key === 'name') {
data.site.portal_name = JSON.parse(value);
}
// ... 7 more parametersOn the initial load path, the exception is caught by initSetup()'s try/catch, which sets initStatus: 'failed' and causes render() to return null. On the hashchange path (updateStateForPreviewLinks), there is no try/catch at all.
Suggested Fix
A simple safe-parse wrapper resolves all 9 instances:
function safeJSONParse(value, fallback = null) {
try {
return JSON.parse(value);
} catch (e) {
console.warn('[Portal] Invalid JSON in URL parameter:', e.message);
return fallback;
}
}Replace each JSON.parse(value) call in fetchQueryStrData() with safeJSONParse(value). Additionally, wrapping updateStateForPreviewLinks() in a try/catch would prevent the uncaught exception on the hashchange path.
Environment
- Ghost version: 6.19.0
- Portal version: 2.36.1
- File:
apps/portal/src/app.js
Steps to Reproduce
Steps to Reproduce
- Run Ghost v6.19.0 with Portal enabled (default)
- Visit any page with a malformed preview hash, e.g.:
https://your-ghost-site.com/#preview?button={INVALID
- The Portal widget does not render
For the hashchange crash path:
- Load a Ghost page normally (Portal renders in bottom-right)
- Change the URL hash to
#preview?button={INVALID - The Portal widget crashes and disappears —
updateStateForPreviewLinks()(line 745) has no try/catch, so the exception propagates uncaught into React
Ghost Version
6.19.0
Node.js Version
18.20.8
How did you install Ghost?
Git clone
Database type
MySQL 5.7
Browser & OS version
No response
Relevant log / error output
Code of Conduct
- I agree to be friendly and polite to people in this repository