# Social integration — security review

Date: 2026-09-01  
Scope: `src/lib/social/**`, OAuth routes, platforms-status, Connected Accounts, env examples.

| Check | Status | Notes |
| ----- | ------ | ----- |
| No secrets in `.env.example` / `.env.production.example` | Pass | Placeholders only after scrub |
| Secrets never returned by platforms-status | Pass | Missing key **names** only |
| OAuth tokens not sent to frontend | Pass | `maskAccountsForClient` nulls tokens |
| Publish endpoints require session | Pass | `getSessionUser` on publish + social APIs |
| Cross-user post access blocked | Pass | `existing.userId !== user.id` → 403 |
| OAuth state cookies used | Pass | `oauth-cookies.ts` |
| Audit logs redact token-like keys | Pass | `social-publish-audit.ts` sanitize |
| Disabled platforms skip provider HTTP | Pass | `getPlatformBlockReason` before publish |
| Git history may still contain old secrets | **Action** | Rotate Meta/LinkedIn/Google/AI keys if examples were ever committed with real values |
| Automatic git history rewrite | Not done | Requires explicit approval |
| Webhook signature validation | N/A | No social webhooks in this release |
| Token encryption at rest | Partial | MariaDB columns named `*_encrypted`; confirm app-layer encryption if required by policy |

## Required operator action

If real credentials were previously committed to the repository:

1. Rotate Meta App Secret, LinkedIn Client Secret, Google Client Secret, Anthropic/OpenAI keys.
2. Invalidate old OAuth refresh tokens by reconnecting Connected Accounts.
3. Do **not** force-push history rewrite unless security lead approves.

## Logging hygiene

- Prefer structured `errorCode` over dumping full provider bodies.
- Never log `Authorization` headers or raw access tokens.
