mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-05 21:39:54 +02:00
CI was running build + typecheck + test, but never lint. The i18n guardrail (eslint-plugin-i18next on packages/views/**/*.tsx) was configured but not enforced, so PRs kept landing user-facing English strings (chat session delete, project resources, mermaid fallback, invitations batch page). Changes: - .github/workflows/ci.yml: add `lint` to the turbo command - packages/eslint-config/react.js: split React rules (JSX-only) from react-hooks rules (apply to .ts too) — hooks live in .ts modules like use-agent-presence.ts, and inline-disable comments need the rule registered to resolve - Translate the 10 lint errors that surfaced: - editor/readonly-content.tsx mermaid render-error + rendering - issues/issue-detail.tsx Archive tooltip - invitations/invitations-page.tsx full page (new invite.batch.*) - invitations-page.test.tsx wrap with I18nProvider so getByRole queries match translated button labels - core/auth/utils.ts intentional control-char regex: add eslint-disable Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
22 lines
936 B
TypeScript
22 lines
936 B
TypeScript
/**
|
||
* Validate a post-login redirect URL and return it only if safe to follow.
|
||
*
|
||
* Only single-slash relative paths (e.g. `/invite/abc`) are accepted. Returns
|
||
* `null` for unsafe or empty input — call sites decide the fallback so this
|
||
* helper never overloads a specific path with "user did not pass next".
|
||
*
|
||
* Rejects:
|
||
* - `null` / empty string
|
||
* - absolute URLs (`https://evil.com`, `javascript:alert(1)`, …)
|
||
* - protocol-relative URLs (`//evil.com`)
|
||
* - paths containing backslashes (Windows-style or `/\\host`)
|
||
* - paths containing ASCII control characters (`\x00`–`\x1f`)
|
||
*/
|
||
export function sanitizeNextUrl(raw: string | null): string | null {
|
||
if (!raw) return null;
|
||
if (!raw.startsWith("/") || raw.startsWith("//")) return null;
|
||
// eslint-disable-next-line no-control-regex -- intentional: rejecting control chars is the whole point
|
||
if (/[\x00-\x1f\\]/.test(raw)) return null;
|
||
return raw;
|
||
}
|