v1.2.1 #187
DominusKelvin
announced in
Announcements
v1.2.1
#187
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
inertia-sails v1.3.1
Security: Shared props no longer leak across requests
This release fixes a critical bug where user-specific shared props could leak between requests, causing one user's data (e.g.,
loggedInUser) to appear in another user's session — including unauthenticated visitors.This affects all Boring Stack apps that call
sails.inertia.share()inroutes.beforehandlers, which is the standard pattern for passing logged-in user data to the frontend.The bug
Three issues combined to create a data leak:
share()silently fell back to global storage — When called outside AsyncLocalStorage context,share()wrote toglobalSharedProps, a process-level singleton. That data persisted and bled into every subsequent request.flushShared()never cleaned global storage — Theglobalparameter defaulted tofalse, so stale data inglobalSharedPropswas never cleared between requests.Hook load order created a race condition — inertia-sails set up AsyncLocalStorage context in
routes.before, but other hooks (like the custom hook) also useroutes.beforeto callshare(). If another hook's handler ran first,share()was called before context existed, triggering the global fallback.The fix
AsyncLocalStorage context is now injected as HTTP middleware during
configure(), guaranteeing it exists before any hook'sroutes.beforehandler runs.The fix uses Sails'
configure()lifecycle phase — which runs for all hooks before any hook'sinitialize()— to inject aninertiaContextmiddleware into the HTTP stack before the router.For socket requests (which bypass Express middleware and go through
sails.router.route()directly), the existingroutes.beforehandlers remain as a fallback with a guard that skips setup if context was already established by the HTTP middleware.Breaking changes
share()no longer falls back to global storagePreviously, calling
share()outside a request context silently wrote toglobalSharedProps. Now it logs a warning and discards the value.If you see warnings like
share('key') called outside request context, move the call into aroutes.beforehandler, controller, or helper — anywhere inside the request lifecycle.flushShared()always cleans global storageThe
globalparameter has been removed.flushShared()now always cleans both request-scoped and global storage to prevent stale data.local()no longer falls back to global storageSame change as
share()— uselocalGlobally()for global locals.How to verify the fix
Update inertia-sails:
Start your app and log in as User A in one browser
Open the app in a different browser or incognito window (not logged in)
Verify the unauthenticated browser does not show User A's avatar, name, or any session data
Check server logs — there should be no
share() called outside request contextwarnings under normal operationAdditional fixes
AsyncLocalStorage.run()callback type error — wrapped the callback to satisfy the() => anysignature expected by therun()overloadReferences
Migration guide
No code changes required in your app. Just update the dependency:
If you were calling
flushShared()with the secondglobalargument, remove it — global is now always cleaned:Full Changelog: v1.2.0...v1.2.1
This discussion was created from the release v1.2.1.
Beta Was this translation helpful? Give feedback.
All reactions