SHA-256 hashes — GSE Companion + GSE addon builds Recomputed and verified 2026-06-12 against files on disk. 706742b44f5ea9056f67df2e8cae771cd909dd0b882a0d4c3bf87a7639d0043f GSE Companion Setup 0.4.12.exe (81,299,552 bytes) 209adedde7905179832038661b5d279a95831a155d963da3190871d502f36b0f app.asar (installed Companion logic) (6,068,792 bytes) 789753305d33dc21732b67948ef839f4b058fcc15e095b8be8fcb855e28d9c85 GSE-3.3.20-9-gd5e65ce.zip (public) (2,514,665 bytes) 7ea11bd7dbe6bb64eb1867462197c7ac52e795a0e7a528eeba77d62be475f5a0 GSE-3.3.20-9-gd5e65ce-PatronBuild.zip (2,522,115 bytes) How to reproduce: certutil -hashfile "" SHA256 (Windows) sha256sum "" (Linux/macOS) app.asar path after install: %LOCALAPPDATA%\Programs\gse-companion\resources\app.asar --- 0.4.13 (acquired 2026-06-17) ------------------------------------------------- d580dc7c7c39fb747b25830e8233d71b7f4404a07d3c8b14262dc3254d114729 GSE Companion Setup 0.4.13.exe (81,299,751 bytes) 4f9a2664ea0d2cb5a4f4594299dfd7e74242379fd4fbf2edbf75655893278c5f app.asar (0.4.13, extracted statically) (6,068,841 bytes) a415db71cfff218b1510f977a1478f66be5e9434cfb90fc00cffdb8364376d41 out/main/index.js (0.4.13 app logic) (167,654 bytes) Added 2026-07-17. The README's 2026-06-17 re-check block says "The 0.4.13 hashes are listed below" and describes this build; until today no 0.4.13 rows existed here, so a reader following that sentence found nothing. These are those hashes. Build identity read from package.json inside app.asar: "version": "0.4.13". Recomputed 2026-07-17. Independently reproduces the README's own 0.4.13 finding: the only code change from 0.4.12 is one line in pruneBridgeData (+49 bytes of index.js). --- 0.4.14 (acquired 2026-06-20) ------------------------------------------------- 24b64bc72d9c56095c7c92b331842a205be6dd3f23830dddab4a850f9f58dbd0 GSE Companion Setup 0.4.14.exe (81,296,884 bytes) 217ff61e074d421ed418f12d47f7f342c09eba9d8c15c4a5bc59fc746ff7229e app.asar (0.4.14, extracted statically) (file) 9c8c9588f7a749c81fb710de73e98899ca516f56cdb004fa82547315b5f0239d out/main/index.js (0.4.14 app logic) Native modules shipped (unchanged, stock packages): 36c2d44b9d7b284f393dd9cc425da5ca90511d90717914f7af5d432b2d3ff5dd cbor-extract node.napi.node d1a71f9ac1728082c1b276392725c3e010b98714888579b99152e401abedbf11 ps-list fastlist-0.3.0-x64.exe 017411f3b0b5c0402cc3b2cb87c32c6fc71abd82e5b17ea6108990096c75a65d ps-list fastlist-0.3.0-x86.exe Live server capture 2026-06-20: GET https://api.gse.tools/settings/access-policy -> {"enforce":false,"updatedAt":null} --- 0.4.15 (acquired 2026-06-20) ------------------------------------------------- d516415c9b1ff83c8d1796b071581ef76763511576999018de16076649224a02 GSE Companion Setup 0.4.15.exe (81,322,606 bytes) 2e734950eea97015bbf2e69f601da128f28e42de01735f1382033625add3b5e2 app.asar (0.4.15, extracted statically) 6b13343b4ab4218a37f68080f1bd1a0e0d37dc5c355b68c5dd21a408b806ffc4 out/main/index.js (0.4.15 app logic) (128,949 bytes) --- 0.4.16 (acquired 2026-06-20) ------------------------------------------------- 264013e8d6508a2cb5b04ac92f22ed5498a8dd38804b91e342ca7fadd1981026 GSE Companion Setup 0.4.16.exe (81,322,563 bytes) 84a72f8636c07f1821cba22ff85aae65c530442ae197bc6149922482c8131b70 app.asar (0.4.16, extracted statically) 5271373bd3de213973282172aa339002dc71c2c88fed39efb13249fbcb078cc2 out/main/index.js (0.4.16 app logic) (128,766 bytes) New dependency since 0.4.14: tweetnacl (ed25519 directive verification). Embedded ed25519 public key (unchanged 0.4.15 -> 0.4.16): b531cb8b505ae9752b5b789f26085853b0ba5da5d7e7e244975f0545430d683a Live server capture 2026-06-21: GET https://api.gse.tools/settings/access-policy -> {"enforce":false,"updatedAt":null,"integrity":"verified"} --- in-game GSE addon 3.3.22-12-gfb1946e-PatronBuild (files dated 2026-06-20) ---- fc6eea938f36222feb577f220108e55a01bbb9e29f1edc18300662c492fea748 GSE/API/Codec.lua (ChaCha20 cipher + DecodePackedMessage) (2,925 bytes) 6aaad9964db4d0af0194496bf05d90680288990fbb7d992b5212f488b1e81fb6 GSE/API/Plugins.lua (locked-proxy block) (5,490 bytes) ac2dffe2becbc9b44aa704c8f9655cc95c5a6b07b6e22e71d4eb6700ece5fce8 GSE/API/Serialisation.lua (!GSE3! / !GSE3!+ dispatch) (18,971 bytes) The encrypted !GSE3!+ format is decoded by the addon (key embedded in Codec.lua) but never encoded on the client; the Companion app rejects it. No !GSE3!+ data was present in the captured GSE SavedVariables on 2026-06-21. --- 0.4.20 (acquired 2026-06-28) ------------------------------------------------- 805d34d8ff6e3a54360546241935d24b21ca81484ff9feae97d91b40f917b274 GSE Companion Setup 0.4.20.exe (81,326,173 bytes) 41e427a5eca7c68f7f1e97b8475de9b8f67b6ae1dc7888e7019de731b2c9e43b app.asar (0.4.20, extracted statically) (6,202,665 bytes) 9d5d897585b7b85d6cd6befb70a2990a58dcf7ba4dd07e06bd02aa4e7f2492c9 out/main/index.js (0.4.20 app logic) (136,601 bytes) 0.4.20 generalized the unsigned diagnostic upload: it now reads server-specified arbitrary files under Interface\AddOns and WTF (any file, 4 MB cap, no "..") and POSTs their content to api.gse.tools/diagnostic/upload, triggered by a companion:request SSE push. --- 0.4.21 (acquired 2026-06-29) ------------------------------------------------- 341fb6212bb950e5d88f92112ede41dbaa06e84e44e4ada12fe76f85408fff73 GSE Companion Setup 0.4.21.exe (81,326,335 bytes) 23803e849fe6aaf0373c7c40a416b631ae14520c1627ce050fdd0270c41968f7 app.asar (0.4.21, extracted statically) (6,202,921 bytes) 12f5bd5231889ad6f9863b9c0f20aa3a327f14074c9a024d28dc1db8eee60e30 out/main/index.js (0.4.21 app logic) (136,857 bytes) 0.4.21 is a sync-notification dedup only. --- 0.4.22 (acquired 2026-07-01) ------------------------------------------------- 61015247508dc209ff3118cbd8842216ccd1c31c19dd94f9f80788c6ee1b665d GSE Companion Setup 0.4.22.exe (81,326,397 bytes) 27716e71c29d9403e0e225cec97f03995a864bf3f4855024e255ec21454cd6e1 app.asar (0.4.22) (6,203,376 bytes; = the INSTALLED app.asar, verified 2026-07-09) 56598af576046dc7c96ddcd401d96549032a3824d03f9a28aa19f86b78923a2b out/main/index.js (0.4.22 app logic) (137,312 bytes) 0.4.22 adds a BugGrabber/BugSack SavedVariables reader to the always-on gather, so their error-log content is attached to every diagnostic upload. The embedded ed25519 public key is unchanged (b531cb8b505ae9752b5b789f26085853b0ba5da5d7e7e244975f0545430d683a). The four GRIP-EMS identifiers are absent from 0.4.20/0.4.21/0.4.22 in 18 encodings tested. Live server capture 2026-07-09 (authenticated with the account token, and anonymous): GET https://api.gse.tools/settings/access-policy -> {"enforce":false,"updatedAt":null,"integrity":"verified"} A ~30-minute decrypted TLS capture on 2026-07-09 (WoW closed, GRIP-EMS present, two manual syncs) showed only GSE content sync: no companion:request directive, no PATCH/PUT/DELETE, no /diagnostic upload, restrictedAccount read-only, and no change to GRIP-EMS.lua on disk. Evidence file added 2026-07-09: 2e549b9ed5057936c1de2f1ff3f58fbba4d50004a6f54c36f7bbcd43bc017138 evidence/companion_0.4.22_main_beautified.js (178,366 bytes; js-beautify formatted copy of the 0.4.22 out/main/index.js, whose authoritative minified hash is 56598af5...b78923a2b above) --- 0.4.23 (acquired 2026-07-15) ------------------------------------------------- 394b68fd9be35a22a6f74f81948f38ec54489dfcf14386e0ddbe3d2c9d37f529 GSE Companion Setup 0.4.23.exe (81,326,323 bytes; UNSIGNED) f668f1223af9a47cd2e3443f5e792180c2fade793d03f5cee56f842d51f744d6 app.asar (0.4.23) (= the INSTALLED app.asar, verified 2026-07-15) 588a914dd3f5744ca47756366eca3b2c4f80ebf45c2c5f7f67b8370c09051e01 out/main/index.js (0.4.23 app logic) (136,361 bytes) v0.4.23 removed the client-side detection, the syncRestrictedAccountFlag PATCH, and integrityRef; policy:state now returns restricted:false hard-coded ("no client-side presence scan. Any account restriction is decided server-side."). RETAINED: the ed25519 engine (key b531cb8b...683a), the arbitrary-file capture + /diagnostic/upload, the BugGrabber/BugSack error-log gather, and the unsigned --force-run auto-updater. Live 2026-07-15: {"enforce":false,"updatedAt":null,"integrity":"verified"}. Aggregate: 1 of 3,747 member records carries restrictedAccount:true (identity not accessed). --- in-game GSE addon 3.3.24-1-g6337f05-PatronBuild (acquired 2026-07-15) ---- No competitor / GRIP / EMS / detection strings in any file. GSE.EncodeMessage writes plain !GSE3! (CBOR+base64); !GSE3!+ (ChaCha20) remains decode-only. Now also declares Interface 120100 (12.1.0). Inert with respect to competitor targeting. GSE Companion 0.4.24 (acquired 2026-07-17) GSE Companion Setup 0.4.24.exe D912618652C9CFDB3EFB5D23E9CD78ED6A3810F02DAD5F41A8546C0CF381D76D 81,326,455 bytes resources/app.asar (extracted from the installer) 0E1FD392E9BF84BEBCF60EC21531B8E4C364815C7EF87F3593B078CE8C141D0C 6,202,541 bytes out/main/index.js 26FD8635ED6F39ED2A51D8E1AC7BB67F3C9F384B52C72163DE808D3C20D3B0A9 136,477 bytes GSE addon 3.3.24-2-g7732fe5 (acquired 2026-07-17) - commit 7732fe5 "Restructure power user features" GSE-3.3.24-2-g7732fe5.zip (FREE build, 165 files) 435128B3251B41F0C1A421CDE8C9B5D8C3C87C4550CC652D4B749D6A49AF91D5 2,561,512 bytes GSE-3.3.24-2-g7732fe5-PatronBuild.zip (PATRON build, 168 files) 575196444D1FA7EA288867921AC7D3B4D19489E6575C1D4D26D7683C3F7FE795 2,570,462 bytes --- 0.4.26 (acquired 2026-07-17) ------------------------------------------------ c720ec821818fa2b58a4e50d71dbbd0c06c81c01ec573b5e2a4505554d0780d7 GSE Companion Setup 0.4.26.exe (81,327,286 bytes; UNSIGNED) c5e569a768acf03bfbe7fe8aa9a9d6a9c4a52f534fa913cc374f90534a57ac21 app.asar (0.4.26) (6,210,073 bytes; = the INSTALLED app.asar, verified 2026-07-17) db3f8f5c1d747d05c701cfb0e05538a065c90fbf14d51535b6e3ca882f53b7e3 out/main/index.js (0.4.26 app logic) (136,850 bytes) v0.4.26 REMOVED the server-triggered arbitrary-file capture. The `paths` field is no longer read (`.paths` 2 -> 0 occurrences); the recursive directory walker is deleted (`withFileTypes` 2 -> 1); `capture-denied` 1 -> 0 and `capture-` 3 -> 0; the 40,000-entry walk cap (`4e4`) 1 -> 0. The SSE `companion:request` else-branch now calls the gather with (requestId, kinds) only. `kinds` is a closed set of three flags (errorlogs / log / settings) - no branch treats a kind as a path - and the server path deletes `errorlogs` before gathering. File attachment is now user-driven: `report:submit` (ipcMain, source "in-app") -> userFilePaths -> single-call-site collector, tagged `userFile:`. New user controls: excludeMods, includeErrorLogs. NEW markers: userFile: 1, requestFiles 3, userFilePaths 4, excludeMods 4, includeErrorLogs 5, report:files-requested 1. RETAINED UNCHANGED: the ed25519 engine (key b531cb8b...683a, sign.detached.verify 1 site), the 0.4.24 write guard (/^GSE.*\.lua$/i), the engine `read` op with NO basename guard, the mandatory GSE-scoped gather (Po -> every GSE*.lua + GSE_Companion_Data.lua, server-triggerable, no prompt), and the unsigned --force-run auto-updater (fileWin-only asset selection, autoApplyUpdates default true, 426 out-of-band trigger, no digest/signature check anywhere). The four GRIP-EMS identifiers remain absent in plain/b64/hex/reversed. NOTE: no 0.4.25 was acquired; whether it released is unknown. --- in-game GSE addon 3.3.25 (acquired 2026-07-17) ----------------------------- ea15d65ba23f91eae0381b2302fabe41443829289c8cc6522dffa34c631c08eb GSE-3.3.25.zip (FREE build, 165 files) (2,561,801 bytes) a62bc47e28b3ae14a7781703a76963d66e7596747bd0b7960a894e704948ab85 GSE-3.3.25-PatronBuild.zip (PATRON, 169 files) (2,571,012 bytes) Changelog: #1979 restructure support requests, #1970 Restructure power user features, #1969 WoW 12.1 changes. vs 3.3.24-2: patron 168 -> 169; the single added file is `release.json`, a BigWigs packager manifest (packaging artifact, not code). Free unchanged at 165. Patron-only set otherwise identical (GSE_QoL x3), so the pay-gate structure of 3.3.24-2 is unchanged. 10 files differ; 5 are .toc version strings. Substantive: GSE_Options/Support.lua (+406 B), GSE/Localization/ModL_enUS.lua (+103 B), GSE_Utils/Patrons.lua (+741 B, patron name list). Support.lua adds an OPT-IN, DEFAULT-OFF checkbox for BugSack/BugGrabber error logs (`errorLogsCheck:SetValue(false)`) feeding `includeErrorLogs` in the submitted payload. This answers the 0.4.22 always-on error-log gather finding: no longer always-on, no longer server-reachable. Competitor scan (provenanceSource / gse-legacy / GRIP-EMS / GRIP_EMS / restrictedAccount / integrityRef / detectGrip / purgeGrip): 0 hits in BOTH builds, verified against a control (case-insensitive `grip` = 5 hits, all resize-grip UI comments). Codec unchanged: Serialisation.lua:8 writes plain "!GSE3!"; all !GSE3!+ occurrences are comparison/decode positions. Serialisation.lua, Codec.lua, Plugins.lua byte-identical to 3.3.24-2. Interface: 11508, 20506, 50504, 120007, 120100 (120100 first appeared in 3.3.24-1, NOT new in 3.3.25). --- GSE_Companion bridge addon (NOT new; present since at least 0.4.20) --------- Installed by the DESKTOP APP, not by any addon channel: `rs()` copies GSE_Companion.toc / Bootstrap.lua / GSE_Companion.lua out of resources/addon inside the Electron app into Interface\AddOns\GSE_Companion, then seeds GSE_Companion_Data.lua with `GSECompanionData = {}`. Verified: the three installed files are byte-identical to %LOCALAPPDATA%\Programs\gse-companion\ resources\addon\. Neither the free nor patron 3.3.25 zip contains the folder. Payload unchanged across 0.4.20 / 0.4.22 / 0.4.24 / 0.4.26 (Bootstrap.lua 260 B, GSE_Companion.lua 35,663 B). Bridge: inbound = app writes GSE_Companion_Data.lua, WoW loads it as a normal addon file on /reload; outbound = app reads GSE SavedVariables after WoW exits. GSE_Companion is on GSE's SUBMODULES allowlist (GSE/API/Init.lua:199) so it receives the real GSE table via pushGSEInto - the same name-keyed side door past the locked proxy that GSE_QoL uses. Lua-injection check: CLEAN. Every key/value passes through `co(String(e)).replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n")` - backslash-first ordering is correct and quotes are escaped, so bridge content cannot break out of its string literal. `\r` is unescaped (would yield an unfinished-string syntax error on exotic input) - a robustness edge, not a vulnerability. --- 0.4.27 (acquired 2026-08-06, characterised 2026-08-26) ---------------------- CORRECTION 2026-08-27. This header previously read "acquired on or before 2026-08-20". That was taken from the file's LastWriteTime, which for every installer in this set reads 20/08/2026 18:16 to 18:17 because that is when the whole folder was copied during a machine rebuild, not when anything was downloaded. CreationTime survived the copy and is the field this repository's acquisition record has always used: it reads 06/08/2026 01:37:56 for 0.4.27, and gives 10/06/2026 for 0.4.12 and 15/07/2026 for 0.4.23, which match their release dates. The old statement was not false, since 2026-08-06 is on or before 2026-08-20, but it rested on a timestamp that records a copy and it threw away precision that was available. Acquisition dates in this repository are my own machine's file metadata and are labelled as such; this one now uses the correct field. 73e805253017628e1dee6865ecb5f2c85ba64bd426988b038b1bc3921df8011f GSE Companion Setup 0.4.27.exe (81,327,641 bytes; UNSIGNED) d3a1cf027fdba74aedb5f00abd525ad7c80f46fd2e1f47253e6a90e6f3b8f4f3 app.asar (0.4.27, extracted statically) (6,211,562 bytes) 6d3bbc72eafbb58938a5b912ca0a6a3851cdb0edb095b291cd0257d1a2da958e out/main/index.js (0.4.27 app logic) (138,339 bytes) --- 0.5.3 (acquired 2026-08-24, characterised 2026-08-26) ----------------------- a00f4dc3d2eb12d1913dacadac78bc2a0169966359855a3d22c1a1a25237e3dd GSE Companion Setup 0.5.3.exe (81,335,293 bytes; UNSIGNED) 2b98b0041ca4787ffb9cb067a575dcc3f3673b185d09644cfd91985121373ddd app.asar (0.5.3, extracted statically) (6,255,817 bytes) 6c53500dcae3975db8ba679a804d557cd4e7e2c2fc342e9b83c20268bf73376c out/main/index.js (0.5.3 app logic) (146,566 bytes) Both builds read statically: NSIS installer -> app-64.7z -> resources/app.asar -> out/main/index.js. Build identity taken from package.json inside app.asar ("version": "0.4.27" and "0.5.3"). Declared dependencies are identical in both and unchanged from 0.4.26: @qikdev/sdk, adm-zip, cbor-x, luaparse, ps-list, tweetnacl. Every competitor-facing marker reads ZERO in both: the four GRIP-EMS identifiers (and a case-insensitive search for "grip" anywhere in index.js), syncRestrictedAccountFlag, detectGripEmsAcrossClients, purgeGripCharSequences, runAccountCleanup, integrityRef, restrictedAccount, .paths, capture-denied and the 4e4 walk cap. RETAINED UNCHANGED in both, at the same counts published for 0.4.26: the ed25519 engine (key b531cb8b...683a, sign.detached.verify 1 site), the 0.4.24 write guard (/^GSE.*\.lua$/i, 2 occurrences, and the "write refused" string), the BugGrabber/BugSack gather (/^!?Bug(Grabber|Sack)\.lua$/i), the user-driven report path (userFile: 1, requestFiles 3, userFilePaths 4, excludeMods 4, includeErrorLogs 5), and the unsigned --force-run auto-updater with autoApplyUpdates present. Full table: UPDATE-2026-08-26-platform-actions-and-current-builds.md. SCANNING CAVEAT, recorded because it nearly produced a false finding: the error-log gather is written as the alternation /^!?Bug(Grabber|Sack)\.lua$/i, so the literal strings "BugGrabber" and "BugSack" do NOT occur in index.js even when the capability is fully present. Counting the literal returns 0 and reads as a removal. Count the regex. Second caveat: the minifier reassigns single-letter identifiers between builds. In these two, Ao is the /^GSE.*\.lua$/i regex and Io is the Bug(Grabber|Sack) regex, which is the opposite of the naming in the v0.4.24 quote in README.md. Match on the regex literal and the error string, never on the variable name. --- installer hash re-verification, 2026-08-26 --------------------------------- Every Companion installer hash published above was recomputed against the file on disk. MATCH: 0.4.12, 0.4.13, 0.4.14, 0.4.15, 0.4.16, 0.4.20, 0.4.21, 0.4.22, 0.4.23 (9 of 11). MISMATCH: none. NOT RE-CHECKABLE: 0.4.24 and 0.4.26. Neither installer is still held, so the hashes published for them on 2026-07-17 stand on that date's recompute and could not be re-verified today. CORRECTION 2026-08-27. The three lines above previously read "(9 of 10)" and named 0.4.26 alone as not re-checkable. Both were wrong. ELEVEN Companion installer hashes stood in this file before the 2026-08-26 pass, not ten, and TWO of those eleven are no longer held. The eleven are 0.4.12, 0.4.13, 0.4.14, 0.4.15, 0.4.16, 0.4.20, 0.4.21, 0.4.22, 0.4.23, 0.4.24 and 0.4.26, and they can be read back out of this repository's git history at the commit preceding that pass. The same pass added 0.4.27, 0.5.3, 0.4.19 and the 0.4.17 / 0.4.18 pair, whose hashes were computed for the first time rather than re-checked, so they sit outside this count and outside the nine. The count was produced by a script that located each published hash and then looked for a filename on the SAME LINE. Every entry in this file puts the two together on one line except the 0.4.24 block, which puts the filename on its own line above the hash. That entry was therefore skipped in silence and never appeared in the totals, as a miss rather than as an error. No hash changed and no comparison failed; nine matched and none mismatched, before and after. What was wrong was the denominator and the list of what could not be checked. Recorded rather than quietly amended, because a file whose purpose is verification cannot correct its own verification claims invisibly. The same class of mistake is described in the SCANNING CAVEAT above: a scan finds only the shape it encodes. That caveat was written on this same date, about a different scan, and then not applied to this one. Two installers held but not named above, recorded for completeness: 743b816e9ad2beecda463a3264fc7623643e628f2ed467f4aa994e155fb72d08 GSE Companion Setup 0.4.19.exe (81,325,163 bytes) 978cc99a5f101072542070b0e031fb92247f9b047511acfbb6d9890373e156ef GSE Companion Setup 0.4.17.exe AND 0.4.18.exe (81,324,864 bytes each) The 0.4.17 / 0.4.18 pair share one hash, independently reproducing the finding already recorded in UPDATE-2026-07-17-v0.4.17-v0.4.19.md: the installer distributed as 0.4.17 is byte-identical to the one distributed as 0.4.18. No 0.4.17 build was ever acquired. --- a note on what a reader can and cannot check here --------------------------- Of the SHA-256 values in this file, exactly one names a file inside this repository: evidence/companion_0.4.22_main_beautified.js. Every other value names an external binary (an installer, an extracted app.asar, an index.js, or an addon zip) that is not distributed here, so a reader cloning this repository cannot reproduce it without obtaining that binary independently. That has always been true and is stated now rather than left to be discovered. The one in-repository hash is computed over LF bytes, and since 2026-08-26 a .gitattributes pins eol=lf so that it reproduces on every platform.