From 9e40fcc1184faed64b2bbb9cbb59f56546e24780 Mon Sep 17 00:00:00 2001 From: admin Date: Wed, 1 Apr 2026 22:23:06 +0700 Subject: [PATCH] 690401:2223 fix double warp by cluade opus local work --- backend/src/main.ts | 9 ++--- frontend/proxy.ts | 67 +++++++++++++++++++++++++++--------- frontend/public/favicon.ico | Bin 0 -> 130 bytes frontend/public/robots.txt | 7 ++-- 4 files changed, 55 insertions(+), 28 deletions(-) create mode 100644 frontend/public/favicon.ico diff --git a/backend/src/main.ts b/backend/src/main.ts index 8dbb5d0..b7078f3 100644 --- a/backend/src/main.ts +++ b/backend/src/main.ts @@ -9,10 +9,6 @@ import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import { json, urlencoded } from 'express'; import helmet from 'helmet'; -// Import Custom Interceptors & Filters ที่สร้างใน T1.1 -import { TransformInterceptor } from './common/interceptors/transform.interceptor'; -import { HttpExceptionFilter } from './common/exceptions/http-exception.filter'; - async function bootstrap() { // 1. Create App const app = await NestFactory.create(AppModule); @@ -65,9 +61,8 @@ async function bootstrap() { }) ); - // ลงทะเบียน Global Interceptor และ Filter ที่เราสร้างไว้ - app.useGlobalInterceptors(new TransformInterceptor()); - app.useGlobalFilters(new HttpExceptionFilter()); + // ⚠️ TransformInterceptor & HttpExceptionFilter ลงทะเบียนผ่าน APP_INTERCEPTOR/APP_FILTER ใน CommonModule แล้ว + // ห้ามลงทะเบียนซ้ำที่นี่ เพราะจะทำให้ Response ถูก wrap ซ้อน 2 ชั้น // 📘 6. Swagger Configuration const swaggerConfig = new DocumentBuilder() diff --git a/frontend/proxy.ts b/frontend/proxy.ts index 3708b74..8562ad5 100644 --- a/frontend/proxy.ts +++ b/frontend/proxy.ts @@ -6,10 +6,45 @@ import { auth } from '@/lib/auth'; // รายการ Route ที่ไม่ต้อง Login ก็เข้าได้ (Public Routes) const publicRoutes = ['/login', '/register', '/']; +// 🛡️ Bot/Scanner Patterns - บล็อก requests ที่เป็น automated scanning +const blockedPatterns = [ + // WordPress scanning + /\/wp-includes/i, + /\/wp-content/i, + /\/wp\//i, + /\/wordpress/i, + /\/xmlrpc\.php/i, + /wlwmanifest\.xml/i, + // Environment/config files + /\/\.env/i, + /\/\.env\./i, + /\/config\/\.env/i, + /\/api\/\.env/i, + // Database admin tools + /\/phpmyadmin/i, + /\/adminer/i, + /\/pma/i, + // Common scanner paths + /\/\.git/i, + /\/\.svn/i, + /\/config\.json/i, + /\/package\.json/i, +]; + +function isBlockedPath(path: string): boolean { + return blockedPatterns.some((pattern) => pattern.test(path)); +} + export default auth((req) => { - const isLoggedIn = !!req.auth; const { nextUrl } = req; + // 🛡️ 0. Block Bot/Scanner Requests (ไม่ส่งต่อไป backend) + if (isBlockedPath(nextUrl.pathname)) { + return new NextResponse(null, { status: 404 }); + } + + const isLoggedIn = !!req.auth; + const isPublicRoute = publicRoutes.includes(nextUrl.pathname); const isAuthRoute = nextUrl.pathname.startsWith('/api/auth'); @@ -46,7 +81,7 @@ export default auth((req) => { // 5. Generate CSP with Nonce (Security Rule Tier 1) // ใช้ Nonce Strategy เพื่ออนุญาต Inline Script เฉพาะที่ระบุตัวตนได้ ป้องกัน XSS const nonce = Buffer.from(crypto.randomUUID()).toString('base64'); - + let connectSrcApi = 'http://localhost:3001'; if (process.env.NEXT_PUBLIC_API_URL) { try { @@ -56,21 +91,19 @@ export default auth((req) => { } } - const cspHeader = ` - default-src 'self'; - script-src 'self' 'nonce-${nonce}' 'strict-dynamic' 'unsafe-eval'; - style-src 'self' 'unsafe-inline'; - img-src 'self' blob: data: https:; - font-src 'self' data:; - connect-src 'self' ws: wss: ${connectSrcApi}; - object-src 'none'; - base-uri 'self'; - form-action 'self'; - frame-ancestors 'none'; - upgrade-insecure-requests; - ` - .replace(/\s{2,}/g, ' ') - .trim(); + const cspHeader = [ + "default-src 'self'", + `script-src 'self' 'nonce-${nonce}' 'strict-dynamic' 'unsafe-eval' 'unsafe-inline' http: https:`, + "style-src 'self' 'unsafe-inline'", + "img-src 'self' blob: data: https:", + "font-src 'self' data:", + `connect-src 'self' ws: wss: ${connectSrcApi}`, + "object-src 'none'", + "base-uri 'self'", + "form-action 'self'", + "frame-ancestors 'none'", + "upgrade-insecure-requests", + ].join('; '); const requestHeaders = new Headers(req.headers); requestHeaders.set('x-nonce', nonce); diff --git a/frontend/public/favicon.ico b/frontend/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..2b693885f5cc73d23acd8223d35b5d2e66e09329 GIT binary patch literal 130 mcmZQzU<5(|0R|wcz~I8dz#zuJz@P!dKp~(AL>x%b3;+OnWC0rh literal 0 HcmV?d00001 diff --git a/frontend/public/robots.txt b/frontend/public/robots.txt index 7316641..386d330 100644 --- a/frontend/public/robots.txt +++ b/frontend/public/robots.txt @@ -1,6 +1,5 @@ +# Block all crawlers from accessing any part of the site +# This is an API/application server, not a content site User-agent: * -Disallow: /api/ -Allow: / +Disallow: / -# Sitemap -# Sitemap: https://your-domain.com/sitemap.xml