Bicrypto 6.8.1
21 September 2026
This release has upgrade notes. Read them before updating — they describe behaviour changes that need your attention.
Core v6.8.1
Release Date: September 21, 2026 Tags: PERFORMANCE, BACKEND, SECURITY, UPDATES, ADMIN, AUDIT, DEPOSITS, AI INVESTMENT, ACCOUNTS
Overview
A performance release, and a large one. An anti-debugging measure in the protected build re-armed itself every four seconds in every backend process and ran until it exhausted the stack — synchronously, so nothing else on the server ran while it did. It has been doing this on every install, at idle, since the protection was introduced.
Measured on a staging server with no user traffic at all: the web, trading and cron processes each burnt 70-90% of a CPU core — about 2.3 of the box's four cores — and the backend was stalled for 3.2 seconds out of every 4. A settings request that should answer in 5ms answered in 119ms, with repeated three-and-a-half second pauses, while the database sat completely idle. After this release the same box idles at 2-7% per process and serves 104 requests a second at a 99th-percentile of 93ms; before, seven requests a second produced six- to eight-second responses.
This costs you one anti-debugging layer, deliberately. See Upgrade Notes.
It also carries the fixes from the evening it was cut. An update that cannot land is now refused with nothing changed instead of half-applied and reported as a success; the admin audit trail records the administrator's address instead of the proxy's; three separate AI-investment doors that could pay a principal back twice now check first; and 306 places that answered their own refusals as server errors now answer them as what they are.
Update Instructions
pnpm updatorThere is no schema change in this release — no new table, no seeder, and
nothing to run by hand. Almost everything is in the compiled backend and arrives
with the restart; the spot-deposit screen change is in the browser bundle and
arrives with the frontend rebuild that pnpm updator runs.
Upgrade Notes
Your server has been doing this since you installed it, and it is worth re-checking capacity
- Nothing is required of you. This is here because the effect is large enough that decisions you made because of it deserve a second look.
- If you added CPU, moved to a bigger plan, or split the backend across processes because the platform was slow or the load average was high, re-measure before you keep paying for it. Idle CPU on the measured box fell from ~2.3 cores to under a tenth of one.
- If your logs are full of
event loop stalledwarnings, or requests that are slow while your database shows nothing waiting, those were this. They should stop. - The effect scales with process count, so an install running the backend, trading and cron processes separately gets the largest share of it back.
One anti-debugging layer has been removed, on purpose
- The measure that caused this deterred someone attaching a debugger to the running backend. It is not what enforces your licence, and it is not what protects the code from being copied.
- The layers that do that are untouched and were verified working after the change: the obfuscation itself, the integrity hashes over the shipped files, the code signing, and the licence gate that runs on requests.
- It is not being replaced with a lighter version of itself. The technique only works by blocking the thread it runs on, which is the entire problem on a server; there is no setting that makes it cheap.
Added
An install its provider updates can refuse the panel's update button
- Added
VENDOR_MANAGED_UPDATES="true", an.envswitch that closes the download-and-extract door with a 403 naming who applies updates on that install. Checking for updates still works, so you can still see what is available and ask for it. Unset — the default — changes nothing. It is for installs where a provider builds and applies the release: two release channels writing to one tree is how an update half-applies.
Changed
The updater refuses an update it cannot apply, and checks the one it did
- Changed the extractor to preflight every path an archive will write and REFUSE with the tree untouched if any of them cannot be written — better than a rollback, which is itself a write path and fails on exactly the permissions that made it necessary. The refusal names the blocked paths, the errno and the account the update runs as.
- Changed the success report to mean something: every file the extractor
claims to have written is re-read from disk and checked for size before the
update is called successful. adm-zip returns
truefor writes it declined to make, so its own account of itself cannot be the last word. - Changed "Extraction failed (37 errors)" — a count nobody can act on — to a sentence naming the paths and what blocked each one.
Fixed
The backend spent most of its time defending itself from a debugger nobody was running
- Fixed by removing the anti-debugging measure from the thirteen protected files that carried it. Each one carried its own copy and its own four-second timer, so the stalls overlapped into one near-continuous block across the whole process. Covered in Upgrade Notes.
The admin audit trail recorded the proxy instead of the person
- Fixed the audit trail, which was handed the socket peer. Every production
install puts a web server in front of the backend on loopback, so every row
in the admin audit log said
127.0.0.1: every approved withdrawal, every KYC decision, every account deletion, attributed to the machine. The address the rate limiter and the country rules already use is now what the record shows. Existing rows cannot be recovered; new ones name the caller.
A handler's own refusal came back as a 500
- Fixed 306 places across 226 routes where a deliberate refusal — "wallet not found", "market has open trades" — was caught and rethrown as a 500. The caller was told the server had broken when it had not, the internal message was pasted into the customer-facing text, and the log filled with stack traces for ordinary conditions. One of them printed a full stack every time somebody opened the withdraw screen for a coin they do not hold.
Deleting a market failed on any install without the AI Market Maker addon
- Fixed the bulk delete, bulk permanent delete and bulk restore of ecosystem and futures markets, which reached the market-maker guard through an import that simply is not present unless that addon is installed. All three died with a raw "Cannot find module" before a single row was read. The check is skipped when the addon is absent — with no market maker there is no funded pool to strand — and any other failure still refuses the delete.
- Fixed the single-market delete, which never had the guard at all and hardcodes force, so the protection could be walked around by deleting markets one at a time. Its copy-trading check also swallowed its own refusal: the catch rethrew only errors that did NOT mention copy trading, and the refusal's wording is "... open copy trading trades".
A spot deposit that never arrived told the customer it had failed
- Fixed the end of the deposit watch. The live poller only follows a deposit for thirty minutes; every declared deposit that is never sent ends that way, and it was reported as an error — two lines in the log per deposit, and "Verification error: Transaction not found" pushed at any customer still on the page, about a row that is still pending and still being checked. The screen now says the page has stopped watching and the deposit is still being checked automatically.
Security advisories asked about no version at all
- Fixed the advisory check, which walked a path back from a file that ships
compiled into
dist/and landed somewhere with no manifest, so it reported a null version on every install in the field.
Deleting AI investments could pay their principal back twice
These doors ship with the AI Investments add-on (6.2.1).
- Fixed the admin bulk delete, which checked whether an investment's principal had already been returned on one read and refunded on another, so a settlement that committed in between was paid again. Each investment is now locked, checked and refunded inside one transaction.
- Fixed bulk Restore, which runs through the same door and refunded every selected active investment — a restore that moved nothing except money.
- Fixed the customer's own cancel, and the admin single delete, refunding a principal that another path had already returned. An investment still marked active is no longer taken as proof the principal is still out.
A spent account-deletion link could still sign the account out everywhere
- Fixed by answering an already-used link before anything else happens. It previously ended every session on the account and, if the account had an open order, told the holder to cancel it and "use this link again" — for a link that could no longer delete anything.
An administrator could switch off their own two-factor authentication
- Fixed by resolving the target account once and using that row from then on. A trailing space in the account id selected the administrator's own row while the "not yourself" check compared two different strings.
Signing in at a differently-cased address signed you in to nothing
- Fixed the login response, which decided whether to send the new session on the address as typed rather than the route that matched — so a request to a differently-capitalised login address was accepted and then returned no session.