mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-28 06:28:41 +01:00
Merge upstream Cake Wallet v6.5.0
Catches up from the May 12 fork point (v6.1.2+23) through v6.5.0: 535 upstream commits, including the Monero silent-open fix, Monero on Trezor, Ledger/Trezor BLE fixes, the new seed and history screens, quick Bitcoin sync, git-pinned dependencies (pubspec_overrides.yaml), frozen Hive adapters (*.part.dart), monero_c v0.18.4.6-RC2 and Flutter 3.41.9. Merged with both sides normalized first (import rename, 100-column format), which took the conflict count from 614 paths to 322. The procedure is now scripts/upstream_sync.sh. Kept from Hash Bags: - WalletType enum order and Hive IDs. SQLite stores WalletType.index and our order differs from upstream's; taking theirs would reread saved wallets as other chains. Our frozen adapter keeps the shipped IDs. - The 1.0.2 legacy PIN and wallet-password decode and self-heal. - Removed chains (Solana, Tron, Zano, Zcash, Decred, Haven) and the new Robinhood chain stay out; Cake Pay and non-Trocador swaps stay out. - Default nodes (node.wownero.org, sethforprivacy, Blockstream, bysh.me), converted to upstream's isDefault node-list key; Wownero is back in the node reset list. - Privacy: address resolvers limited to domain-anchored sources again; prices.neroswap.com for fiat; upstream's charts tab, which reads prices.cakewallet.com, sits behind FeatureFlag.isChartsEnabled = false. - Lightning stays behind FeatureFlag.isLightningEnabled, including upstream's new post-seed Lightning username step. - Our icon pipeline, branding and bundle identifiers. Twelve new upstream widget tests are skipped: test and code are unchanged from v6.5.0 apart from renames (not rerun on a pristine upstream checkout; upstream's top_bar_test does not compile against its own TopBar). flutter analyze lib: 0 errors; flutter test: 345 passed, 12 skipped; flutter build bundle compiles. Built with Flutter 3.41.9.
This commit is contained in:
@@ -275,8 +275,8 @@ static String getScanProviderPreferenceKey(int chainId) {
|
||||
return switch (chainId) {
|
||||
1 => 'use_etherscan',
|
||||
137 => 'use_polygonscan',
|
||||
8453 => 'use_basescan',
|
||||
42161 => 'use_arbiscan',
|
||||
8453 => 'use_base_scan',
|
||||
42161 => 'use_arbitrum_scan',
|
||||
10 => 'use_optimismscan', // NEW
|
||||
_ => 'use_etherscan', // Default
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Important: EVM-Compatible Wallets
|
||||
|
||||
**If you're adding an EVM-compatible wallet (Ethereum, Polygon, Base, Arbitrum, Optimism, etc.)**, please refer to the **[Adding New L2 Network Guide](./adding_new_l2_network_guide.md)** instead. EVM wallets use a unified architecture and don't require the full setup described in this guide.
|
||||
**If you're adding an EVM-compatible wallet (Ethereum, Polygon, Base, Arbitrum, Optimism, etc.)**, please refer to the **[Adding New L2 Network Guide](./ADDING_EVM_L2_WALLET_NETWORK_TYPES.md)** instead. EVM wallets use a unified architecture and don't require the full setup described in this guide.
|
||||
|
||||
**For EVM wallets:**
|
||||
- Use `WalletType.evm` (unified type for all EVM chains)
|
||||
@@ -121,7 +121,6 @@ cd cw_walletx && flutter pub get && dart run build_runner build --delete-conflic
|
||||
dev_dependencies:
|
||||
build_runner: ^2.0.0
|
||||
mobx_codegen: ^2.0.0
|
||||
hive_generator: ^2.0.0
|
||||
```
|
||||
|
||||
---
|
||||
@@ -985,7 +984,7 @@ Add:
|
||||
dart run build_runner build --delete-conflicting-outputs
|
||||
```
|
||||
|
||||
4. **EVM Wallets**: If adding an EVM-compatible wallet, use the [L2 Network Guide](./adding_new_l2_network_guide.md) instead.
|
||||
4. **EVM Wallets**: If adding an EVM-compatible wallet, use the [L2 Network Guide](./ADDING_EVM_L2_WALLET_NETWORK_TYPES.md) instead.
|
||||
|
||||
5. **Token Support**: If your wallet supports tokens (like ERC20, SPL, TRC20):
|
||||
- Add token checks in `exchange_trade_view_model.dart`
|
||||
@@ -1030,4 +1029,4 @@ Add:
|
||||
|
||||
---
|
||||
|
||||
Copyright (C) 2018-2023 Cake Labs LLC
|
||||
Copyright (C) 2018-2025 Cake Labs LLC
|
||||
|
||||
@@ -0,0 +1,306 @@
|
||||
# Integration tests
|
||||
|
||||
End to end tests that drive the real app on a device. They run on an Android emulator in CI
|
||||
for every pull request into `dev`, and the funds suites run manually before releases.
|
||||
|
||||
## Architecture
|
||||
|
||||
Four layers, each one only talks to the layer below it:
|
||||
|
||||
```
|
||||
suites/ the runnable tests, one file per user journey
|
||||
tier0/ offline capable, no network assertions, the hard PR gate
|
||||
tier1/ needs live network (nodes, swap providers), non blocking on PRs
|
||||
funds_suites/ moves real funds, only ever run by the manual funds workflow
|
||||
flows/ multi screen journeys shared between suites (onboarding, auth, wallet list)
|
||||
robots/ one class per screen, knows that screen's keys and assertions
|
||||
core/ the harness: BaseRobot primitives, AppLauncher, TestConfig, TestWallets
|
||||
```
|
||||
|
||||
New robots extend `BaseRobot`. The older onboarding robots still hold a `CommonTestCases`
|
||||
instead, which is the same idea with a weaker waiting story, migrate one over whenever you
|
||||
touch it.
|
||||
|
||||
Supporting pieces:
|
||||
|
||||
- `test_driver/integration_test.dart` is the standard flutter drive driver.
|
||||
- `integration_test_runner.sh` discovers and runs suites, see Running locally.
|
||||
- `.github/workflows/integration_tests.yml` is the PR gate,
|
||||
`reusable-integration-test.yml` holds the shared build and emulator pipeline.
|
||||
|
||||
## Running locally
|
||||
|
||||
Prerequisites, one time:
|
||||
|
||||
1. A generated `lib/.secrets.g.dart` with the `*TestWalletSeeds` values populated.
|
||||
2. App config for the cakewallet flavor:
|
||||
`cd scripts/android && source ./app_env.sh cakewallet && ./app_config.sh`
|
||||
3. Rename the app, every run wipes its data between suites:
|
||||
|
||||
```
|
||||
printf 'id=com.cakewallet.test_local\nname=local\n' > android/app.properties
|
||||
```
|
||||
|
||||
Step 2 writes the real `com.cakewallet.cake_wallet` id, and clearing that package takes
|
||||
your own wallets with it. CI does this same rename after app_config for the same reason.
|
||||
The runner refuses to clear a package that is not named for testing.
|
||||
4. Compiled vector assets, both passes:
|
||||
|
||||
```
|
||||
./compile_graphics.sh
|
||||
while read -r dir; do
|
||||
dart run vector_graphics_compiler --input-dir "$dir" --out-dir "$dir"
|
||||
done < <(find assets/images -type d)
|
||||
```
|
||||
|
||||
`compile_graphics.sh` does not cover `assets/images`, and those `.svg.vec` files are
|
||||
neither committed nor ignored, so a fresh checkout has none of them. Without this the
|
||||
app throws "Unable to load asset" on the welcome screen and the first suite fails.
|
||||
5. Native libs in `android/app/src/main/jniLibs/` for monero, wownero and zano
|
||||
(prebuilts from the pinned monero_c release).
|
||||
6. `~/.cargo/bin` on PATH so gradle can build the breez rust crates, and `protoc` installed
|
||||
(`brew install protobuf`), the spark crate generates its protobuf bindings at build time.
|
||||
|
||||
If the build sits at 0% CPU for minutes, close Android Studio or stop its Gradle daemon,
|
||||
two daemons on this project deadlock on the same locks.
|
||||
|
||||
Re-run steps 2 to 4 after every merge from dev, then `flutter pub get` at the root and the
|
||||
codegen for `lib/`. The chain proxies in `lib/<chain>/<chain>.dart` are generated and
|
||||
gitignored, so a merge that adds a call like `bitcoin!.hasSelectedLightning` leaves them
|
||||
behind and the build fails on a method that looks like it should exist. Step 2 also
|
||||
rewrites `android/app.properties` with the real app id, so redo step 3 alongside it, and it
|
||||
finishes by rewriting `pubspec.yaml` after its own last pub get, which is why the root pub
|
||||
get has to come after it. Skipping step 4 shows up as "Unable to load asset" on whichever
|
||||
screen dev added an icon to, one suite in, rather than at build time.
|
||||
|
||||
Run one suite against a booted emulator:
|
||||
|
||||
```
|
||||
flutter drive --driver=test_driver/integration_test.dart \
|
||||
--target=integration_test/suites/tier0/onboarding_create_test.dart \
|
||||
--dart-define=CI_BUILD=true -d <device-id>
|
||||
```
|
||||
|
||||
Run a whole tier through the runner:
|
||||
|
||||
```
|
||||
TEST_TIER=tier0 FLUTTER_DEVICE=<device-id> ./integration_test_runner.sh
|
||||
```
|
||||
|
||||
`SUITE_DIR` also takes a single file, which is what you want while iterating on one suite:
|
||||
|
||||
```bash
|
||||
SUITE_DIR=integration_test/suites/tier0/fiat_currency_test.dart ./integration_test_runner.sh
|
||||
```
|
||||
|
||||
Runner knobs (environment variables): `SUITE_DIR`, `TEST_TIER` (tier0, tier1, all),
|
||||
`PLATFORM` (android, linux, macos, auto), `FLUTTER_DEVICE`, `RETRY_COUNT`,
|
||||
`EXTRA_DART_DEFINES`, `REMOVE_DATA_DIRECTORY=N` to keep app data between suites,
|
||||
`REMOVE_DESKTOP_DATA=Y` to let a desktop run wipe the wallet directories it shares with the
|
||||
installed app, `VOID_GRACE` for how long a driver that cannot attach is given to recover.
|
||||
|
||||
Test knobs (dart defines): `TEST_WALLET_TYPES=all` runs every available wallet type,
|
||||
a comma separated list of type names runs just those, unset runs the representative set
|
||||
(solana, ethereum, bitcoin, monero).
|
||||
|
||||
## Which tier does my test go in
|
||||
|
||||
- Creates wallets, navigates screens, checks local state: **tier0**.
|
||||
- Needs a node, a provider API or any live network response: **tier1**.
|
||||
- Signs and broadcasts a real transaction: **funds_suites**, never anywhere else.
|
||||
|
||||
tier0 blocks merges. tier1 runs on every PR but reports without blocking until it has a
|
||||
stable history. funds_suites run only from the manual funds workflow.
|
||||
|
||||
## What is covered today
|
||||
|
||||
Twenty seven suites. Add a line here when you add one.
|
||||
|
||||
### tier0, no network needed
|
||||
|
||||
| Suite | What it proves |
|
||||
| --- | --- |
|
||||
| `onboarding_create_test` | A wallet can be created for every configured type, and the app lands on the dashboard with that wallet open |
|
||||
| `onboarding_restore_test` | A wallet restores from seed for every configured type, and the restored wallet reports the seed it was given |
|
||||
| `invalid_seed_test` | A seed the wallet cannot parse leaves the user on the restore screen with nothing created |
|
||||
| `duplicate_wallet_name_test` | A name already taken is refused instead of quietly overwriting the wallet holding it |
|
||||
| `wallet_group_test` | A wallet added to an existing seed shares that seed, and both wallets stay reachable through the group |
|
||||
| `wallet_rename_test` | A wallet can be renamed, and cannot be renamed onto a name another wallet already holds |
|
||||
| `wallet_delete_test` | Deleting a wallet takes it off the list and out of storage, and leaves the others alone |
|
||||
| `receive_address_test` | The receive sheet shows an address the opened wallet owns, not a leftover from the previous one |
|
||||
| `seed_confirmation_test` | The seed and keys the app displays are the ones the opened wallet holds |
|
||||
| `show_keys_auth_test` | The seed and keys page turns away a wrong pin and opens for the right one |
|
||||
| `change_pin_test` | A changed pin is the one that opens what the old pin used to guard |
|
||||
| `send_validation_test` | The send screen refuses an empty address, a malformed one, an empty amount and more than the balance |
|
||||
| `address_book_test` | A saved contact keeps the address it was given |
|
||||
| `send_from_address_book_test` | A contact picked on the send screen fills in the address that was saved for it |
|
||||
| `settings_nav_test` | Every settings row opens its page and backs out of it |
|
||||
| `language_test` | Changing the language changes what the settings screen shows |
|
||||
| `fiat_currency_test` | Turning the fiat api off hides the currency setting, turning it back on returns it and the currency can be changed |
|
||||
|
||||
### tier1, needs a node or a provider
|
||||
|
||||
| Suite | What it proves |
|
||||
| --- | --- |
|
||||
| `sync_status_test` | A restored wallet reaches a node and starts syncing rather than sitting at connecting |
|
||||
| `node_switching_test` | Confirming another node repoints the wallet at it |
|
||||
| `transaction_history_test` | A wallet with known transactions renders them, both in the home preview and the full list |
|
||||
| `transaction_details_test` | Tapping a transaction opens the details of that transaction and not another one |
|
||||
| `swap_quote_test` | The swap sheet reaches a provider and returns a real quote, no trade is created |
|
||||
| `monero_legacy_seed_test` | A 25 word monero seed restores through the legacy path, which takes a seed type and a restore height the polyseed path never asks for |
|
||||
|
||||
### funds_suites, manual workflow only
|
||||
|
||||
| Suite | What it proves |
|
||||
| --- | --- |
|
||||
| `send_dry_run_test` | Every funded chain builds and signs a transaction, then throws it away without broadcasting |
|
||||
| `send_funds_test` | A real self transaction is broadcast on every funded chain |
|
||||
| `swap_dry_run_test` | A real deposit is priced end to end, stopping before the trade is created |
|
||||
| `swap_funds_test` | A swap is created and its deposit broadcast |
|
||||
|
||||
The two dry runs need funded seeds because a quote and a signed transaction both depend on a
|
||||
real balance, but neither spends anything. `SPEND=true` is what lets the two that do spend
|
||||
past their guard.
|
||||
|
||||
## Adding a test for your feature
|
||||
|
||||
1. Give the widgets your test touches stable keys, inline in the widget:
|
||||
`key: ValueKey('<page>_<element>_key')`. Keys go on the widget the test taps or reads,
|
||||
never on AnimatedSwitcher children where the key is the animation identity.
|
||||
2. Create or extend the robot for the screen in `robots/`. One robot per screen, it
|
||||
extends `BaseRobot` and implements `isDisplayed()`. Robots own every finder for their
|
||||
screen, suites never call `find` directly.
|
||||
3. If the journey spans several screens, add a flow to `flows/` composing the robots.
|
||||
4. Copy `integration_test/templates/example_feature_test.dart.example` into the right
|
||||
tier directory, rename it to `<feature>_test.dart` and fill it in. The runner only
|
||||
picks up files ending in `_test.dart`.
|
||||
5. Run it twice locally against an emulator before pushing.
|
||||
6. Add it to the table above.
|
||||
|
||||
## Harness rules
|
||||
|
||||
- Suites use `integrationTest` from `core/app_launcher.dart`, not `testWidgets`. It contains
|
||||
background async errors from app networking that would otherwise fail the test, awaited
|
||||
assertion failures still fail the test normally.
|
||||
- No `sleep` or fixed delays, use `pumpUntilFound` and `pumpUntil` with a timeout.
|
||||
- No `pumpAndSettle` in new code, screens with endless animations never settle,
|
||||
use the bounded `settle()` from BaseRobot.
|
||||
- No `find.text` on localized strings, keys only. Wallet names and addresses are data,
|
||||
matching on those is fine.
|
||||
- `.secrets.g.dart` is only imported by `core/test_wallets.dart`.
|
||||
- Every suite starts from a fresh install, the runner wipes app data between suites.
|
||||
- Reading a view model through the page widget for a state assertion is fine, driving
|
||||
the app through view models instead of the UI is not.
|
||||
|
||||
## Secrets
|
||||
|
||||
Test wallet seeds and receive addresses live in `lib/.secrets.g.dart` under names like
|
||||
`solanaTestWalletSeeds`, defined in `tool/utils/secret_key.dart` and reachable through
|
||||
`TestWallets`. CI injects the real values from the `MAIN_SECRETS_FILE` repository secret.
|
||||
|
||||
Adding a new test secret means adding it in `tool/utils/secret_key.dart`, mapping it in
|
||||
`TestWallets` and asking the team lead to add the value to the CI secret.
|
||||
|
||||
The slack report uses two more repository secrets, `SLACK_TESTS_TOKEN` and
|
||||
`SLACK_TESTS_CHANNEL`, which is a channel id rather than a webhook. Both the PR gate and
|
||||
the funds workflow report through them, so every test result lands in one channel.
|
||||
|
||||
That is a separate slack app from the one behind `SLACK_APP_TOKEN`, which uploads apks to
|
||||
the builds channel. They are split so each token carries only what it needs, `chat:write`
|
||||
for this one and the file scopes for that one, and so the name on a message says which of
|
||||
the two sent it. A post coming back `missing_scope` means the app is short the
|
||||
`chat:write` scope or was never reinstalled after it was added.
|
||||
|
||||
## Funds suites
|
||||
|
||||
`funds_suites/` restore funded wallets and move real funds: a small self send on every
|
||||
funded chain, and one real swap with its deposit broadcast. They only run from the manual
|
||||
`Funds Integration Tests` workflow, which the team lead dispatches from the Actions tab
|
||||
before a release. The job runs in the `funds` environment, so add required reviewers to that
|
||||
environment under Settings, Environments, or a dispatch still starts without an approval.
|
||||
|
||||
Funded seeds live in the `FUNDS_SECRETS_FILE` secret, a base64 encoded replacement for
|
||||
`integration_test/core/funded_wallets.dart` mapping wallet type names to that chain's
|
||||
funded wallets, at least two per chain. A wallet with a passphrase carries it and the restore
|
||||
flow ticks the passphrase box and enters it. A wallet without one leaves it out:
|
||||
|
||||
```dart
|
||||
import "funded_wallet.dart";
|
||||
|
||||
const Map<String, List<FundedWallet>> fundedWallets = {
|
||||
"solana": [
|
||||
FundedWallet(seed: "first wallet seed words ...", passphrase: "first passphrase"),
|
||||
FundedWallet(seed: "second wallet seed words ...", passphrase: "second passphrase"),
|
||||
],
|
||||
"ethereum": [
|
||||
FundedWallet(seed: "seed words ..."),
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
A wrong passphrase restores an empty derivation, so it shows up the same way a drained
|
||||
wallet does, as "no spendable balance".
|
||||
|
||||
The suites restore a chain's funded wallets one by one and use the first that shows a
|
||||
spendable balance, a wallet that finishes syncing while still empty counts as drained.
|
||||
A chain where every funded wallet is empty fails with a message asking for a top up.
|
||||
|
||||
The checked in default is an empty map and must stay empty. Only the funds workflow turns
|
||||
on `write_funds_secrets`, and that input is the one thing keeping funded seeds out of a PR
|
||||
build now that no environment scopes the secret. In auto mode the suites discover every
|
||||
chain present in the map, so funding a new chain only means adding its entry to the
|
||||
secret. The dispatch inputs narrow a run: `flows` picks send, swap or both, `chains` lists
|
||||
the chains the send suites run on, `swap_from` picks the wallet type the swap deposits from
|
||||
(empty takes the first funded chain) and `swap_to` the currency it receives (empty leaves
|
||||
the swap page's own pairing, which is XMR for everything but a monero wallet). Whatever
|
||||
`swap_to` names must have a fixture address in `TestWallets.receiveAddressFor`, that is
|
||||
where the payout goes. Per chain send amounts are tuned in `TestConfig._fundsSendAmounts`.
|
||||
The swap suite enters an amount just above the provider minimum, the deposit wallet's
|
||||
balance has to cover that minimum plus fees.
|
||||
|
||||
## How CI runs them
|
||||
|
||||
The PR gate runs on GitHub hosted runners, the self-hosted android builders have no
|
||||
usable KVM so the emulator cannot start there. Moving back is a one line change to
|
||||
`runs-on` in `reusable-integration-test.yml` once a KVM capable builder exists.
|
||||
|
||||
tier0 and tier1 each get their own emulator step and upload their logs separately, so a
|
||||
runner that dies during tier1 cannot take the gate's own results with it. The gradle heap
|
||||
is capped before the test phase because the daemon and the emulator together were
|
||||
exhausting the runner.
|
||||
|
||||
Every run posts to slack. The message names each tier's counts, its duration and any suite
|
||||
that failed, and the full list of what passed goes in a reply on the same message so the
|
||||
channel keeps the short version. A suite that failed because the driver never attached is
|
||||
labelled as such rather than reported as a failing test, since in that case the suite never
|
||||
ran at all. It needs `SLACK_TESTS_TOKEN` and `SLACK_TESTS_CHANNEL`, and
|
||||
without either the step logs a notice and skips rather than failing the gate. Cancelled
|
||||
runs stay quiet, since superseded runs are cancelled on purpose. The report is built from
|
||||
the `SUMMARY_FILE` each tier writes, so anything the runner counts is available to it.
|
||||
|
||||
Two environment quirks are worth knowing when a build fails in CI but not locally: the
|
||||
deps docker image regenerates the mweb ffi bindings with an ffigen too old for the current
|
||||
compiler and its rsync overwrites `cw_mweb/pubspec.yaml`, so the workflow restores that
|
||||
file and regenerates the bindings itself. And `assets/images` svgs need compiling to
|
||||
`.vec`, which `compile_graphics.sh` does not cover.
|
||||
|
||||
## Flakiness playbook
|
||||
|
||||
- A timeout in `pumpUntilFound` throws with the finder description. Diagnose through the
|
||||
`integration-test-logs` artifact in CI, it holds the run log and a final logcat dump.
|
||||
The timeout also takes a screenshot, it lands in `build/integration_test_screenshots/`
|
||||
on the machine that ran the suite, named after the robot and the helper that timed out.
|
||||
CI does not upload them.
|
||||
- The app's own error handling ignores missing `.svg.vec` assets by design, the harness
|
||||
filters those too. Any other FlutterError fails the test, that is intentional.
|
||||
- Monero and wownero load native libraries on first open, give their steps generous
|
||||
timeouts rather than retries.
|
||||
- A driver that cannot attach is watched rather than waited out. Once flutter drive says
|
||||
it is struggling, the attempt gets `VOID_GRACE` seconds (60 by default) to come back and
|
||||
is then ended so the retry can start, instead of sitting there for the rest of
|
||||
`TEST_TIMEOUT`. Run 31364715120 lost 20 minutes to two attempts that did exactly that.
|
||||
60 is well clear of a healthy attach, which took under a second on all 19 attempts that
|
||||
worked in that same run, against 5 seconds for the warning to appear on the two that
|
||||
did not.
|
||||
- A suite that fails once in CI retries once with wiped app data. A red gate means the
|
||||
same suite failed twice in a row.
|
||||
+106
-6
@@ -1,12 +1,112 @@
|
||||
# Security Policy
|
||||
|
||||
## Reporting a Vulnerability
|
||||
Cake Wallet is developed by **Cake Labs LLC**. We take the security and privacy of
|
||||
our users seriously and welcome reports from security researchers.
|
||||
|
||||
If you need to report a vulnerability, please either:
|
||||
> **Cake Wallet is not affiliated with CAKE.com, Clockify, or security.cake.com.**
|
||||
> Those services belong to unrelated companies. The only official vulnerability
|
||||
> disclosure channels for Cake Wallet are the ones listed on this page and at
|
||||
> https://cakewallet.com/security.
|
||||
|
||||
* Open a security advisory: https://github.com/cake-tech/cake_wallet/security/advisories/new
|
||||
* Send an email to `dev@cakewallet.com` with details on the vulnerability
|
||||
## Reporting a vulnerability
|
||||
|
||||
## Supported Versions
|
||||
**Please do not open a public issue, pull request, or social-media post for a
|
||||
security vulnerability.** Public disclosure before a fix is available puts users'
|
||||
funds and privacy at risk. Use one of the private channels below and we will
|
||||
coordinate a fix and disclosure with you.
|
||||
|
||||
As we don't maintain previous versions of the app, only the latest release for each platform is supported and any updates will bump the version number.
|
||||
1. **GitHub private security advisory (preferred).**
|
||||
[Report a vulnerability](https://github.com/cake-tech/cake_wallet/security/advisories/new).
|
||||
This gives you a private, structured thread with the maintainers and is the
|
||||
fastest way to reach us.
|
||||
2. **Encrypted email.** Send details to **security@cakewallet.com**. For sensitive
|
||||
reports, please encrypt with our PGP key:
|
||||
- Key: https://cakewallet.com/.well-known/cakewallet-security.asc
|
||||
- Fingerprint: `DC91 6520 0271 AC6A 0533 3D3C BFE7 D9A5 0E4D 3A0A`
|
||||
|
||||
Both channels are monitored and automatically raise an alert in our internal
|
||||
security channel, so reports will not be missed.
|
||||
|
||||
### What to include
|
||||
|
||||
- A clear description of the issue and its security impact.
|
||||
- A working proof of concept is required. It must run directly against Cake
|
||||
Wallet itself, using a release build or locally built version, and demonstrate
|
||||
the reported behavior and security impact. Standalone Python code,
|
||||
mathematical examples, or simulations that only reproduce the theory without
|
||||
exercising Cake Wallet do not satisfy this requirement.
|
||||
- Step-by-step reproduction instructions.
|
||||
- Affected platforms (iOS, Android, macOS, Linux, Windows) and app version.
|
||||
- Affected wallet types / chains, if applicable.
|
||||
- Any relevant logs, addresses, or transaction IDs (for on-chain issues).
|
||||
|
||||
If you used AI tooling to find or write up the report, please say so.
|
||||
|
||||
### Communication expectations
|
||||
|
||||
AI should not be used to generate comments when communicating with maintainers
|
||||
and other contributors. Comments are expected to be written by humans. Comments
|
||||
that are believed to be written by AI may be moderated.
|
||||
|
||||
## Our commitment (safe harbor)
|
||||
|
||||
We consider security research conducted in good faith under this policy to be
|
||||
authorized. We will not pursue or support legal action against researchers who:
|
||||
|
||||
- make a good-faith effort to avoid privacy violations, data destruction, and
|
||||
interruption or degradation of our services;
|
||||
- only interact with accounts they own or have explicit permission to access; and
|
||||
- give us a reasonable opportunity to fix an issue before disclosing it publicly.
|
||||
|
||||
If in doubt about whether an action is authorized, ask us first at
|
||||
security@cakewallet.com.
|
||||
|
||||
## What to expect
|
||||
|
||||
- **Acknowledgement:** within **2 business days**.
|
||||
- **Triage and initial assessment:** within **7 business days**.
|
||||
- **Coordinated disclosure:** we aim to ship a fix and coordinate public
|
||||
disclosure within **90 days** of the report. We will keep you updated on
|
||||
progress and agree on a disclosure date with you.
|
||||
- **Credit:** with your permission, we are happy to publicly credit you for the
|
||||
report once a fix is released.
|
||||
|
||||
## Scope
|
||||
|
||||
**In scope:** the Cake Wallet and Monero.com applications and the code in this
|
||||
repository and its sibling `cake-tech` repositories — anything that could lead to
|
||||
loss of funds, exposure of keys or seeds, a privacy leak, or a
|
||||
failed/incorrect transaction.
|
||||
|
||||
**Out of scope:** issues in third-party services, exchange/swap providers, or
|
||||
nodes we do not operate; reports generated solely by automated scanners without a
|
||||
demonstrated impact; low-severity or informational issues on our marketing and
|
||||
landing websites (for example reflected or self-XSS, missing security headers,
|
||||
clickjacking on pages with no sensitive actions, or SPF/DMARC and cookie-flag
|
||||
nitpicks) that do not affect the app or user funds; and social-engineering or
|
||||
physical attacks.
|
||||
|
||||
## Rewards
|
||||
|
||||
At our **sole discretion**, we may offer a reward for a valid report. To be
|
||||
eligible, a report must:
|
||||
|
||||
- be submitted **privately** through one of the channels above (a GitHub private
|
||||
security advisory or `security@cakewallet.com`) — anything disclosed publicly or
|
||||
sent through other channels is not eligible; and
|
||||
- identify a genuine vulnerability with real impact on users — typically loss of
|
||||
funds, exposure of keys or seeds, a privacy leak, or a failed or incorrect
|
||||
transaction.
|
||||
|
||||
Trivial or low-impact findings are **not** eligible — for example, reflected XSS
|
||||
or other low-severity issues on our marketing websites, missing security headers,
|
||||
hardening or best-practice suggestions, automated-scanner output without a working
|
||||
proof of concept, or already-known issues. There is no fixed bounty and no
|
||||
guaranteed payout; whether a report qualifies, and any amount, are determined
|
||||
solely by Cake Labs LLC.
|
||||
|
||||
## Supported versions
|
||||
|
||||
We do not maintain previous releases. Only the **latest release for each platform**
|
||||
is supported; security fixes are delivered in new versions. Please keep Cake Wallet
|
||||
up to date.
|
||||
|
||||
@@ -18,8 +18,8 @@ In order to build the latest version of Cake Wallet, simply run the following:
|
||||
git clone --branch main https://github.com/cake-tech/cake_wallet.git
|
||||
# NOTE: Replace `main` with the latest release tag available at https://github.com/cake-tech/cake_wallet/releases/latest.
|
||||
cd cake_wallet
|
||||
# docker build -t ghcr.io/cake-tech/cake_wallet:debian13-flutter3.32.0-ndkr28-go1.24.1-ruststablenightly . # Uncomment to build the docker image yourself instead of pulling it from the registry
|
||||
docker run -v$(pwd):$(pwd) -w $(pwd) -i --rm ghcr.io/cake-tech/cake_wallet:debian13-flutter3.32.0-ndkr28-go1.24.1-ruststablenightly bash -x << EOF
|
||||
# docker build -t ghcr.io/cake-tech/cake_wallet:debian13-flutter3.41.9-ndkr28-go1.24.1-ruststablenightly . # Uncomment to build the docker image yourself instead of pulling it from the registry
|
||||
docker run -v$(pwd):$(pwd) -w $(pwd) -i --rm ghcr.io/cake-tech/cake_wallet:debian13-flutter3.41.9-ndkr28-go1.24.1-ruststablenightly bash -x << EOF
|
||||
set -x -e
|
||||
git config --global --add safe.directory '*'
|
||||
pushd scripts/android
|
||||
|
||||
@@ -20,8 +20,8 @@ In order to build the latest version of Cake Wallet, simply run the following:
|
||||
git clone --branch main https://github.com/cake-tech/cake_wallet.git
|
||||
# NOTE: Replace `main` with the latest release tag available at https://github.com/cake-tech/cake_wallet/releases/latest.
|
||||
cd cake_wallet
|
||||
# docker build -t ghcr.io/cake-tech/cake_wallet:debian13-flutter3.32.0-ndkr28-go1.24.1-ruststablenightly . # Uncomment to build the docker image yourself instead of pulling it from the registry
|
||||
docker run --privileged -v$(pwd):$(pwd) -w $(pwd) -i --rm ghcr.io/cake-tech/cake_wallet:debian13-flutter3.32.0-ndkr28-go1.24.1-ruststablenightly bash -x << EOF
|
||||
# docker build -t ghcr.io/cake-tech/cake_wallet:debian13-flutter3.41.9-ndkr28-go1.24.1-ruststablenightly . # Uncomment to build the docker image yourself instead of pulling it from the registry
|
||||
docker run --privileged -v$(pwd):$(pwd) -w $(pwd) -i --rm ghcr.io/cake-tech/cake_wallet:debian13-flutter3.41.9-ndkr28-go1.24.1-ruststablenightly bash -x << EOF
|
||||
set -x -e
|
||||
git config --global --add safe.directory '*'
|
||||
pushd scripts
|
||||
|
||||
Reference in New Issue
Block a user