|
1 | 1 | # Security Policy |
2 | 2 |
|
3 | | -## Supported Versions |
| 3 | +Report vulnerabilities to sg85207@gmail.com |
4 | 4 |
|
5 | | -| Version | Supported | |
6 | | -|---------|-----------| |
7 | | -| Latest (main branch) | Yes | |
8 | | - |
9 | | -## Reporting a Vulnerability |
10 | | - |
11 | | -If you discover a security vulnerability in Ledger Sync, please report it responsibly: |
12 | | - |
13 | | -1. **Do NOT open a public GitHub issue** for security vulnerabilities |
14 | | -2. Email the maintainer directly at the email listed on the GitHub profile |
15 | | -3. Include a description of the vulnerability, steps to reproduce, and potential impact |
16 | | -4. You can expect an initial response within 48 hours |
17 | | - |
18 | | -## Security Architecture |
19 | | - |
20 | | -### Authentication |
21 | | - |
22 | | -- **OAuth 2.0 only** (Google, GitHub) — no password storage |
23 | | -- JWT tokens with configurable expiration (default 30 minutes) |
24 | | -- Token blacklist on logout prevents token reuse |
25 | | -- OAuth secrets stored server-side only; frontend never sees provider tokens |
26 | | - |
27 | | -### Data Isolation |
28 | | - |
29 | | -- All database tables are scoped by `user_id` foreign key |
30 | | -- Every API endpoint requires JWT authentication via `get_current_user` dependency |
31 | | -- Every database query filters by `current_user.id` — no cross-user data access possible |
32 | | -- User identity is extracted from JWT (not request parameters) — cannot be spoofed |
33 | | - |
34 | | -### API Security |
35 | | - |
36 | | -- **Rate limiting** via slowapi on all endpoints |
37 | | -- **Security headers**: CSP, HSTS, X-Frame-Options, X-Content-Type-Options |
38 | | -- **CORS** configured for frontend origin only |
39 | | -- **Input validation** via Pydantic schemas on all request bodies |
40 | | -- **SQL injection protection** via SQLAlchemy ORM (no raw SQL) |
41 | | -- **File upload validation** — only .xlsx/.xls accepted, chunked upload support |
42 | | - |
43 | | -### Data Protection |
44 | | - |
45 | | -- Transaction deduplication via SHA-256 hashing |
46 | | -- Soft deletes with `is_deleted` flag (audit trail preserved) |
47 | | -- Database: SQLite for development, PostgreSQL for production with connection pooling |
48 | | -- SQLite WAL mode enabled for concurrent read performance |
49 | | - |
50 | | -### Account Management |
51 | | - |
52 | | -- Account reset requires typing "RESET" to confirm |
53 | | -- Account deletion requires typing "DELETE" to confirm |
54 | | -- Both operations are irreversible and delete all user-scoped data |
55 | | - |
56 | | -## Best Practices for Self-Hosting |
57 | | - |
58 | | -1. **Use HTTPS** in production (Render provides this automatically) |
59 | | -2. **Set strong JWT secret**: `LEDGER_SYNC_JWT_SECRET_KEY` should be a random 256-bit key |
60 | | -3. **Use PostgreSQL** in production (not SQLite) for proper access controls |
61 | | -4. **Keep dependencies updated**: Run `uv lock --upgrade` and `pnpm update` regularly |
62 | | -5. **Enable database backups** if using a hosted PostgreSQL provider |
63 | | -6. **Do not expose** the database port publicly — only the backend API should access it |
| 5 | +Version: 1 |
0 commit comments