This document defines the structured security review process for YieldVault-RWA. All code changes must follow these guidelines to ensure sensitive code paths are thoroughly vetted.
- Overview
- Sensitive Code Paths
- Review Checks
- Sign-Off Requirements
- Common Findings and Remediation
- Incident Response
- Release Coordination
Security reviews are mandatory for changes that:
- Handle authentication, authorization, or access control
- Process or store secrets and credentials
- Update dependencies (especially transitive dependencies)
- Modify contract code or blockchain interactions
- Handle sensitive user data (PII, financial data)
- Affect rate limiting, DDoS protection, or infrastructure security
The goal is to minimize risk through structured, repeatable review processes while enabling teams to move confidently.
Scope: User login, token validation, permission checks, session management
Checklist:
- Authentication flow uses industry-standard methods (OAuth 2.0, JWT, etc.)
- Token generation includes sufficient entropy and expiration
- Password handling uses proper hashing (bcrypt, argon2, scrypt)
- Authorization checks are applied consistently
- No hardcoded credentials or test data in production code
- Rate limiting prevents brute force attacks
- Session fixation and CSRF protections are in place
Example files to review:
backend/src/auth/*backend/src/middleware/*frontend/src/auth/*
Reviewers: Lead security engineer + auth domain owner
Scope: API keys, database credentials, private keys, environment-sensitive configuration
Checklist:
- No secrets committed in code (verified by git-hooks and scanning)
- Secrets are injected via environment variables or secure vaults
- Rotation procedures are documented
- Sensitive logs are scrubbed (no secrets in error messages)
- Secret access is audited where applicable
- Secrets are never logged, even in debug mode
Example files to review:
.env*files (should be in.gitignore)backend/src/config/*backend/src/utils/encryption/*
Reviewers: DevOps/Infrastructure engineer + lead developer
Scope: Package version changes, new transitive dependencies, security patches
Checklist:
- Update is from a legitimate, verified source
- No typosquatting (package name is correct)
- Known vulnerabilities resolved (checked against CVE databases)
- Breaking changes are understood and handled
- License compatibility verified (no GPL if proprietary code)
- Minimal version constraints used (pinned or range)
- Update included in changelog with reasoning
Example files to review:
package.jsonandpackage-lock.jsonCargo.tomlandCargo.lock(Rust contracts)backend/package.json,frontend/package.json
Reviewers: Tech lead + security engineer
Scope: Solidity contract code, transaction construction, state mutations, external calls
Checklist:
- No reentrancy vulnerabilities
- State mutations are atomic or properly coordinated
- External calls use safe patterns (checks-effects-interactions)
- Gas limits and estimation are correct
- No logic that could be front-run
- Contract state transitions are validated
- Events are emitted for all state changes
- Access controls are properly enforced
Example files to review:
contracts/src/*.solbackend/src/blockchain/*- Contract interaction layers
Reviewers: Smart contract auditor + lead backend engineer
Scope: PII, financial data, user balances, transaction history
Checklist:
- Data is encrypted at rest if applicable
- Data is encrypted in transit (TLS/HTTPS)
- Access is restricted by permission checks
- Audit logs track access to sensitive data
- Data retention policies are enforced
- No unintended data leakage in error messages or logs
- GDPR/privacy regulations are respected (right to deletion, etc.)
Example files to review:
backend/src/models/*(data models)backend/src/api/routes/*(API endpoints)backend/src/services/*(business logic)
Reviewers: Data privacy officer + backend architect
- Secret Scanning: Gitleaks scans for leaked credentials
- Dependency Audit:
npm audit,cargo auditfor known vulnerabilities - SAST: Static analysis for common security patterns
- Linting: Code style and security lints
CI Status: All must pass before human review
- Threat Modeling: Are there new attack vectors?
- Data Flow: How does data move through the system?
- Error Handling: Could exceptions leak sensitive information?
- Testing: Are edge cases and attacks tested?
- Documentation: Are security implications documented?
For sensitive changes, approval from security-cleared reviewers is required:
[Approved for security]
Reviewed: Authentication flow for new OAuth provider
Checked: Token expiration, secret management, rate limiting
Risk: Low - follows existing patterns
- ✅ 1 approval from code owner
- ✅ All CI checks pass
- ✅ At least 1 test
- ✅ 2 approvals (code owner + security reviewer)
- ✅ All CI checks pass (including security scans)
- ✅ Security sign-off comment required
- ✅ Comprehensive tests demonstrating secure behavior
- ✅ No "Request Changes" left unresolved
- ✅ 3 approvals (code owner + security reviewer + release owner)
- ✅ All CI checks pass
- ✅ Security audit completed (external if needed)
- ✅ Rollback plan documented
- ✅ All stakeholders notified
- ✅ Security and architecture review
- ✅ Impact analysis on dependent services
- ✅ Deprecation period observed (if applicable)
- ✅ Migration guide provided
Risk: Secrets in code → exposed in repository history, build artifacts, logs
Remediation:
- Remove secret from code
- Rotate affected credentials immediately
- Use environment variables or secure vault
- Add to
.gitignore - Use
git-filter-repoto purge history (only if not yet public)
# Example: Move secret to env
- const API_KEY = "sk-123456789";
+ const API_KEY = process.env.API_KEY;Risk: Injection attacks, buffer overflows, DoS
Remediation:
- Validate all user inputs (type, length, format)
- Use allowlists where possible
- Sanitize for output context (HTML, SQL, JavaScript)
- Add tests for invalid inputs
// ✗ Unsafe
app.get('/user/:id', (req, res) => {
db.query(`SELECT * FROM users WHERE id = ${req.params.id}`);
});
// ✓ Safe
app.get('/user/:id', (req, res) => {
const id = parseInt(req.params.id, 10);
if (!Number.isInteger(id)) throw new Error('Invalid ID');
db.query('SELECT * FROM users WHERE id = ?', [id]);
});Risk: Sensitive information in error messages, system crashes
Remediation:
- Catch specific exceptions
- Log full error internally only
- Return generic error to user
- Never expose stack traces in production
// ✗ Unsafe
try {
// operation
} catch (e) {
res.status(500).json({ error: e.message });
}
// ✓ Safe
try {
// operation
} catch (e) {
logger.error('Operation failed:', e); // Internal only
res.status(500).json({ error: 'An error occurred' });
}Risk: Data inconsistency, financial loss, contract exploits
Remediation:
- Use database transactions
- Use mutex/locks for concurrent access
- Implement optimistic concurrency control
- Test with load and concurrent requests
// ✓ With transaction
db.$transaction(async (tx) => {
const current = await tx.balance.findUnique({ where: { id } });
const updated = await tx.balance.update({
where: { id },
data: { amount: current.amount - withdrawal }
});
});Risk: Unauthorized state-changing actions on behalf of users
Remediation:
- Use CSRF tokens for state-changing operations (POST, PUT, DELETE)
- Validate token on every request
- Use SameSite cookie attribute
- Implement double-submit cookies if needed
// ✓ With CSRF protection
app.post('/transfer', csrfProtection, (req, res) => {
// Token already validated by middleware
// Process transfer
});Risk: Man-in-the-middle attacks, credential theft
Remediation:
- Enforce HTTPS/TLS everywhere
- Use HSTS headers
- Pin certificates for critical connections
- Use secure WebSocket (wss://)
# ✓ In production nginx config
server {
listen 443 ssl http2;
ssl_protocols TLSv1.2 TLSv1.3;
add_header Strict-Transport-Security "max-age=31536000" always;
}Risk: Unauthorized data access, privilege escalation
Remediation:
- Apply principle of least privilege
- Use role-based access control (RBAC)
- Add per-resource authorization checks
- Audit access patterns
// ✗ Unsafe
app.get('/users/:id', (req, res) => {
const user = db.getUser(req.params.id);
res.json(user);
});
// ✓ Safe
app.get('/users/:id', (req, res) => {
const user = db.getUser(req.params.id);
if (!canViewUser(req.user, user)) {
throw new ForbiddenError();
}
res.json(user);
});If a security issue is found during review:
- Stop the PR: Do not merge until resolved
- Classify: Severity level (critical, high, medium, low)
- Assign: Route to appropriate expert
- Remediate: Fix the issue or redesign
- Verify: Re-review to confirm fix
- Document: Add to incident log and use for training
For critical issues in production, follow Incident Response Plan immediately.
- All PRs passed security review
- No open security findings
- Dependency audit passed
- SAST/scanning passed
- Changelog documents security changes
- Release notes include security advisories if any
If releasing a security fix:
- Coordinate with security@yieldvault.com
- Prepare security advisory
- Follow responsible disclosure timeline
- Notify customers if data exposed
- CONTRIBUTING.md - Contribution workflow
- ARCHITECTURE_SUMMARY.md - System design
- Release Documentation - Release processes
- OWASP Top 10
- CWE Top 25
Last Updated: August 2026
Owned By: Security Team
Review Schedule: Quarterly