New script APIs
window.onurlchange(SPA navigation events)GM_getTab/GM_saveTab/GM_getTabs(per-tab storage)GM_cookie: cross-domain access (gated by@connect) + sameSite on set()GM_download: custom request headersGM_xmlhttpRequest: per-request cookies@icon64
UI
- "New User Script" jumps straight into the editor (toolbar + about:addons)
- "User Script Commands" menu grouped per script
- Source viewer: regex (/pattern/) find
Updates
- Built-in update scheduler: check every N days (0 = off) + "Check now"
- The empty "Get user scripts" view now offers a hosting-site menu (GreasyFork / OpenUserJS / Gist).
Import / Export
- Offline restore — bundles each script's
@require/@resource/@icon - Violentmonkey / Tampermonkey import compatibility
- Non-freezing export, constant-memory import, integrity-checked + de-duplicated dependencies
Security
- Missing
@connectnow means same-origin only (was: all hosts) - SSRF guard — loopback/intranet hosts require an explicit
@connect - Secure-update check now also covers
@updateURL; optional HTTPS-only + hash (#sha256=) pinning for dependencies - HttpOnly cookie values can be hidden from scripts; forced third-party cookies now optional
GM_downloadallows any file except dangerous executables (was an over-narrow allow-list)
Fixes
GM_cookienow works at runtime (incl. the GM.cookie promise form)- Update checks skip stale cache; removed a duplicate Accept header
Notes & preferences
-
How "New User Script" works now. Both the toolbar New User Script… and the about:addons Create new userscript button skip the old name/namespace dialog: they create a script immediately — auto-named "New User Script N" with the Greasemonkey namespace, pre-scoped to the active tab's site — and open it straight in your configured editor (or the browser's Scratchpad). You rename it just by editing
@name; the on-disk folder and the script's internal id never change, so renaming never loses the script'sGM_setValuedata. Prefer the old flow? Setextensions.greasemonkey.manager.newScript.classicDialog.enabledto true and both entry points fall back to the name/namespace dialog. -
Heads-up —
@connectis now enforced. A userscript that callsGM_xmlhttpRequestagainst another domain without declaring it in@connectis now blocked (requests are limited to the page's own origin), matching Violentmonkey / Tampermonkey. If an older script stops making cross-site requests, add the right //@connecthost line — or, to restore the previous "allow any host" behaviour globally, setextensions.greasemonkey.xmlhttprequest.allowAllHostsWithoutConnectto true. Loopback / intranet addresses (localhost, 127.0.0.1, 10.x, …) always require an explicit@connect, even with that pref on. -
Dependency pinning.
@require/@resourceURLs may carry a Subresource-Integrity hash — e.g. //@requirehttps://cdn/lib.js#sha256= (also sha384 / sha512) — and the downloaded file is verified against it; a mismatch is refused. Set extensions.greasemonkey.requireSecureDependencies to true to additionally refuse plain-http:// dependencies.
New about:config preferences (all under extensions.greasemonkey., default in parentheses):
update.intervalDays(1) — days between automatic script-update checks; 0 disables them. update.lastCheck records the last sweep.manager.newScript.classicDialog.enabled(false) — restore the classic name/namespace dialog for new scripts.xmlhttprequest.allowAllHostsWithoutConnect(false) — restore the old "no@connect= reach any host" behaviour.xmlhttprequest.forceThirdPartyCookies(true) — set false so a cross-origin GM_xmlhttpRequest respects the browser's third-party-cookie policy instead of always sending them.requireSecureDependencies(false) — require HTTPS for@require/@resource.api.GM_cookie.exposeHttpOnly(true) — set false to hide HttpOnly cookie values from GM_cookie.list.api.window.onurlchange(true) — the SPA-navigation monitor; set false to disable it.api.GM_getTab(true) — the GM_getTab / GM_saveTab / GM_getTabs APIs; set false to remove them.backup.asyncExport(true) — set false to force the older synchronous (UI-blocking) backup export.