Security
Designed to fail closed on every boundary.
PredictFlow is non-custodial — your key never leaves your wallet extension. But non-custodial alone is not safe. A compromised upstream or a malformed quote response could still slip a malicious transaction into your signing prompt. These defenses exist because prediction markets move real money and the threat model deserves it.
The four-gate signing pipeline
Before your wallet opens its signing UI, every transaction passes through these gates in order. Any failure blocks the prompt and surfaces an explicit error.
Payload size limit
Any DFlow /order response larger than twice the Solana max transaction size is rejected outright. Protects against a malicious upstream trying to push an oversized binary.
Decode with @solana/web3.js
The transaction is parsed into its VersionedTransaction form before any other check runs. Malformed payloads fail here and never reach the signing prompt.
Program whitelist assertion
Every instruction target is checked against a strict allowlist: System, SPL Token, Associated Token Account, ComputeBudget, Memo, and the DFlow router program (configured via VITE_DFLOW_ALLOWED_PROGRAMS). Anything else — rejected.
RPC preflight simulation
The final gate runs simulateTransaction against your configured Solana RPC (with sigVerify disabled and recent blockhash replaced). A server-side attempt to drain a wallet fails here and never reaches the wallet prompt.
Content-Security-Policy
The application ships a strict CSP that enumerates every origin it's allowed to reach. Any script or fetch to an unlisted host is blocked by the browser, regardless of what the app code tries to do.
default-src 'self';
base-uri 'self';
object-src 'none';
frame-ancestors 'self';
form-action 'self';
img-src 'self' data: https://phantom.app https://solflare.com https://backpack.app;
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
font-src 'self' data: https://fonts.gstatic.com;
script-src 'self';
connect-src 'self'
https://*.dflow.net
wss://*.dflow.net
https://*.solana.com
https://*.helius-rpc.com
https://*.quiknode.pro
https://*.triton.one;
manifest-src 'self';
worker-src 'self' blob:;
upgrade-insecure-requests; Defense in depth
Only browser-injected providers are supported (Phantom, Solflare, Backpack). No WalletConnect bridge, no remote signing — every signature happens in the wallet extension you installed.
Every submit carries an X-Idempotency-Key header. A module-level submission lock prevents double-signing across component remounts or rapid double-clicks.
Wallet pubkeys are SHA-256-hashed before any analytics event. Error messages are stripped of HTML and control characters before reaching Sentry.
VITE_ALLOW_SYNTHESIZED_MINTS and
VITE_ALLOW_SIMULATED_FILLS default to false in
production. Real-money deployments can never accidentally fake a fill.
What PredictFlow doesn't do
- Take custody of funds, ever.
- Store private keys or seed phrases.
- Sign transactions on your behalf.
- Expose key material to analytics, Sentry, or any third-party service.
- Use remote signing, hardware bridges, or multi-party computation.
- Maintain a shared orderbook or ledger — everything you own is on-chain.
Responsible disclosure
Found a vulnerability in the client, the Pages Function proxy, or the deploy tooling? Email security@predictflow.org with reproduction steps. We'll respond within 72 hours.
Security audited? No — but it's open source.
Every line of the transaction pipeline is in the repo. Audit it yourself, or invite the researcher of your choice.