Improve security
This commit is contained in:
@@ -82,10 +82,12 @@ Create a user, then log in through the UI at `http://localhost:5173`:
|
||||
|
||||
```sh
|
||||
curl -X POST -H "Content-Type: application/json" \
|
||||
-d '{"name": "mace", "email": "you@example.com", "password": "secret"}' \
|
||||
-d '{"name": "mace", "email": "you@example.com", "password": "secret1"}' \
|
||||
http://localhost:8001/api/v1/user/create
|
||||
```
|
||||
|
||||
Passwords must be at least 6 characters.
|
||||
|
||||
### Useful commands during development
|
||||
|
||||
```sh
|
||||
@@ -110,6 +112,30 @@ docker exec -it rss-postgres psql -d rss -U admin
|
||||
|
||||
---
|
||||
|
||||
## Security notes
|
||||
|
||||
- **Sessions**: login returns a JWT (`token` header) valid for 24 hours. Logging out
|
||||
(`POST /api/v1/auth/logout`, requires the current token) bumps the user's
|
||||
`token_version`, which immediately invalidates *all* outstanding tokens for that
|
||||
account — there's no per-session revocation, so logging out on one device logs out
|
||||
every device.
|
||||
- **Login rate limiting**: `POST /api/v1/auth/login` is limited to a burst of 5 requests
|
||||
per IP, replenishing one every 2 seconds (`actix-governor`).
|
||||
- **Outbound fetches**: feed syncs and the article-reader endpoint only fetch
|
||||
`http`/`https` URLs that resolve to public IP addresses (no loopback/private/
|
||||
link-local, e.g. `127.0.0.1` or the `169.254.169.254` cloud metadata address).
|
||||
Redirects are followed (up to 5 hops), but each redirect target is checked against the
|
||||
same rules before being fetched, so a redirect can't be used to reach an internal
|
||||
address.
|
||||
- **Stored feed content**: `<img>` tags from synced feed content are sanitized
|
||||
(`ammonia`) down to `src`/`alt`/`title` before being stored, since they're later
|
||||
rendered with `v-html` in the frontend.
|
||||
- **If `JWT_SECRET` or `POSTGRES_PASSWORD` are ever leaked** (e.g. committed to git),
|
||||
rotate them in `.env` and restart the backend — rotating `JWT_SECRET` invalidates every
|
||||
outstanding token as a side effect.
|
||||
|
||||
---
|
||||
|
||||
## Production setup (Docker)
|
||||
|
||||
The whole stack — Postgres, backend, and frontend — runs via Docker Compose. The frontend is built as a static Vue bundle and served by nginx, which also reverse-proxies `/api/` to the backend container.
|
||||
|
||||
Reference in New Issue
Block a user