StellarCred is in active development. Security fixes are applied to the latest commit on main.
Do not open a public GitHub issue for security vulnerabilities.
Email dahunsisamuel1st@gmail.com with:
- A description of the vulnerability and its potential impact
- Steps to reproduce or a proof-of-concept (private gist / attachment is fine)
- Any suggested mitigations if you have them
You will receive an acknowledgement within 48 hours. If the issue is confirmed, a fix will be prioritised and you will be credited in the release notes unless you prefer to remain anonymous.
Areas of particular interest:
| Area | Risk |
|---|---|
contracts/proof_registry |
Forged proofs accepted on-chain |
contracts/issuer_registry |
Unauthorized issuer registration |
app/api/issue/route.ts |
Server-side signing key exposure, credential forgery |
In-circuit ECDSA (std::ecdsa_secp256k1) |
Signature bypass |
| Persona KYC relay | Identity data leakage, bypass |
ISSUER_PRIVATE_KEYmust never have aNEXT_PUBLIC_prefix — it is server-side only.- The issuer's secp256k1 signature is verified inside the ZK proof (
std::ecdsa_secp256k1), and the contract checks the public key from public inputs matches the registered issuer key. A valid proof requires a registered issuer to have signed the credential. prehash: falseis required when signing — Noir uses the raw 32-byte commitment as the message digest. Changing this breaks all existing proofs.- Identity fields from KYC providers are used only to derive credential values and are never stored or logged after the API call completes.
See the full threat model and reviewer checklist in docs/THREAT_MODEL.md.
Before deploying StellarCred to the Stellar mainnet, verify that all security parameters and operational keys meet the following production standards:
- Multi-Signature / HSM Custody: The administrator key (contract admin) must NOT be a hot wallet stored in plaintext. It must be custody-secured (e.g., using a hardware wallet, an HSM, or a multi-signature account setup with appropriate thresholds).
- Minimal Privilege & Revocation: Ensure the admin key is only used for contract configuration/upgrades and is distinct from operational issuer keys.
- Upgrade Authorization: If the contract is upgradeable, confirm that upgrade authority is assigned to a multisig wallet or a community-controlled DAO address.
- Secret Key Protection: The
ISSUER_PRIVATE_KEYmust be securely stored in production-grade environment secrets (e.g., AWS Secrets Manager, GCP Secret Manager, or Vercel Encrypted Environment Variables). It must never be checked into git or exposed to the client-side (do not prefix withNEXT_PUBLIC_). - Key Rotation Procedures: Test and document the key rotation procedure. Registering a new issuer key in
IssuerRegistrymust be validated, and the corresponding private key updated in the API environment without service disruption. - Revocation: Ensure compromised issuer keys can be immediately removed or revoked in
IssuerRegistryby the admin.
- Ledger Close Alignment: The verification caching duration (
expiry/ TTL) must be aligned with Stellar mainnet ledger close times (average 5 seconds per ledger). - Storage TTL Verification: Review the storage TTL (Time-To-Live) settings for contract instances and entries. Confirm they are set high enough to prevent state eviction (by invoking TTL extension on-chain) while optimizing fee costs.
- Expiration Checks: Ensure proof submission expirations account for clock drift and network latency on mainnet.
- Gas and Fee Budgets: Verify that on-chain proof verification costs (CPU instructions and memory usage) fit comfortably within the mainnet limits per transaction and ledger.
- Transaction Fees: Ensure that transactions are submitted with competitive base fees to prevent delays during periods of high mainnet network congestion.
- Batch Size Constraints: If using batch submissions, ensure the batch limits (maximum 5 proofs) prevent transaction execution timeouts and stay well within the Soroban resource limits.