Security

Security considerations and best practices for using Shade402 in production.

Wallet Security

Private Key Storage

Never store private keys in code or version control:

// BAD: Hardcoded private key
const wallet = Keypair.fromSecretKey(
  Buffer.from('hardcoded-secret-key', 'base64')
);

// GOOD: Load from environment variable
const wallet = Keypair.fromSecretKey(
  Buffer.from(process.env.WALLET_SECRET_KEY!, 'base64')
);

// GOOD: Use key management service
const wallet = await loadWalletFromAWSSecretsManager();

Key Rotation

Regularly rotate wallet keys:

  1. Generate new key pair

  2. Update environment variables

  3. Update configuration

  4. Test with small amounts

  5. Monitor old wallet for unexpected activity

Key Access Control

Limit access to wallet private keys:

  • Use environment variables (not committed to git)

  • Use secret management services (AWS Secrets Manager, HashiCorp Vault)

  • Implement access controls and audit logging

  • Use separate wallets for different environments

Payment Verification

On-chain Verification

Always enable on-chain verification in production:

initX402({
  // ... other config ...
  autoVerify: true, // Enable in production
});

On-chain verification:

  • Confirms transaction exists on blockchain

  • Verifies transaction signature

  • Checks transaction status

  • Prevents replay attacks

Payment Expiration

Set appropriate expiration times:

paymentRequired({
  expiresIn: 300, // 5 minutes - short for sensitive operations
  // or
  expiresIn: 3600, // 1 hour - longer for batch operations
});

Consider:

  • Shorter expiration for high-value resources

  • Longer expiration for user-initiated flows

  • Balance security with user experience

Amount Validation

Always validate payment amounts:

// Server-side validation
if (parseFloat(authorization.actualAmount) < parseFloat(requiredAmount)) {
  return res.status(403).json({ error: 'Insufficient payment' });
}

Resource Encryption

Enable Encryption

Use resource encryption for sensitive resources:

import { generateKeyPair } from '@shade402/core';

const { publicKey, privateKey } = generateKeyPair();

initX402({
  // ... other config ...
  encryptionPublicKey: publicKey,
  encryptionPrivateKey: privateKey,
});

Encryption prevents:

  • Payment request replay attacks

  • Resource path exposure

  • Unauthorized access to payment requests

Key Management

Store encryption keys securely:

  • Use separate keys for different environments

  • Rotate keys periodically

  • Use key management services

  • Never expose private keys

URL Validation

Client-side Validation

The client validates URLs to prevent SSRF attacks:

  • Only allows http:// and https:// schemes

  • Blocks localhost and private IPs (unless allowLocal is enabled)

  • Validates URL format

For local development only:

const client = new X402Client(wallet, rpcUrl, undefined, true); // allowLocal

Never use allowLocal in production.

Server-side Validation

Validate all incoming URLs and parameters:

function validateUrl(url: string): boolean {
  try {
    const parsed = new URL(url);
    // Only allow specific domains
    const allowedDomains = ['api.example.com'];
    return allowedDomains.includes(parsed.hostname);
  } catch {
    return false;
  }
}

Error Handling

Don't Expose Sensitive Information

// BAD: Exposes internal details
catch (error) {
  res.status(500).json({ error: error.message, stack: error.stack });
}

// GOOD: Generic error messages
catch (error) {
  console.error('Internal error:', error);
  res.status(500).json({ error: 'Internal server error' });
}

Rate Limiting

Implement rate limiting for payment-protected endpoints:

import rateLimit from 'express-rate-limit';

const paymentLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 10, // 10 requests per window
});

app.get('/api/premium-data',
  paymentLimiter,
  paymentRequired({ amount: '0.01' }),
  handler
);

Transaction Security

Transaction Signing

Always verify transaction signatures:

// Server verifies signature
const isValid = await processor.verifyPayment(
  paymentRequest,
  authorization
);

if (!isValid) {
  return res.status(403).json({ error: 'Invalid payment' });
}

Transaction Monitoring

Monitor transactions for suspicious activity:

  • Track payment amounts and frequencies

  • Alert on unusual patterns

  • Log all payment transactions

  • Review failed payment attempts

Network Security

RPC Endpoint Security

Use secure RPC endpoints:

// Use HTTPS
const rpcUrl = 'https://api.mainnet-beta.solana.com';

// Or use authenticated RPC provider
const rpcUrl = process.env.HELIUS_RPC_URL; // Includes API key

Network Validation

Validate network configuration:

const allowedNetworks = ['solana-mainnet', 'solana-devnet'];

if (!allowedNetworks.includes(network)) {
  throw new Error('Invalid network');
}

Best Practices Summary

  1. Never commit private keys to version control

  2. Use environment variables or key management services

  3. Enable on-chain verification in production

  4. Set appropriate expiration times for payment requests

  5. Validate all payment data before processing

  6. Enable resource encryption for sensitive resources

  7. Implement rate limiting for payment endpoints

  8. Monitor transactions for suspicious activity

  9. Use secure RPC endpoints with HTTPS

  10. Log payment transactions for audit purposes

  11. Handle errors securely without exposing sensitive information

  12. Regularly rotate keys and update dependencies

  13. Test security measures before production deployment

  14. Keep dependencies updated for security patches

Security Checklist

Before deploying to production:

Reporting Security Issues

If you discover a security vulnerability:

  1. Do not open a public issue

  2. Include details of the vulnerability

  3. Wait for confirmation before disclosing

Next Steps

Last updated