From 97af951ec0f80b1c09bb2c51235ecd765f9423c0 Mon Sep 17 00:00:00 2001 From: Agus Arya <190161908+auttomus@users.noreply.github.com> Date: Sun, 7 Jun 2026 15:56:28 +0800 Subject: [PATCH 1/4] Potential fix for code scanning alert no. 6: Incomplete URL substring sanitization Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- .../orders/components/OrderDetailView.tsx | 45 +++++++++++++------ 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/frontend/app/features/orders/components/OrderDetailView.tsx b/frontend/app/features/orders/components/OrderDetailView.tsx index a260e19..d654a2f 100644 --- a/frontend/app/features/orders/components/OrderDetailView.tsx +++ b/frontend/app/features/orders/components/OrderDetailView.tsx @@ -141,19 +141,38 @@ export function OrderDetailView({ orderId }: OrderDetailViewProps) { )} - {order.listing.digitalLink && ( - - - {order.listing.digitalLink.includes("drive.google.com") || order.listing.digitalLink.includes("docs.google.com") - ? "Buka Tautan Google Drive" - : "Akses Tautan Eksternal"} - - )} + {order.listing.digitalLink && (() => { + const externalHref = order.listing.digitalLink.startsWith("http") + ? order.listing.digitalLink + : `https://${order.listing.digitalLink}`; + + let externalHost = ""; + try { + externalHost = new URL(externalHref).hostname.toLowerCase(); + } catch { + externalHost = ""; + } + + const isGoogleDocsOrDrive = + externalHost === "drive.google.com" || + externalHost.endsWith(".drive.google.com") || + externalHost === "docs.google.com" || + externalHost.endsWith(".docs.google.com"); + + return ( + + + {isGoogleDocsOrDrive + ? "Buka Tautan Google Drive" + : "Akses Tautan Eksternal"} + + ); + })()} ) : (
From 6309aa36feaf1f34d262252717124f240650d5dd Mon Sep 17 00:00:00 2001 From: Agus Arya <190161908+auttomus@users.noreply.github.com> Date: Sun, 7 Jun 2026 16:12:17 +0800 Subject: [PATCH 2/4] Potential fix for code scanning alert no. 4: Incomplete URL substring sanitization Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- .../create/ListingDigitalProductStep.tsx | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/frontend/app/features/listings/components/create/ListingDigitalProductStep.tsx b/frontend/app/features/listings/components/create/ListingDigitalProductStep.tsx index be9c05d..493716a 100644 --- a/frontend/app/features/listings/components/create/ListingDigitalProductStep.tsx +++ b/frontend/app/features/listings/components/create/ListingDigitalProductStep.tsx @@ -59,10 +59,27 @@ export function ListingDigitalProductStep() { } }; - const isGoogleDrive = listingData.digitalLink.toLowerCase().includes("drive.google.com") || - listingData.digitalLink.toLowerCase().includes("docs.google.com"); - - const isDropbox = listingData.digitalLink.toLowerCase().includes("dropbox.com"); + const hasAllowedHost = (url: string, allowedHosts: string[]) => { + try { + const hostname = new URL(url).hostname.toLowerCase(); + return allowedHosts.some((allowedHost) => { + const normalizedAllowedHost = allowedHost.toLowerCase(); + return ( + hostname === normalizedAllowedHost || + hostname.endsWith(`.${normalizedAllowedHost}`) + ); + }); + } catch { + return false; + } + }; + + const isGoogleDrive = hasAllowedHost(listingData.digitalLink, [ + "drive.google.com", + "docs.google.com", + ]); + + const isDropbox = hasAllowedHost(listingData.digitalLink, ["dropbox.com"]); return (
From 30561a9d99dc9705b58f33ea029177cc762f8afb Mon Sep 17 00:00:00 2001 From: Auttomus <190161908+auttomus@users.noreply.github.com> Date: Sun, 7 Jun 2026 16:17:15 +0800 Subject: [PATCH 3/4] chore: update lockfile dependencies --- backend/pnpm-lock.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/pnpm-lock.yaml b/backend/pnpm-lock.yaml index 40205ea..49c8eab 100644 --- a/backend/pnpm-lock.yaml +++ b/backend/pnpm-lock.yaml @@ -2512,8 +2512,8 @@ packages: fast-safe-stringify@2.1.1: resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} - fast-uri@3.1.0: - resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + fast-uri@3.1.2: + resolution: {integrity: sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==} fast-xml-builder@1.2.0: resolution: {integrity: sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q==} @@ -6028,14 +6028,14 @@ snapshots: ajv@8.18.0: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.1.0 + fast-uri: 3.1.2 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 ajv@8.20.0: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.1.0 + fast-uri: 3.1.2 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 @@ -6845,7 +6845,7 @@ snapshots: fast-safe-stringify@2.1.1: {} - fast-uri@3.1.0: {} + fast-uri@3.1.2: {} fast-xml-builder@1.2.0: dependencies: From fbaac23ec68d368d61dd5221ab88af81417b8e03 Mon Sep 17 00:00:00 2001 From: Agus Arya <190161908+auttomus@users.noreply.github.com> Date: Sun, 7 Jun 2026 16:22:10 +0800 Subject: [PATCH 4/4] Potential fix for code scanning alert no. 1: Loop bound injection Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- backend/src/modules/iam/iam.service.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/backend/src/modules/iam/iam.service.ts b/backend/src/modules/iam/iam.service.ts index 48be185..b7b252d 100644 --- a/backend/src/modules/iam/iam.service.ts +++ b/backend/src/modules/iam/iam.service.ts @@ -154,7 +154,10 @@ export class IamService { * Membuat inisial nama dengan desain premium & gradasi warna yang dinamis */ function generateSvgAvatar(name: string): string { - const initial = name ? name.trim().charAt(0).toUpperCase() : '?'; + const MAX_NAME_LENGTH = 128; + const safeName = + typeof name === 'string' ? name.trim().slice(0, MAX_NAME_LENGTH) : ''; + const initial = safeName ? safeName.charAt(0).toUpperCase() : '?'; // Daftar warna gradasi premium yang modern dan estetis const gradients = [ @@ -168,8 +171,8 @@ function generateSvgAvatar(name: string): string { // Hitung hash deterministik dari nama agar pengguna yang sama selalu mendapat gradasi warna yang sama let hash = 0; - for (let i = 0; i < name.length; i++) { - hash = name.charCodeAt(i) + ((hash << 5) - hash); + for (let i = 0; i < safeName.length; i++) { + hash = safeName.charCodeAt(i) + ((hash << 5) - hash); } const index = Math.abs(hash) % gradients.length; const { start, end } = gradients[index];