How this app is built
Security posture
RetroBytes is a small store, but it is built as a security exercise, so the application controls are deliberate and testable. This page describes the controls in place today, in plain language, with a link to the source for each one so the claims can be checked against the code.
Session management
- The session id is regenerated on a successful login, so a session id planted before login cannot be reused afterward (session fixation defense).
- Sessions carry an expiry. A logged-in session stops resolving a user once it passes its configurable time to live (SESSION_TTL_HOURS, default 24 hours).
- The Secure flag on the session and CSRF cookies is driven by configuration (COOKIE_SECURE), so cookies are marked Secure when the app runs behind HTTPS.
Authorization
- The wishlist is scoped to the authenticated user id, so wishlist reads and writes are bound to the logged-in account rather than to the session alone.
- Admin routes are role gated. A request without the ADMIN role is refused.
- Order viewing is owner checked. A caller who does not own an order is answered with a 404 (order not found) rather than a 403, so order ids cannot be probed for existence by enumeration.
Input validation
- Region and ZIP inputs are length limited and pattern checked.
- Search terms are restricted to an allowed character set and capped at 50 characters.
- Quantities are parsed and bounded, and required fields on orders and other forms are checked server side.
Output handling
Pages are rendered with Go's html/template, which escapes interpolated values by context. User supplied and admin supplied fields (product names, descriptions, emails) are auto-escaped on output, and the templates do not use any raw HTML bypass.
Source: web/templates/product.htmlLogging
Security relevant events are logged (authentication outcomes, access denials, validation failures, rate limit hits, admin actions). Sensitive values are deliberately kept out of the logs: session ids, CSRF tokens, and raw rejected search input are not written. Only a request id and IP are kept for correlation.
Source: internal/log/log.goCredential handling
- No default login credentials ship with the code.
- Demo shopper accounts are seeded only when demo seeding is explicitly enabled (SEED_DEMO).
- The admin account is created only from environment variables (ADMIN_EMAIL and ADMIN_PASSWORD). There is no hardcoded admin password.
Supply chain
Continuous integration runs govulncheck (Go's vulnerability scanner) and gosec (static analysis) alongside build, vet, and tests. The dependency tree and the application code paths, including the template rendering and CSRF token handling, are re-checked on each run rather than asserted once, so newly disclosed advisories surface over time.
Source: .github/workflows/ci.ymlThis is a learning and portfolio project, not a production service, and it is not deployed with real customer data. The controls above describe the current state of the code.