# Leaked seed phrase: why one sentence on a web page is the whole wallet

Published: 2026-11-12 · Updated: 2026-11-03 · By HackerGPT Team
Canonical: https://hackergpt.org/blog/leaked-seed-phrase-nft-takeover/

> In CyberGym's NFT Takeover challenge, a 12-word phrase posted on a public page is enough to control the wallet holding the shop's token. Why a seed phrase is the wallet, how the challenge was found, and how to keep secrets out of your own site.

**TL;DR:** A seed phrase is not a password to a wallet; it *is* the wallet. Under BIP-39 and BIP-32 the same 12 words always produce the same private keys, so anyone who reads them controls every address derived from them, with no reset and no second factor. CyberGym's NFT Takeover challenge makes the point with a phrase posted by accident on a public page.

This article is for learners working through OWASP Juice Shop and for anyone who publishes content to a website or repository. You will see how the phrase was found with nothing but careful reading, why those words alone are enough, and how to keep secrets of any kind out of what your site publishes. Test only applications you own or have written permission to test; [CyberGym](https://cybergym.hackergpt.app), our hosted Juice Shop instance, is built for practice, and its wallet is a planted training wallet.

[Watch on YouTube: CyberGym Challenge: NFT Takeover](https://www.youtube.com/watch?v=CxTNy9iYkOc)

## What is the NFT Takeover challenge?

It is a two-star challenge in the *Sensitive Data Exposure* category of [OWASP Juice Shop](https://owasp.org/www-project-juice-shop/). The [companion guide](https://pwning.owasp-juice.shop/companion-guide/latest/part2/sensitive-data-exposure.html) states it as "Take over the wallet containing our official Soul Bound Token (NFT)", with one hint: "Find the seed phrase posted accidentally."

A soul-bound token is an NFT that cannot be transferred. [ERC-5192](https://eips.ethereum.org/EIPS/eip-5192) defines a minimal interface for them, where a token reports itself as locked to its owner's address. So the challenge is not to move the token. It is to prove you control the address that holds it.

Two stars is fair. There is no smart-contract bug and no injection. The whole challenge is reconnaissance plus one fact about wallets.

## Where was the seed phrase on CyberGym?

It was on the About Us page, in a slide no one reads closely. The tester did not start by guessing endpoints. They opened the side menu and read each page in turn: customer feedback, the GitHub link, the photo wall, the FAQ, then About Us. About Us ends with a Customer Feedback carousel, and one of its one-star posts asked the shop to send its chatbot NFT to the poster's wallet. It named an in-app page, `/#/juicy-nft`, right next to it sat twelve words joined by hyphens, and it was signed by a masked address ending `ereum@juice-sh.op`.

That is how this kind of leak looks in practice: not a file called `secrets.txt`, but a customer comment in a place that looks harmless. We will not reproduce the words here. They are a training wallet's phrase, but printing a seed phrase, even a planted one, normalises the habit this article argues against.

The `/#/juicy-nft` page showed the Juicy Chatbot SBT and its owner, `8343D2`. Before the challenge is solved, the page asks for the wallet's private key and has a button to authenticate with it. It also carries the warning that every wallet repeats: never reveal your private key or seed phrase.

One observation from the run: CyberGym is a shared instance, so the page was already in its solved state. Instead of the key field it showed the full account address and a note that the token is non-transferable. Juice Shop records solved challenges on the instance, not per visitor. That does not stop you from working the method and checking your result.

## Why is a seed phrase the whole wallet?

Because every key in the wallet is calculated from it, by published rules that anyone can run. There is nothing else to steal.

- **[BIP-39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki)** turns random bits into words from a fixed 2,048-word list. Twelve words carry 128 bits of entropy plus a 4-bit checksum. The words are then stretched with PBKDF2-HMAC-SHA512, 2,048 rounds, using `"mnemonic"` plus an optional passphrase as the salt, into a 512-bit seed.
- **[BIP-32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)** turns that seed into a master key and a tree of child keys. A wallet is that tree.
- **[BIP-44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)** fixes the path through the tree: `m / purpose' / coin_type' / account' / change / address_index`. Ethereum's coin type is 60 in the [SLIP-44 registry](https://github.com/satoshilabs/slips/blob/master/slip-0044.md), so the first Ethereum address of a wallet sits at `m/44'/60'/0'/0/0`.

![A redacted 12-word phrase derives a seed, a BIP-44 Ethereum path, then the private key and address](https://hackergpt.org/blog/leaked-seed-phrase-nft-takeover/seed-to-wallet.webp) *Each arrow is a published, deterministic standard. Nothing in the chain asks who is holding the words.*

Run those steps on the same words and you get the same private keys and addresses, on any computer, forever. That is the feature: you can restore a lost wallet from paper. It is also why a leak cannot be undone. There is no server to reset the phrase. The only remedy is to move what you can to a new wallet before someone else does.

An optional BIP-39 passphrase adds a factor that is not written with the words. Without it, the twelve words are the only secret.

## How was the takeover confirmed?

By deriving the addresses from the phrase and matching one against the token's owner. The tester chose Ethereum because the `ereum` signature on the post and the token both pointed to it. They derived the first few addresses on the standard Ethereum path, and the first one matched the owner address shown on `/#/juicy-nft`, which starts `0x8343` and ends `Ce05`. Entering the derived private key into the page's form is what normally marks the challenge solved. Because the shared instance already showed it as solved, the address match and the scoreboard entry were the confirmation in this run.

In the video the derivation was done with a web-based converter, and the tester's own search results warned against exactly that. For this planted training phrase it does no harm. For any real phrase, typing it into a website hands it to that website. If you need to derive keys, do it offline, with a wallet library you trust, on a machine you control. The safer habit for this challenge is the same.

Working through a challenge like this with every step explained is what HackerGPT's [CTF Mode](https://hackergpt.org/features/ctf-mode/) does, and the video ends with HackerGPT working the same challenge, without narration. It grepped the site's JavaScript bundle for the hidden `/rest/web3/` routes, opened `/#/juicy-nft`, took the phrase by its own account from a community write-up of the challenge (the run does not show it reading the About Us page), derived the key and sent it to `POST /rest/web3/submitKey`. The server answered "Challenge successfully solved", and HackerGPT confirmed it through `/api/Challenges`. The [CTF Mode field guide](https://hackergpt.org/docs/ctf/) shows the workspace on Juice Shop.

## How do I keep secrets off my own site?

Treat everything your site publishes as public forever, and scan it the way an attacker would read it. The weakness here is [CWE-200, Exposure of Sensitive Information to an Unauthorized Actor](https://cwe.mitre.org/data/definitions/200.html). The [OWASP Secrets Management Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html) covers how to keep keys and tokens out of code and content to begin with.

1. **Search content, not only code.** CMS pages, testimonials, banners, alt text, uploaded images and PDFs all ship to visitors. The phrase in this challenge lived in page copy.

2. **Look for seed-phrase shapes.** Twelve to twenty-four short lowercase words in a row, joined by spaces or hyphens, rarely appear in normal prose. A rough check over your own build output or content export:

   ```bash
   # Run on your own project. Matches 12-24 runs of 3-8 letter words.
   grep -rnoE '\b([a-z]{3,8}[ -]){11,23}[a-z]{3,8}\b' dist/
   ```

   It will flag some ordinary sentences too. Read each hit; anything that looks like a list of unrelated words is worth a second look.

3. **Scan history as well as the current tree.** A secret deleted in a later commit is still in the repository. Secret scanners that read git history, such as Gitleaks or TruffleHog, catch keys and tokens a grep will not.

4. **Check screenshots and photos.** A picture of a note, a hardware wallet card or a terminal can leak as much as text.

5. **Read your own site with an outsider's eyes.** The habits from our guide to [OSINT on your own company](https://hackergpt.org/blog/intelligence-gathering/) apply directly: list what is public, then ask what an attacker could do with each item.

## What should I do if a seed phrase leaks?

Assume the wallet is already lost and move fast:

- Create a **new wallet** with a new phrase, on a device you trust.
- Move every asset you still can from the old addresses to the new ones. Transferable tokens and coins can move. A soul-bound token, by design, cannot, so its owner address stays exposed.
- Remove the phrase from wherever it was published. That limits new readers but does not undo the leak; caches, archives and scrapers may already have it.
- Revoke token approvals the old addresses granted, so a contract cannot be used to pull funds later.

CyberGym's own wallet shows why speed matters. Its explorer history, traced in our [crypto wallet OSINT walkthrough](https://hackergpt.org/blog/crypto-wallet-osint-ctf/), ends with someone using the public key to delegate the account to code that forwards every new deposit elsewhere.

For a company the same logic applies to API keys and signing keys: rotate first, clean up second. Our [vibe-coded app security checklist](https://hackergpt.org/blog/vibe-coded-app-security-checklist/) starts with secrets in the client bundle for that reason.

## Key takeaways

- A seed phrase is the wallet. Anyone who has the words can derive every key, and there is no reset.
- Leaks hide in harmless-looking content: a banner, a testimonial, a screenshot. Read your own pages the way an attacker would.
- Never paste a real seed phrase into a website. Derive keys offline, if at all.
- Scan built output and git history for secrets, not only the current source tree.
- If a phrase or key leaks, move assets and rotate before cleaning up the post.

## FAQ

### What can someone do with my seed phrase?

Everything you can. The phrase deterministically produces every private key in the wallet under BIP-39 and BIP-32, so anyone holding it can sign transactions from every derived address. Unless you also set a BIP-39 passphrase they do not have, nothing else stands in the way.

### Can a leaked seed phrase be changed or reset?

No. The keys are calculated from the words, so there is nothing to reset. The only protection is to create a new wallet and move assets to it before someone else moves them.

### Why does a 12-word phrase work for Ethereum addresses?

BIP-39 turns the words into a seed, BIP-32 turns the seed into a key tree, and BIP-44 picks the branch. Ethereum's branch is coin type 60, so its first address is at `m/44'/60'/0'/0/0`. The same words also produce keys for other chains on their own branches.

### Is the NFT Takeover challenge a smart contract exploit?

No. The challenge needs no contract bug. It is information disclosure: a seed phrase posted on a public page. Finding it is reconnaissance, and proving ownership is matching the derived address to the token's owner.

### Is it safe to use an online seed phrase converter?

Not with a real phrase. Anything you type into a website can be recorded, and a seed phrase gives full control of the wallet. Use one only with a throwaway or training phrase, and derive real keys offline with software you trust.

## Sources

- [Pwning OWASP Juice Shop: Sensitive Data Exposure (NFT Takeover)](https://pwning.owasp-juice.shop/companion-guide/latest/part2/sensitive-data-exposure.html)
- [OWASP Juice Shop project](https://owasp.org/www-project-juice-shop/)
- [BIP-39: Mnemonic code for generating deterministic keys](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki)
- [BIP-32: Hierarchical Deterministic Wallets](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)
- [BIP-44: Multi-Account Hierarchy for Deterministic Wallets](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)
- [SLIP-44: Registered coin types for BIP-0044](https://github.com/satoshilabs/slips/blob/master/slip-0044.md)
- [ERC-5192: Minimal Soulbound NFTs](https://eips.ethereum.org/EIPS/eip-5192)
- [CWE-200: Exposure of Sensitive Information to an Unauthorized Actor](https://cwe.mitre.org/data/definitions/200.html)
- [OWASP Secrets Management Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html)

Practise reconnaissance on [CyberGym](https://cybergym.hackergpt.app), or check what your own site publishes with [HackerGPT](https://hackergpt.app).
