Production API Credentials Hardcoded in Public Sample Code
The Risk
The exchange published a sample script that was supposed to teach developers how to call its API. The keys inside that sample were not test keys, they were real working credentials for a live customer account. Anyone reading the documentation could view balances on that account, see its withdrawal history, see the saved withdrawal address book, cancel its open orders, and place fresh trades using its money. The keys had been sitting in a public repository for a long time before this report.
The Vulnerability
The exchange's official API documentation repository on a public code-hosting platform contained a sample script that included a working API key and matching secret hardcoded as Python string literals. They were named in a way that suggested a test or demo account, but they authenticated cleanly against the production exchange API and returned data and actions that should only be available to the account owner.
The Attack
The credentials are taken directly from the public sample. Authentication uses an MD5 sum over the form body, which the documentation itself describes.
SIGN=$(python3 -c "import hashlib; \
print(hashlib.md5(b'api_key=<KEY>&secret_key=<SECRET>').hexdigest().upper())")
curl -s -X POST https://[redacted-host]/api/private/account \
-H "X-API-SITE-ID: " \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "api_key=<KEY>&sign=$SIGN" The response was HTTP 200 with a large object containing balances across roughly 991 assets.
Confirmed Read Access
- Account balances across all assets
- Withdrawal history with transaction hashes and destinations (14 records observed)
- Saved withdrawal address book including user-supplied labels (46 entries observed)
Confirmed Write Access
cancelallordersucceeded with code 0- A limit order was placed and then cancelled, demonstrating the full trading lifecycle was reachable
The withdrawal endpoints appeared blocked server-side during testing, which limited direct fund theft. Trading write access remained available, and unauthorized trades alone are sufficient to cause financial loss through wash trading, market manipulation, or simply draining via paired-order fills.
The Impact
Anyone who reads the public documentation has the equivalent of an account API key for a real production account. The risk is not theoretical, the credentials are operational and tested. Even with withdrawals disabled, an attacker can move the account's balances against unfavorable orders, dump positions, or use the account to make the order book look thinner or thicker than it really is. The saved address book and withdrawal history also provide a directly identifying trail of where this customer sends funds.
Remediation
- Immediately revoke the exposed credentials at the API key management layer.
- Replace the keys in the sample script with placeholders such as
YOUR_API_KEY_HEREand add a clear comment explaining users must supply their own. - Scrub the credentials from git history and rotate any tokens derived from them.
- Audit account activity during the exposure window for unauthorized trading or order patterns.
- Enable secret scanning on the documentation repository and add a pre-commit hook that blocks values matching the API key format.
- Review every other public sample repository for the same anti-pattern.