| Version | Status | Security Updates |
|---|---|---|
| 1.x (Testnet) | Active | Yes |
| < 1.0 | Pre-release | No |
Mainnet releases will receive security updates for a minimum of 12 months from release.
If you discover a security vulnerability in PERO-J, please report it privately to prevent public disclosure before a fix is available.
Do not open a public GitHub issue for security vulnerabilities.
-
GitHub Security Advisory (Preferred)
- Navigate to the Security tab
- Click "Report a vulnerability"
- Fill out the form with details of the vulnerability
- This creates a private discussion visible only to maintainers
-
Email
- Send a detailed report to:
security@pero-j.dev - Include steps to reproduce, impact assessment, and proposed remediation
- PGP key available upon request for highly sensitive disclosures
- Send a detailed report to:
- Description: Clear explanation of the vulnerability
- Type: (e.g., smart contract logic flaw, input validation, XSS, injection, etc.)
- Affected Component: (e.g., on-chain contract, indexer, frontend)
- Steps to Reproduce: Detailed instructions or proof-of-concept
- Impact: Severity and potential consequences
- Suggested Fix: (optional, but appreciated)
- Initial Acknowledgment: Within 24 hours
- Triage & Assessment: Within 72 hours
- Fix Development & Testing: Varies by severity (see below)
- Public Disclosure: Coordinated with the reporter, typically 30–90 days after a fix is released
| Severity | Examples | Timeline |
|---|---|---|
| Critical | Fund loss, contract lock-up, consensus failure | 7 days |
| High | Unauthorized state changes, access control bypass | 14 days |
| Medium | Information leakage, denial-of-service | 30 days |
| Low | Minor bugs, edge cases with limited impact | 60 days |
We follow coordinated vulnerability disclosure practices:
- Researchers report vulnerabilities privately
- PERO-J maintainers acknowledge receipt and begin investigation
- A patch is developed and tested
- The fix is released, and the vulnerability is publicly disclosed after release
- Credit is given to the reporter (unless anonymity is requested)
We do not offer monetary bug bounties at this time, but we recognize responsible disclosures in release notes and on this page.
transfer_admin intentionally requires authorization from both the current
admin and the new admin before ownership changes. This prevents a mistyped
address from permanently locking the contract, but it means the new admin must
co-sign the same transaction. The new admin does not need to be online at the
time the transaction is created; the transaction can be prepared and shared
for signing.
For a handoff using a hardware wallet or multi-signature account:
- Build an invoke transaction calling
transfer_adminwith the current admin and new admin addresses. - Simulate and prepare the transaction with the network's Soroban tooling.
- Have the current admin sign its authorization entry.
- Share the prepared transaction or auth envelope with the new admin. Have the new admin sign its authorization entry; for a multi-signature account, collect the signatures required by that account's signer policy.
- Combine the signatures, verify both authorization entries and the target address, then submit the transaction to the network.
Do not submit until both parties have verified the new address. A failed or expired prepared transaction must be rebuilt and signed again.
- Do not share your Stellar private keys with any service, including PERO-J
- Use testnet for exploratory transactions before mainnet deployment
- Verify contract addresses before calling smart contracts
- Monitor your wallet transactions regularly
- Review the contract code in
contract/before integrating PERO-J ABIs - Test ABI decoders with known-good values before trusting decoded events
- Keep dependencies up-to-date (
npm audit,cargo audit) - Do not hardcode secrets in environment files; use a secure secrets manager
PERO-J has not undergone a third-party security audit. The project is currently in testnet development. A formal audit is planned before mainnet deployment as outlined in ROADMAP.md.
If you lose access to your Stellar private key (secret key), there is no way to recover it. Stellar does not provide any mechanism for key recovery or account restoration.
- No seed phrase recovery — Unlike some blockchains, Stellar accounts are secured by a single private key
- No administrative override — There is no backdoor or admin key that can recover lost accounts
- No support recovery — Stellar development support cannot recover lost keys
- Contract redeployment required — If an admin key is lost, the only option is to deploy a new contract instance
Because transfer_admin requires authorization from both the current admin and the new admin, a lost admin key leaves the deployed contract permanently un-administrable. Once the current admin's secret key is gone, no other party can co-sign the transfer, so the existing contract instance can never change ownership again. In practical terms this means:
- No new indexers can be added — the
IndexerAllowlistcan no longer be modified, so no trusted event submitters can be added to the running contract - Contract metadata can no longer be updated by the admin —
update_contractandregister_contractcannot be performed by the existing admin key - No further on-chain administrative actions — any future admin-only operation is blocked for that contract instance
The indexer for the network continues to run off the contract's recorded state, but no administrative changes are possible on the locked instance. There is no on-chain recovery mechanism — this is a deliberate security property (a lost key must not grant anyone else control).
Out of scope (by design): on-chain key recovery, time-locked admin override, or any mechanism that could let a third party seize an account. These would weaken the security model.
- Backup your keys securely — Store private keys in multiple secure locations
- Use hardware wallets — For significant funds and especially for the admin key, use hardware wallet solutions (Ledger/Trezor)
- Prefer multi-sig for the admin key — Holding the admin key in a multi-signature account (see the Admin Transfer Procedure for
transfer_admin) spreads the trust and protects against a single lost key permanently locking the contract - Test key recovery — Verify you can access your account from a backup before storing value
- Document key locations — Keep a secure record of where keys are stored (not the keys themselves)
- Immediately revoke access — If possible, transfer assets to a new secure account
- Deploy new contract — If admin key is lost, deploy a new contract with a new admin key
- Update configurations — Update all references to the old contract address
- Notify stakeholders — Inform users of the contract address change
Since a lost admin key cannot be recovered and the existing contract instance is un-administrable, the only recovery path is redeployment. The migration procedure is:
- Deploy a new contract instance using a fresh, securely-held admin key (hardware wallet or multi-sig preferred)
- Re-register contract metadata on the new instance — call
register_contractfor eachContractMetathat existed on the old instance, using the same ABI data - Rebuild the indexer allowlist on the new instance — re-add each trusted indexer to
IndexerAllowlistvia the admin key - Repoint the indexer to the new contract address (update
SOROBAN_EXPLORER_CONTRACT_ID) and re-runsubmit_eventsubmissions against the new instance - Update downstream references — change any configuration, frontend, or monitoring that references the old contract address to use the new one
- Notify stakeholders — document the new contract address and any historical event gaps so consumers can adjust
Warning: Any assets or contracts associated with a lost key are permanently inaccessible. This is by design for security — there is no central authority that can recover lost keys.
For non-security questions or general inquiries, please open a GitHub issue or discussion. For security matters, use the reporting methods above.
Last Updated: 2026-08-31
Policy Version: 1.1