From 9c9a99543628e735e09836cda109f8890e39e9cc Mon Sep 17 00:00:00 2001 From: Shagun Killekar Date: Sat, 16 May 2026 13:38:04 +0530 Subject: [PATCH] fix: sanitize and validate GitHub username input --- app/page.tsx | 53 +- package-lock.json | 2053 +++++++++------------------------------------ 2 files changed, 417 insertions(+), 1689 deletions(-) diff --git a/app/page.tsx b/app/page.tsx index 6c5fa5d..0cd7564 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -66,11 +66,22 @@ const Icons = { export default function LandingPage() { const [username, setUsername] = useState(''); + const [error, setError] = useState(''); const [copied, setCopied] = useState(false); + const cleanUsername = (value: string) => { + return value + .trim() + .replace(/^https?:\/\/(www\.)?github\.com\//i, '') + .replace(/\/$/, '') + .replace(/\s/g, ''); +}; + +const isValidUsername = (value: string) => { + return /^(?!-)(?!.*--)[A-Za-z0-9-]{1,39}(?(null); const trimmedUsername = username.trim(); - const hasUsername = trimmedUsername.length > 0; - + const hasUsername = trimmedUsername.length > 0 && error === ''; const badgeUrl = `/api/streak?user=${trimmedUsername}`; const markdown = `![CommitPulse](https://commitpulse.vercel.app/api/streak?user=${trimmedUsername})`; @@ -117,14 +128,36 @@ export default function LandingPage() {
-
- setUsername(e.target.value)} - /> +
+
+ { + const raw = e.target.value; + const cleaned = cleanUsername(raw); + + setUsername(cleaned); + + if (cleaned && !isValidUsername(cleaned)) { + setError('Invalid GitHub username format'); + } else { + setError(''); + } + }} + /> +
+ + {error && ( +

+ Invalid GitHub username format +

+ )} +
+ +