| Version | Supported |
|---|---|
| 0.1.x | ✅ |
Never commit secrets to the repository. All sensitive configuration must use environment variables:
# Required for production
JWT_SECRET_KEY=<strong-random-secret>
AUTH_USERS=<username:hashed_password>
ALLOWED_ORIGINS=https://yourdomain.com
ALLOWED_HOSTS=yourdomain.comGenerate a strong secret key:
python -c 'import secrets; print(secrets.token_urlsafe(32))'Security Requirements:
- Minimum 32 characters
- Randomly generated (not a password)
- Never logged or exposed
- Rotate periodically (at least annually)
User passwords must be hashed with bcrypt:
from passlib.context import CryptContext
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
hashed = pwd_context.hash("user-password")Security Requirements:
- Use bcrypt with automatic salt
- Never store plaintext passwords
- Use timing-safe comparison
- Minimum password length: 8 characters (recommended: 12+)
Required for production deployments:
- Use valid SSL/TLS certificates (Let's Encrypt recommended)
- Enforce HTTPS (redirect HTTP → HTTPS)
- Enable HSTS (Strict-Transport-Security header)
- Use TLS 1.2 or higher only
Restrict origins to your domains only:
ALLOWED_ORIGINS=https://yourdomain.com,https://mobile.yourdomain.comDo NOT use:
*(wildcard - allows all origins)http://origins in production- Development URLs in production
Built-in rate limiting for authentication:
- 5 login attempts per 15 minutes per IP
- Automatic lockout after threshold
Production Recommendations:
- Use Redis for distributed rate limiting
- Monitor for brute force attacks
- Consider IP allowlisting for known locations
Current: Rate limiting uses in-memory storage Limitation: Resets on server restart Production Recommendation: Use Redis for persistent session storage
Current: Full images served for thumbnails (client-side resize) Limitation: Bandwidth intensive Production Recommendation: Pre-generate thumbnails or use image processing service
Current: JWT token required for image access Note: Images served without additional permission checks beyond authentication Consideration: Add specimen-level permissions if needed
Default: 24 hours
Configurable: ACCESS_TOKEN_EXPIRE_MINUTES environment variable
Recommendation: Shorter expiration (2-8 hours) for high-security deployments
DO NOT open a public GitHub issue for security vulnerabilities.
Instead, email security reports to: [Your security contact email]
- Description: Clear description of the vulnerability
- Impact: Potential security impact
- Reproduction: Steps to reproduce the issue
- Environment: Version, Python version, deployment method
- Proposed Fix: If you have suggestions
- Acknowledgment: Within 48 hours
- Initial Assessment: Within 1 week
- Status Update: Every 2 weeks until resolved
- Fix Release: Depends on severity
- Critical: 1-7 days
- High: 1-4 weeks
- Medium: 1-3 months
- Low: Next scheduled release
We follow coordinated disclosure:
- Reporter notifies maintainers privately
- Maintainers confirm and develop fix
- Fix released and version updated
- Public disclosure after fix available
- Reporter credited (if desired)
- JWT_SECRET_KEY generated and set (32+ characters)
- AUTH_USERS configured with bcrypt hashes
- ENVIRONMENT=production set
- HTTPS/TLS certificate configured
- ALLOWED_ORIGINS restricted to production domains
- ALLOWED_HOSTS restricted to production domains
- API docs disabled (check /docs returns 404)
- Default test credentials removed
- Firewall rules configured (only ports 80/443 open)
- System packages up to date
- Python dependencies up to date
- Database backups configured (if applicable)
- Monitoring and alerting configured
- Incident response plan documented
- Health check endpoint responding
- Authentication working correctly
- Rate limiting functional
- HTTPS redirect working
- Security headers present (verify with securityheaders.com)
- CORS policy enforced
- No secrets in logs
- Error messages don't leak sensitive info
- Backup restoration tested
The API automatically includes security headers:
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Strict-Transport-Security: max-age=31536000; includeSubDomains
Verify with:
curl -I https://yourdomain.com/api/v1/healthStatus: Not applicable (no SQL database in core API) Note: If adding database, use parameterized queries
Mitigation:
- X-XSS-Protection header enabled
- Content-Type validation
- Input sanitization in validators
Mitigation:
- JWT tokens required (not cookies)
- SameSite cookie policy (if cookies added)
Mitigation:
- JWT signature verification
- Token expiration enforced
- Constant-time password comparison
Mitigation:
- Per-IP rate limiting
- Failed attempt tracking
- Exponential backoff
Mitigation:
- Generic error messages
- API docs disabled in production
- No stack traces in responses
Mitigation:
- Regular dependency updates
- CI/CD security scanning
- Pin dependency versions
# Bad - commits secret
JWT_SECRET_KEY = "hardcoded-secret"
# Good - reads from environment
JWT_SECRET_KEY = os.environ.get("JWT_SECRET_KEY")# Bad - SQL injection risk
cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")
# Good - parameterized
cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))# Bad - no validation
def update_field(field_name, value):
record[field_name] = value
# Good - validate with Pydantic
class FieldUpdate(BaseModel):
field_name: str = Field(min_length=1, max_length=100)
value: str = Field(max_length=1000)# Bad - exposes internal details
except Exception as e:
return {"error": str(e)}
# Good - generic message
except Exception as e:
logger.error(f"Update failed: {e}")
return {"error": "Update failed"}# Good - catches errors early
def process_specimen(specimen_id: str) -> SpecimenReview:
pass-
Failed Login Attempts
- Sudden spikes indicate brute force
- Pattern: Multiple IPs trying same username
-
Rate Limit Triggers
- Frequent triggers indicate attack
- Monitor via logs or metrics
-
Error Rates
- Sudden increase may indicate attack
- Check for input validation errors
-
Unusual Traffic Patterns
- Off-hours access
- Geographic anomalies
- User agent patterns
- SIEM: Splunk, ELK Stack, or cloud-native
- IDS/IPS: Fail2ban, CloudFlare WAF
- Log Analysis: Automated alert rules
- Uptime Monitoring: UptimeRobot, Pingdom
- Isolate: Take affected systems offline
- Investigate: Review logs, identify scope
- Contain: Change all secrets (JWT key, passwords)
- Notify: Inform users if data compromised
- Remediate: Fix vulnerability, test thoroughly
- Document: Post-mortem analysis
- Monitor: Enhanced monitoring post-incident
For security incidents: [Your security contact email]
We take security seriously. Security updates are released as soon as possible:
- Critical: Immediate patch release
- High: Within 1 week
- Medium: Next minor release
- Low: Next major release
Subscribe to releases on GitHub to receive notifications.
Last Updated: 2025-12-02 Version: 0.1.x