fix(security): resolve audit findings — logging, endpoints, contact details

- Stop logging submitted password forms to the browser console
- Drive analytics from NEXT_PUBLIC_UMAMI_* instead of a hardcoded vendor
  script URL and site ID; renders nothing when unset
- Replace the wildcard image remote host "**" with an explicit allowlist
  (adds DigitalOcean Spaces)
- Fix the socket URL fallback to the API port (:3001, was :4000)
- Replace placeholder and personal contact emails with support@re-quest.com,
  including the privacy policy and terms pages

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-04 11:30:46 +05:30
parent 9c0e7457e5
commit fc932dbc7e
10 changed files with 27 additions and 31 deletions

View File

@@ -7,18 +7,11 @@ const nextConfig: NextConfig = {
// Image optimization // Image optimization
images: { images: {
remotePatterns: [ remotePatterns: [
{ { protocol: "https", hostname: "*.contabostorage.com" },
protocol: "https", { protocol: "https", hostname: "*.amazonaws.com" },
hostname: "**", { protocol: "https", hostname: "*.digitaloceanspaces.com" },
}, { protocol: "http", hostname: "localhost" },
{ { protocol: "http", hostname: "127.0.0.1" },
protocol: "http",
hostname: "localhost",
},
{
protocol: "http",
hostname: "127.0.0.1",
},
], ],
// Don't proxy external images through Next.js server // Don't proxy external images through Next.js server
// Avoids SSL cert issues with Contabo S3 (sin1.contabostorage.com) // Avoids SSL cert issues with Contabo S3 (sin1.contabostorage.com)

View File

@@ -3,8 +3,8 @@
import { SettingsSidebar, PasswordSecurityForm } from '@/components/settings'; import { SettingsSidebar, PasswordSecurityForm } from '@/components/settings';
export default function PasswordSecurityPage() { export default function PasswordSecurityPage() {
const handleSave = (data: { currentPassword: string; newPassword: string }) => { const handleSave = (_data: { currentPassword: string; newPassword: string }) => {
console.log('Updating agent password:', data); // TODO: call the change-password API. Do not log password payloads.
}; };
return ( return (

View File

@@ -3,8 +3,8 @@
import { SettingsSidebar, PasswordSecurityForm } from '@/components/settings'; import { SettingsSidebar, PasswordSecurityForm } from '@/components/settings';
export default function UserPasswordSecurityPage() { export default function UserPasswordSecurityPage() {
const handleSave = (data: { currentPassword: string; newPassword: string }) => { const handleSave = (_data: { currentPassword: string; newPassword: string }) => {
console.log('Updating user password:', data); // TODO: call the change-password API. Do not log password payloads.
}; };
return ( return (

View File

@@ -31,7 +31,7 @@ interface ContactCta {
const defaultContactDetails: ContactDetails = { const defaultContactDetails: ContactDetails = {
title: 'Get In Touch', title: 'Get In Touch',
description: 'Have a question about a property or need assistance? Fill out the form below and our team will get back to you shortly.', description: 'Have a question about a property or need assistance? Fill out the form below and our team will get back to you shortly.',
email: '123support@gmail.com', email: 'support@re-quest.com',
phone: '1234567890', phone: '1234567890',
phoneHours: 'Mon-Fri 9am-6pm', phoneHours: 'Mon-Fri 9am-6pm',
officeAddress: '123 Market Street', officeAddress: '123 Market Street',

View File

@@ -262,7 +262,7 @@ export default function FAQPage() {
Start Live Chat Start Live Chat
</Link> </Link>
<a <a
href="mailto:support@requesn.com" href="mailto:support@re-quest.com"
className="flex items-center justify-center gap-2 w-[174px] h-[51px] border border-[#00293d] rounded-[7px] font-fractul text-[16px] text-[#00293d] hover:bg-gray-50 transition-colors" className="flex items-center justify-center gap-2 w-[174px] h-[51px] border border-[#00293d] rounded-[7px] font-fractul text-[16px] text-[#00293d] hover:bg-gray-50 transition-colors"
> >
<Image <Image

View File

@@ -158,12 +158,15 @@ export default function RootLayout({
<NotificationProvider /> <NotificationProvider />
{children} {children}
</SessionProvider> </SessionProvider>
{/* Umami analytics — loaded after page becomes interactive */} {/* Umami analytics — set NEXT_PUBLIC_UMAMI_URL and NEXT_PUBLIC_UMAMI_WEBSITE_ID to enable */}
{process.env.NEXT_PUBLIC_UMAMI_URL &&
process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID && (
<Script <Script
src="https://analytics.superlabs.co/script.js" src={process.env.NEXT_PUBLIC_UMAMI_URL}
data-website-id="00e1ce31-e174-4519-8b59-63e8d4556b01" data-website-id={process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID}
strategy="afterInteractive" strategy="afterInteractive"
/> />
)}
{/* Microsoft Clarity */} {/* Microsoft Clarity */}
{process.env.NEXT_PUBLIC_CLARITY_ID && ( {process.env.NEXT_PUBLIC_CLARITY_ID && (
<Script id="ms-clarity" strategy="afterInteractive"> <Script id="ms-clarity" strategy="afterInteractive">

View File

@@ -477,10 +477,10 @@ export default function PrivacyPolicyPage() {
<p className="mb-1"> <p className="mb-1">
Email:{' '} Email:{' '}
<a <a
href="mailto:request.sha@gmail.com" href="mailto:support@re-quest.com"
className="text-[#e58625] underline hover:opacity-80" className="text-[#e58625] underline hover:opacity-80"
> >
request.sha@gmail.com support@re-quest.com
</a> </a>
</p> </p>
<p>Address: 1975 Peralta Point, Colorado Springs, CO 80910</p> <p>Address: 1975 Peralta Point, Colorado Springs, CO 80910</p>

View File

@@ -163,7 +163,7 @@ export default function TermsOfServicePage() {
<p className="font-serif text-[15px] leading-[24px] text-[#00293d] mb-4"> <p className="font-serif text-[15px] leading-[24px] text-[#00293d] mb-4">
If you experience any threatening, abusive, or suspicious behavior from another user, please report the If you experience any threatening, abusive, or suspicious behavior from another user, please report the
interaction immediately using the in-app reporting feature or by contacting us at interaction immediately using the in-app reporting feature or by contacting us at
officialteam.request@gmail.com. RE-Quest will investigate reported incidents and take appropriate action, support@re-quest.com. RE-Quest will investigate reported incidents and take appropriate action,
which may include account suspension or referral to law enforcement. which may include account suspension or referral to law enforcement.
</p> </p>
@@ -464,7 +464,7 @@ export default function TermsOfServicePage() {
If you have any questions or concerns about these Terms, please contact us: If you have any questions or concerns about these Terms, please contact us:
</p> </p>
<p className="font-serif text-[15px] leading-[24px] text-[#00293d] mb-1"> <p className="font-serif text-[15px] leading-[24px] text-[#00293d] mb-1">
<span className="font-bold">Email:</span> officialteam.request@gmail.com <span className="font-bold">Email:</span> support@re-quest.com
</p> </p>
<p className="font-serif text-[15px] leading-[24px] text-[#00293d]"> <p className="font-serif text-[15px] leading-[24px] text-[#00293d]">
<span className="font-bold">Address:</span> 1975 Peralta Point, Colorado Springs, CO 80910 <span className="font-bold">Address:</span> 1975 Peralta Point, Colorado Springs, CO 80910

View File

@@ -270,10 +270,10 @@ export function SubscriptionForm() {
{/* Support Email */} {/* Support Email */}
<Link <Link
href="mailto:support@example.com" href="mailto:support@re-quest.com"
className="font-serif font-bold text-[14px] text-[#e58625] underline hover:text-[#d47920] transition-colors" className="font-serif font-bold text-[14px] text-[#e58625] underline hover:text-[#d47920] transition-colors"
> >
support@example.com support@re-quest.com
</Link> </Link>
</div> </div>

View File

@@ -59,7 +59,7 @@ class SocketService {
} }
// Extract base URL without /api/v1 path for Socket.io connection // Extract base URL without /api/v1 path for Socket.io connection
const apiUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:4000'; const apiUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001/api/v1';
const baseUrl = apiUrl.replace(/\/api\/v1\/?$/, ''); const baseUrl = apiUrl.replace(/\/api\/v1\/?$/, '');
this.socket = io(baseUrl, { this.socket = io(baseUrl, {