Files
cg_api_secure-webshare/agent1_batch3.md

62 lines
4.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Server-Side Password Authentication Flow Assessment (Batch 3)
**File inspected:** `crates/cgcx-server/src/main.rs`
## Flow Verification
### 1. `get_metadata` handler (`/api/content/:cxid`)
- **Lines ~496568**
- Sequence:
1. Content status check (Deleted/Blacklisted) → **404 NotFound**
2. Max-views check (`content.view_count >= max`) → **410 Gone**
3. Password validation via `password_from_request(&headers, query.sc.as_deref(), ...)`**401 Unauthorized** if invalid
4. Returns metadata JSON if all checks pass
- **View increment:** None. Metadata requests do not consume auto-destroy views.
- **Conclusion:** Password check is enforced and returns 401 on failure. ✅
### 2. `serve_file` handler (`/api/content/:cxid/file/:file_idx`)
- **Lines ~700890**
- Sequence:
1. Content status check → **404**
2. Max-views check → **410**
3. Password validation via `password_from_request`**401** if invalid
4. Download permission check → **403 Forbidden** if `?download=true` but not allowed
5. File lookup, path-traversal validation, ETag conditional check (304)
6. Range header parsing
7. **View increment at line ~825:** `repo.increment_views(&content_id).await?`
8. If `new_views >= max`, spawns background auto-delete task after 30s
9. Streams decrypted file body
- **Conclusion:** View increment happens **after** password validation and all other guards. Unauthorized requests cannot consume views. ✅
### 3. `password_from_request` helper
- **Lines ~436475**
- Validates `sc` query parameter using Argon2 (`PasswordHash::new` + `Argon2::default().verify_password`).
- Falls back to `cgcx_pw` cookie verified with HMAC-SHA256 and `subtle::ConstantTimeEq`.
- Returns `None` on any mismatch, causing the caller to return 401.
- **Conclusion:** Argon2 verification is present and constant-time. ✅
### 4. `serve_raw_file` handler (`/api/content/:cxid/file/:file_idx/raw`)
- **Lines ~9201020**
- Sequence mirrors `serve_file` for status, max-views, and password checks.
- **View increment:** None. This endpoint never increments `view_count`.
---
## Edge Cases & Concerns
| # | Edge Case | Impact | Risk |
|---|-----------|--------|------|
| 1 | **`serve_raw_file` skips view increment** | Requests to the `/raw` endpoint do not consume auto-destroy views. A user could repeatedly preview raw text without triggering deletion. | Medium — bypasses view-count enforcement for text content previews. |
| 2 | **Zero-size files in `serve_file` return early** | The zero-size branch (line ~751) returns a response **before** the increment block, so zero-byte files never consume a view. | Low — niche, but technically bypasses max-views for empty files. |
| 3 | **Range/conditional/HEAD requests skip increment** | `serve_file` only increments when `!is_range && !is_conditional && !is_head`. Video/audio seeking (range requests), cache revalidation (If-None-Match), and HEAD probes do not count as views. | Low — intentional for UX, but means views are under-counted. |
| 4 | **Max-views checked before password validation** | In all three handlers, if `view_count >= max`, a request with a wrong password receives **410 Gone** instead of **401 Unauthorized**. This leaks that the content existed and exhausted its views without requiring the password. | Low — information disclosure about content lifecycle. |
| 5 | **TOCTOU race on view increment** | `content.view_count` is read in `repo.get()` and incremented later in a separate statement. Under concurrent requests, two clients could both pass the initial `view_count < max` check and both increment, causing `view_count` to exceed `max`. Both requests are still served. | Low — SQLite serializes writes via `conn.lock()`, but the read-write gap still allows one extra view. |
---
## Conclusion
- **Password authentication flow is correct.** Wrong passwords receive 401 and do **not** increment view counts.
- **No server changes are required for Batch 3.** The frontend password fix (if any) is independent of server behavior.
- The identified edge cases are pre-existing behaviors. None are blockers for Batch 3, but items 1 (`serve_raw_file` bypass) and 5 (TOCTOU race) may be worth addressing in a future hardening pass if auto-destroy accuracy is critical.