> **ARCHIVED:** 2025-12-22 | All items tracked as GitHub issues: #141 (CSP), #145 (CSRF), #223 (CSP headers), #282 (rate limiting)

# Security Hardening Follow-up Tasks

> **Created:** 2025-12-08 | **PR:** #84 | **Status:** Archived - See GitHub Issues

Post-merge improvements identified during PR #84 review. These are enhancements to the security hardening work, not blockers.

## Priority: High

### 1. CSRF Integration Tests

**Location:** `lib/__tests__/csrf.test.ts` (new file)

**What to test:**

- Origin header validation (valid/invalid origins)
- Referer fallback when Origin is missing
- Subdomain pattern matching (`*.myamsoil.com`, `*.acdev3.com`, etc.)
- Method filtering (only POST/PUT/DELETE/PATCH should be validated)
- Missing headers rejection

**Example structure:**

```typescript
describe('CSRF Protection', () => {
  it('should block POST with invalid origin', async () => {
    const request = mockRequest({ origin: 'https://evil.com' });
    const result = validateCsrf(request);
    expect(result?.status).toBe(403);
  });

  it('should allow POST from dealer subdomain', async () => {
    const request = mockRequest({ origin: 'https://bobsoil.myamsoil.com' });
    const result = validateCsrf(request);
    expect(result).toBeNull(); // null = allowed
  });

  it('should allow staging subdomain', async () => {
    const request = mockRequest({ origin: 'https://dealer.acdev3.com' });
    const result = validateCsrf(request);
    expect(result).toBeNull();
  });

  it('should skip validation for GET requests', async () => {
    const request = mockRequest({ method: 'GET', origin: 'https://evil.com' });
    const result = validateCsrf(request);
    expect(result).toBeNull();
  });
});
```

---

### 2. Rate Limiting Monitoring

**Location:** Cloudflare Dashboard

**Current behavior:** Rate limiting is handled at the Cloudflare edge, which provides IP identification and rate limiting before requests reach the application.

**Enhancement:** Set up Cloudflare rate limiting alerts to monitor:

- Blocked request counts by rule
- Geographic distribution of rate-limited IPs
- Unusual traffic patterns

**Why:** Edge rate limiting is more efficient but requires monitoring through Cloudflare's dashboard rather than application logs.

---

## Priority: Medium

### 3. CSP Monitoring & Enforcement

**Current state:** CSP is in `Report-Only` mode (next.config.mjs:54-55)

**Follow-up steps:**

1. **Set up CSP violation reporting endpoint:**

   ```typescript
   // app/api/csp-report/route.ts
   export async function POST(request: Request) {
     const report = await request.json();
     logger.warn('[CSP Violation]', report);
     return new Response(null, { status: 204 });
   }
   ```

2. **Add report-uri to CSP header:**

   ```
   Content-Security-Policy-Report-Only: ...; report-uri /api/csp-report
   ```

3. **Monitor violations for 1-2 weeks** to identify:
   - Legitimate resources being blocked
   - Third-party scripts needing allowlisting
   - Any inline scripts that need nonces

4. **Tune policy** based on real violations

5. **Switch to enforcement mode:**
   ```diff
   - 'Content-Security-Policy-Report-Only'
   + 'Content-Security-Policy'
   ```

---

### 4. HSTS Header (Strict-Transport-Security)

**Location:** `next.config.mjs` security headers section

**Add for production:**

```javascript
{
  key: 'Strict-Transport-Security',
  value: 'max-age=31536000; includeSubDomains; preload',
},
```

**Considerations:**

- Only enable for production (HTTPS required)
- `includeSubDomains` ensures dealer subdomains also use HTTPS
- `preload` allows submission to browser HSTS preload lists
- Start with shorter `max-age` (e.g., 86400) and increase after verification

**Implementation:**

```javascript
// Only add HSTS in production
...(process.env.NODE_ENV === 'production' ? [{
  key: 'Strict-Transport-Security',
  value: 'max-age=31536000; includeSubDomains',
}] : []),
```

---

## Priority: Low

### 5. Pre-sanitize CMS Content at Save Time

**Current:** XSS sanitization happens at render time via `sanitizeHtmlWithSecureLinks()`

**Optimization:** Sanitize during save/publish and store sanitized HTML. This:

- Reduces render-time overhead
- Ensures content is clean before it reaches the database
- Allows detection of XSS attempts during content creation

**Trade-off:** Requires re-sanitizing all existing content and adds complexity to the save flow.

---

## Verification Checklist

After implementing each item:

- [ ] CSRF tests: Run `npm test -- csrf` and verify all pass
- [ ] Rate limit logging: Deploy to staging and verify logs appear in Vercel
- [ ] CSP monitoring: Check `/api/csp-report` receives violation reports
- [ ] HSTS: Verify header appears in browser dev tools (production only)

---

## Related Files

| File                         | Purpose                      |
| ---------------------------- | ---------------------------- |
| `lib/csrf.ts`                | CSRF validation logic        |
| `next.config.mjs`            | Security headers (CSP, HSTS) |
| `lib/cms/sanitize.ts`        | Server-side XSS sanitization |
| `lib/cms/sanitize-client.ts` | Client-side XSS sanitization |
