← knowledge.oriz.in

Tampermonkey userscript audit — 2026-07-03

decision decisionuserscriptstampermonkeyauditchrome

Tampermonkey userscript audit — 2026-07-03

Method

  1. Copied Chrome's Tampermonkey LevelDB from %LOCALAPPDATA%\Google\Chrome\User Data\Default\Local Extension Settings\dhdgffkkebhmkfjojejmpbldmpobfkfo to a scratch dir (bypasses Chrome's lock).
  2. Read with classic-level npm package (Snappy-aware). 877 raw keys → 137 unique userscripts.
  3. Categorized by author + support/homepage URL.
  4. Fetched source for the 37 with GitHub support URLs.
  5. Static-scanned for: unsafe eval, document.write, missing @grant, missing @connect, deprecated GM_getValue, jQuery-CDN, hardcoded localhost, exposed API keys, chrome.* namespace misuse, unrestricted @match.
  6. Filtered out heuristic false positives (URL strings that aren't GM_xhr targets, GM_ regex matches in comments, local variables named GM_fetch).

Numbers

Category Count
Total installed 137
Own (chirag127) 4
Third-party with GitHub tracker 37
Third-party Codeberg tracker 1
Third-party Greasyfork-only (comments) 52
Third-party Sleazyfork-only (NSFW) 4
No tracker / dead links 43
Heuristic-flagged findings 13
Strict-verified findings 1
PRs filed this session 1

The one real finding

Purfview/IMDb-Scout-Modeval(ratings_array.join("+")) for summing an array. Textbook eval-for-sum antipattern. Filed PR #350: replace with reduce((a,b) => a+b, 0).

False positives that were flagged but survived scrutiny

Script Heuristic-flag Why false
KeepChatGPT, Pixiv Downloader, Google Unlocked gm_xhr_no_connect Regex matched URL strings that aren't GM_xhr targets
IMDb Scout Mod, SearchJumper missing_grant for GM_Config / GM_fetch Both are local variables/references, not Tampermonkey APIs
AdsBypasser eval Intentional — script unwraps dynamic ad-payloads by design
Multiple scripts deprecated_gm_getvalue Sync API still works fine; async migration needs await propagation through every caller, not a mechanical swap
Various jquery_injection jQuery loaded via <script> tag is fine when the target site allows unsafe-inline; CSP-breakage is site-specific

Why so many false positives

Static scanning of userscripts is noisy because:

Every finding must be verified against the actual call site, not the regex hit. Filing 13 speculative issues would have been spam.

Not-yet-filed (Greasyfork listings, no GitHub)

52 Greasyfork-only scripts + 43 no-tracker scripts. Filing on Greasyfork's per-script "feedback" tab is possible but:

Deferred: file only when a real bug hits during actual use. Do not mass-file.

Own scripts (repos/own/userscripts/)

4 tracked: serp-open-articles, youtube-dislike-and-next-shortcut, youtube-nav-shortcuts, youtube-next-video-shortcut, youtube-prev-video-shortcut. Their Greasyfork downloadURLs point to oriz-org/userscripts which was renamed — the installed copies are stale. Auto-update won't fetch new versions until @downloadURL in the installed metadata points at chirag127/userscripts or wherever the current home is.

Action for own scripts: update @downloadURL in each .user.js header to point at the current-canonical raw URL, republish to Greasyfork so installed copies re-lock to the right update path. Tracked separately.

Data artifacts (local only, not committed)

Rules exercised

Follow-up