Kaspa Forge OfficeForge
Security

Security Center

Everything that decides whether Kaspa Forge can be trusted with your money, in one place — the real hashes, keys and test numbers, and how to check every one of them yourself. Kaspa Forge is non-custodial: the funds live in open-source on-chain covenants, and this page is our attempt to make that verifiable rather than a promise. Last reviewed: July 11, 2026. Security contact: kaspa@officeforge.co · security.txt.

Open beta · external audit pending. Both covenants are open source and have passed our own on-chain and adversarial tests, but they have not yet had an independent external audit. Treat Kaspa Forge like beta software: keep vault balances and deals modest (suggested vault cap 5,000 KAS; deals run 50–10,000 KAS).

1. The trust model

Kaspa Forge holds no custody of your coins. Money sits in a Kaspa on-chain covenant — a script enforced by Kaspa consensus, not by our server. The signing keys exist only in your browser or app, inside your encrypted key file, and are never sent to us. What that buys you, stated as hard invariants:

  • The server cannot steal. No vault or escrow private keys, and no seed, ever live on the server. The keyless covenant paths (a vault's complete and inheritAuto; an escrow's autoRelease and timeout) hard-bind their output to a fixed recipient, so even our own watcher can only push funds where the contract already says they go.
  • The arbiter cannot steal. The escrow covenant has no path to any third party — every one of its 10 spend paths pays only the buyer, the seller, or the fixed service-fee address. A compromised or coerced arbiter still cannot express a theft as a valid transaction; the worst they can do is pick one of buyer / seller / split.
  • A thief with your hot key gets nothing fast. A vault withdrawal only leaves through the unvault delay window to a fixed destination, and a separate alarm key (kept off the device that holds the hot key) cancels it.
  • The watcher is a liveness service, not a custodian. It watches the chain and broadcasts the already-signed keyless paths (auto-release, inheritance, timeout) and sends alerts — it holds no key that can redirect funds.
  • Covenants are P2PK-only and non-composable. Outputs bind to plain pay-to-pubkey scripts; the covenants cannot be chained or wrapped into a larger contract that changes their rules.
  • Single-input on every path. Every entrypoint of both covenants asserts tx.inputs.length == 1 and an on-chain fee-budget cap (0.1 KAS), closing a multi-UTXO siphon and preventing a transition from being burned into the network fee.
  • The service is a convenience, not a dependency. If our site disappears, your funds do not: the contracts live on-chain and can be operated from your recovery sheet against any Kaspa node — see §10.

Full architecture and the annotated invariant list live in the docs; the contract sources below are the ground truth.

2. The contracts & their hashes

Two Silverscript covenants run everything. Both are published in full in our public repository. The SHA-256 below is of the covenant source file as published — it lets you confirm that the code you audit is the code we ship.

vault.sil — the Kaspa Safe vault covenant
versionv3 — inheritance (auto / signed), migrate path
spend paths7 — initiate · cancel · complete · checkin · inheritAuto · inheritSigned · migrate
sha-256a47cb298f60d688427585f9f7b443fddd3bef44c6ec87ebf35648897f7d0220b
escrow.sil — the Kaspa Escrow / Гарант covenant
versionv1 — 10 fixed payout paths
spend paths10 — release · refund · mutual · dispute · autoRelease · arbitrate{ToBuyer,ToSeller,Split} · timeout{ToBuyer,ToSeller}
sha-25665d4b6bb3c516647b72a873dab1272445c498f8b17bfba19ec15519726dcb4a0
Why not a single "deployed contract hash"? A covenant's on-chain script prefix is the source plus your own parameters (your pubkeys, delay, heir, fee budget, deal terms), so every vault and every deal has a different script hash — by design. The stable, auditable thing is the source above; the per-safe / per-deal script is derived from it deterministically by the open-source tooling, and your Desk shows the exact address you funded. See §3 to reproduce it.

3. Verify a contract yourself

Everything needed to check the covenants is public in github.com/pcdoctormsk-ctrl/kaspa-safe: both .sil sources, the vaultctl / escrowctl CLIs, the web front-end and the Android app with its build workflow.

Confirm the source hash matches what this page claims:

# after cloning the repo
sha256sum contracts/vault.sil contracts/escrow.sil
# expect:
# a47cb298f60d688427585f9f7b443fddd3bef44c6ec87ebf35648897f7d0220b  contracts/vault.sil
# 65d4b6bb3c516647b72a873dab1272445c498f8b17bfba19ec15519726dcb4a0  contracts/escrow.sil

Run the covenants against the real Kaspa VM. The CLIs compile the covenant with the pinned Silverscript compiler (rev d25bd34) and execute every spend path — including the attacks (early completion, wrong key, wrong destination, premature inheritance, one-key migrate, multi-input siphon) — inside the actual Kaspa node VM, under the consensus compute-budget limit:

# needs Rust (rustup.rs), protobuf-compiler, clang
cd vaultctl  && cargo run --release -- selftest   # vault: 25 checks
cd escrowctl && cargo run --release -- selftest   # escrow: 52 checks

Reproduce your own safe's address. For a vault you already created, vaultctl status --recovery <your recovery sheet> rebuilds the covenant from your parameters and prints the same address your Desk funded — proof that the deployed script is exactly this source instantiated with your keys, with no server in the loop.

4. Public keys & addresses

These are the only long-lived service values baked into escrow deals. Both are public by nature — an x-only public key and a Kaspa address. There is no service private key you need to trust: the arbiter key only lets the arbiter choose among buyer/seller/split, and the fee address only ever receives the visible service fee.

arbiter pubkey (x-only)43eec216c3c93e4c0565eb53aae1e4674d567111661baf5eaa2df405316eaa2e
escrow fee addresskaspa:qq3manh4l3yj69hc062wz5a86h6qjffx7nuh9ldkdjqr5kaxm4zy6sh2lksln

When you create or join a deal, these exact values are written into the covenant you fund — you can confirm them in your key file and against the on-chain deal.

5. Tests & audit status

Automated test suites (run July 11, 2026). The Rust core and server carry unit and property tests across the covenant logic, the watcher, the wallet/derivation and the deal state machine:

server crate119 passed · 0 failed · 1 ignored
wasm core crate29 passed · 0 failed
total148 passed · 0 failed

Consensus-VM contract selftests. On top of the unit tests, the covenants are exercised path-by-path inside the real Kaspa node VM (see §3 to run them yourself): vault 25 checks, escrow 52 checks — each including the adversarial cases, all green.

External audit: pending. No independent third-party security audit has been completed yet. The above is our own testing — thorough, but not a substitute for an external review. That is the single biggest reason to keep amounts modest during the open beta.

6. Reproducible builds & the app

The WASM vault/escrow core is built from source with wasm/build.sh (wasm-pack, release). The Android app is built by the public android-apk GitHub Actions workflow in the same repository, so the binary you install traces back to auditable source and CI, not a hand-uploaded file.

Current Android build. The APK and its SHA-256 are published alongside the download; verify before you install:

version0.1.1
apk sha-256086421854bedd54b1c123092f06ab309be2aea04efbbfff3590ff7a089bc413b
# verify a downloaded APK
sha256sum KaspaSafe.apk
# must equal 086421854bedd54b1c123092f06ab309be2aea04efbbfff3590ff7a089bc413b

Signed release APKs are also published on GitHub Releases. The web app runs entirely in your browser; its Content-Security-Policy blocks any network connection other than to this origin, so a key can't be exfiltrated even via a script injection.

7. Known limitations

Honesty is part of the security story. These are the real edges of the current design:

  • No external audit yet. The contracts are unaudited by a third party — see §5.
  • Open beta, capped amounts. Suggested vault cap 5,000 KAS; escrow deals are enforced to 50–10,000 KAS.
  • Escrow needs an active buyer. A dispute must be opened within the dispute window. If the window passes with no dispute, funds auto-release to the seller — the buyer must act in time.
  • Lose your key file, lose access. There are no accounts and no password reset. Your encrypted key file is the only way in — back it up. A dictionary-weak passphrase weakens the file's encryption.
  • The service token is a capability. The token in your key file authorizes management API calls for your vault/deal; anyone who obtains it can call those endpoints (it still cannot move funds outside the covenant's fixed paths). It is not rotated automatically. Detail in the privacy policy.
  • Alerts depend on the service. Telegram / e-mail alerts and the watcher's convenience broadcasts stop if our service is down. On-chain safety does not depend on them — but you may not be notified as quickly. Run your own watcher from the recovery kit if you want independence.
  • You evaluate your counterparty. In Escrow and the Marketplace we are not a party to the deal and do not vet goods, identity or solvency; the arbiter rules only within buyer/seller/fee.

8. Contract change history

Every change to the covenant sources, newest first (from the repository git log):

date file change
2026-07-10vaultmigrate path added (both signatures = instant full authority: upgrade / key rotation / exit)
2026-07-10bothon-chain griefing cap: feeBudget ≤ MAX enforced in every path (audit 07-11)
2026-07-10bothfee budget became a constructor parameter + two require()s from the audit
2026-07-10bothsingle-input invariant added to all paths (multi-UTXO anti-siphon)
2026-07-07vaultheader brought up to v3 (auto/signed inheritance)
2026-07-05escrowescrow.sil v1 — 10 paths (release/refund/mutual/dispute/autoRelease/arbitrate×3/timeout×2)
2026-07-04vaultv3 inheritance (auto/signed, chosen at creation)
2026-07-04vaultfirst on-chain vault (genesis covenant accepted by consensus)

The authoritative, complete log is the git history of contracts/vault.sil and contracts/escrow.sil in the public repository.

9. Responsible disclosure

Found a vulnerability? Please report it privately and give us a chance to fix it before it becomes public.

  • Email kaspa@officeforge.co with enough detail to reproduce (a proof-of-concept, affected component, and impact).
  • Do not post it publicly or exploit it against real users' funds while we work on a fix.
  • We aim to acknowledge reports quickly and will keep you updated on the fix and timeline. We will credit reporters who want it.

Machine-readable contact per RFC 9116: /.well-known/security.txt.

We do not run a paid bug-bounty program and make no promise of payment. This is a good-faith responsible-disclosure channel — we simply ask you to report privately, and we will act on it.

10. If something goes wrong

Because the contracts live on-chain, you can act even if our site is down:

  • Vault recovery (offline): the vault recovery guide and vaultctl operate your safe from your recovery sheet against any Kaspa node — check-in, cancel a theft, complete a withdrawal, claim inheritance, or migrate out.
  • Deal recovery (offline): the escrow recovery guide covers a stuck deal — including the keyless timeout path that releases funds if the arbiter never rules.
  • Suspected theft of a vault hot key: use your alarm key to cancel the in-flight withdrawal (shown in your Telegram alert and vault panel), then migrate to a fresh vault.
  • Found a security bug: do not post it publicly — email kaspa@officeforge.co (see §9).

Related: Terms · Safe privacy · Escrow & Market privacy · Docs. Questions: kaspa@officeforge.co.