fix: resolve critical bugs and security issues across the project

Security:
- Disable SSL verification only in development (lib/req.js)
- Wrap all JSON.parse(cookie) calls in try-catch via safeJsonParse utility
- Sanitize dangerouslySetInnerHTML in blog/clinic with sanitizeHtml utility
- Fix open redirect in payment page — validate URL origin before redirect
- Fix cookie cleanup on 401 — use js-cookie with correct domain scope

Performance:
- Wrap ItemDoctor with React.memo to prevent unnecessary re-renders
- Replace <img> with Next.js <Image> in blog Caption component

Functionality:
- Fix memory leak in Recode.js — store intervals in refs, cleanup on unmount
- Add null guard on retryIcon.current before classList manipulation
- Fix getParsedUserInfo in helper to handle malformed cookie gracefully

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
hamed
2026-06-07 09:19:20 +03:30
co-authored by Claude Sonnet 4.6
parent 1aa9f82d2a
commit 59e0a0fe4f
13 changed files with 104 additions and 33 deletions
+2 -1
View File
@@ -1,3 +1,4 @@
import { memo } from "react";
import Image from "next/image";
import { Button } from "@mui/material";
import Link from "next/link";
@@ -109,4 +110,4 @@ function ItemDoctor({ doctor, loading, setDoctors, priority = false }) {
);
}
export default ItemDoctor;
export default memo(ItemDoctor);
+3 -1
View File
@@ -4,6 +4,7 @@ import { getUser } from "@/lib/auth";
import { redirect } from "next/navigation";
import { cookies } from "next/headers";
import { fetchReq } from "@/lib/req";
import { safeJsonParse } from "@/lib/sanitize";
async function LayoutPanel({ children }) {
const user = await getUser();
@@ -22,7 +23,8 @@ async function LayoutPanel({ children }) {
const accessToken = cookieStore.get("access_token");
if (userInfo && accessToken) {
const parsedUserInfo = JSON.parse(userInfo.value);
const parsedUserInfo = safeJsonParse(userInfo.value);
if (!parsedUserInfo) return;
const representationUuid = parsedUserInfo?.representation_uuid;
if (representationUuid) {
+7 -2
View File
@@ -199,8 +199,13 @@ export default function PaymentDetailsPage() {
<>
<button
onClick={() => {
const paymentUrl = `${process.env.NEXT_PUBLIC_API_URL}/payment/${payment.uuid}`;
window.location.href = paymentUrl;
try {
const apiOrigin = new URL(process.env.NEXT_PUBLIC_API_URL).origin;
const paymentUrl = new URL(`/payment/${payment.uuid}`, apiOrigin);
if (paymentUrl.origin === apiOrigin) {
window.location.href = paymentUrl.href;
}
} catch {}
}}
className="flex-1 bg-[#5559CE] hover:bg-[#4448b3] text-white font-bold py-3 px-6 rounded-lg transition-colors"
>