Security Review for Hone
Based on OWASP Top 10 (2021) and modern web security practices.
OWASP Top 10 Relevance to Hone
A01:2021 - Broken Access Control
- •Risk: Unauthorized access to other users' financial data
- •Hone Context: Currently single-user, but if multi-user is added:
- •Implement proper session management
- •Validate user owns requested resources
- •Use principle of least privilege
A02:2021 - Cryptographic Failures
- •Data Classification: Transaction data is sensitive PII
- •At Rest: SQLCipher for database encryption (per DESIGN.md)
- •In Transit:
- •All external connections MUST use TLS/HTTPS
- •Ollama connection should use HTTPS if remote
- •Hashing: Using SHA-256 for deduplication (appropriate choice)
Database Encryption (Required):
rust
// SQLCipher - open encrypted database
let conn = Connection::open("hone.db")?;
conn.pragma_update(None, "key", &passphrase)?;
// Key derivation - use Argon2 to derive key from user passphrase
use argon2::{Argon2, PasswordHasher};
let salt = SaltString::generate(&mut OsRng);
let argon2 = Argon2::default();
let key = argon2.hash_password(passphrase.as_bytes(), &salt)?;
Implementation Requirements:
- •Use
rusqlitewithbundled-sqlcipherfeature - •Derive encryption key from passphrase using Argon2
- •Passphrase provided at startup (env var or prompt)
- •Never log or expose the passphrase
Backup Encryption:
- •Backups encrypted with
agebefore upload to Cloudflare R2 - •Consider post-quantum algorithms for future-proofing (harvest now, decrypt later threat)
A03:2021 - Injection
- •SQL Injection (Critical for hone-core/src/db.rs)
- •All queries MUST use parameterized statements
- •Never interpolate user input into SQL
rust
// SECURE - parameterized query
conn.execute(
"INSERT INTO transactions (account_id, amount) VALUES (?, ?)",
params![account_id, amount]
)?;
// VULNERABLE - string interpolation
conn.execute(
&format!("SELECT * FROM transactions WHERE merchant = '{}'", merchant),
[]
)?;
- •CSV Injection (hone-core/src/import.rs)
- •Sanitize fields starting with
=,+,-,@(Excel formula injection) - •Validate numeric fields are actually numeric
- •Sanitize fields starting with
A04:2021 - Insecure Design
- •Threat Modeling: Financial data attracts attackers
- •Defense in Depth: Multiple layers of validation
- •Secure Defaults: Restrictive CORS, minimal permissions
A05:2021 - Security Misconfiguration
- •CORS: Restrict to specific origins in production
rust
// Development (permissive)
CorsLayer::permissive()
// Production (restrictive)
CorsLayer::new()
.allow_origin("https://your-domain.com".parse::<HeaderValue>().unwrap())
.allow_methods([Method::GET, Method::POST])
- •Error Messages: Never expose stack traces or internal paths
- •Headers: Set security headers (via tower-http)
- •
X-Content-Type-Options: nosniff - •
X-Frame-Options: DENY - •
Content-Security-Policy
- •
A06:2021 - Vulnerable Components
- •Run
cargo auditregularly (already set up) - •Keep dependencies updated
- •Review transitive dependencies
A07:2021 - Authentication Failures
- •Currently N/A (single-user, local)
- •If adding auth:
- •Use established libraries (not custom)
- •Implement rate limiting
- •Secure session management
A08:2021 - Data Integrity Failures
- •CSV Import: Validate file integrity
- •Check file size limits
- •Validate expected columns exist
- •Reject malformed data gracefully
A09:2021 - Security Logging
- •Log security-relevant events:
- •Failed authentication attempts (if added)
- •Access to sensitive endpoints
- •Import operations
- •Don't log sensitive data (transaction details, amounts)
A10:2021 - SSRF
- •Ollama Integration: Validate URL is localhost/trusted
- •Don't allow user-controlled URLs for HTTP requests
Frontend Security (React/TypeScript)
XSS Prevention
- •React escapes by default (good)
- •Never use
dangerouslySetInnerHTMLwith user data - •Sanitize data before rendering if from external source
Sensitive Data
- •Don't store financial data in localStorage/sessionStorage
- •Clear sensitive state on logout
- •Use httpOnly cookies for auth tokens (if added)
Content Security Policy
html
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'">
Secrets Management
Never Commit
- •API keys, tokens, passwords
- •Database credentials
- •Private keys
Secure Storage
- •Use
.envfiles (gitignored) - •Environment variables at runtime
- •Consider
dotenvcrate for Rust
Detection Patterns
code
# Patterns that indicate hardcoded secrets api_key\s*[:=] password\s*[:=] secret\s*[:=] token\s*[:=] -----BEGIN.*PRIVATE KEY-----
Security Review Checklist
Database Layer (db.rs)
- • SQLCipher encryption enabled (bundled-sqlcipher feature)
- • Key derived via Argon2 from passphrase
- • All queries use parameterized statements (
params![]) - • No string interpolation in SQL
- • Input validation before queries
- • Errors don't expose SQL details
Import Layer (import.rs)
- • File size limits enforced
- • Path traversal prevented
- • CSV fields sanitized
- • Malformed input handled gracefully
API Layer (hone-server)
- • Request validation on all endpoints
- • Generic error responses
- • CORS configured appropriately
- • Security headers set
Frontend (ui/)
- • No sensitive data in localStorage
- • XSS vectors checked
- • CSP headers configured
- • API errors handled gracefully