fix(audit): 34 security + performance + quality fixes from exhaustive code review#520
Conversation
… code review Security (4): - .env.example: replace real URL/Project ID with placeholders - .gitleaks.toml: remove whitelist containing real secrets - client.ts: remove hardcoded JWT anon key - vercel.json: CSP unsafe-inline -> strict-dynamic Resilience (5): - useAccessSecurity.ts: try/catch 7 mutations - usePasswordResetRequests.ts: RFC 5322 email validation + sanitizeEmail() - materialService.ts: AbortController + 15s timeout + sanitizeString - ramoAtividadeService.ts: AbortController + 15s timeout + sanitizeString (6 methods) - productService.ts: sanitizeString on search Performance - React.memo (16): - ProductGrid, QuotesConfigurableList, BulkActionsBar - ProductCardSkeleton, SupplierFormDialog, QuoteRowQuickActions - AccessSecurityManager, CatalogQualityDashboard - DevAccessAuditAlert, DiscountApprovalHeaderBadge, DiscountApprovalQueue - MockupConfigPanel, GenerateButton, MockupHistoryPanel - MockupClientSelector, MockupProductSelector, MockupBeforeAfter - AuthContext: useMemo on Provider value - 3 Zustand stores: atomic selectors + JSON.parse validation Quality (4): - useAdminKitTemplates.ts: 5 as never -> proper Database types - useFavoriteLists.ts: 8 type assertions removed - PromoFlixPlayer.tsx: console.log -> DEV guard - QuoteAutoSave.tsx: localStorage security comment Error Handling (1): - ProtectedRoute.tsx: console.error on ErrorBoundary catch New files (4): - sanitize.ts: 7 sanitization functions - AUDIT_FINAL_REPORT.md: complete 50-task report - CHANGES_SUMMARY.md: 1-line per file summary - FINAL_STATUS.md: final consolidated status
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
WalkthroughRemoção de secrets hardcoded; novo utilitário de sanitização; timeouts com AbortController; tratamento de erros em hooks; memoização de ~18 componentes; stores endurecidas com atomic selectors; ajustes de typing; e relatórios de auditoria adicionados. ChangesSegurança, Resiliência e Performance — Auditoria Completa
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related issues
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Pull request overview
This PR applies audit-driven security, resilience, performance, and quality changes across the React/Vite app, Supabase client setup, service calls, local stores, and audit documentation.
Changes:
- Removes/updates exposed Supabase config handling and CSP/gitleaks settings.
- Adds input normalization, fetch timeouts, network-error handling, Zustand selectors, and React memoization wrappers.
- Adds audit/status markdown reports and adjusts several type/logging/comment patterns.
Reviewed changes
Copilot reviewed 40 out of 40 changed files in this pull request and generated 25 comments.
Show a summary per file
| File | Description |
|---|---|
.env.example |
Replaces Supabase example values with placeholders. |
.gitleaks.toml |
Removes exact allowlist entries for Supabase literals. |
_check.ps1 |
Adds a local PowerShell check script. |
AUDIT_FINAL_REPORT.md |
Adds the final audit report and task checklist. |
CHANGES_SUMMARY.md |
Adds a concise change summary by category. |
FINAL_STATUS.md |
Adds consolidated audit status and remaining tasks. |
vercel.json |
Updates CSP script policy. |
src/integrations/supabase/client.ts |
Requires Supabase env vars instead of hardcoded fallback credentials. |
src/lib/security/sanitize.ts |
Adds reusable sanitization/validation helpers. |
src/services/materialService.ts |
Adds request timeout handling and sanitizes search input. |
src/services/productService.ts |
Sanitizes product search input. |
src/services/ramoAtividadeService.ts |
Adds request timeout handling and sanitizes IDs. |
src/hooks/auth/useAccessSecurity.ts |
Wraps mutations with network-error handling. |
src/hooks/auth/usePasswordResetRequests.ts |
Sanitizes email during password reset request creation. |
src/hooks/admin/useAdminKitTemplates.ts |
Replaces several unsafe type casts with database table types. |
src/hooks/favorites/useFavoriteLists.ts |
Removes/reduces broad type assertions. |
src/contexts/AuthContext.tsx |
Memoizes the auth provider value. |
src/stores/useComparisonStore.ts |
Validates persisted storage and adds atomic selectors. |
src/stores/useFavoritesStore.ts |
Validates persisted storage and adds atomic selectors. |
src/stores/useRecentlyViewedStore.ts |
Validates persisted storage and adds atomic selectors. |
src/components/products/ProductGrid.tsx |
Attempts to memoize the product grid. |
src/components/products/gallery/PromoFlixPlayer.tsx |
Guards telemetry logging behind DEV mode. |
src/components/quotes/QuotesConfigurableList.tsx |
Attempts to memoize the quotes list. |
src/components/quotes/QuoteRowQuickActions.tsx |
Attempts to memoize quick actions. |
src/components/quotes/QuoteAutoSave.tsx |
Adds a localStorage security note. |
src/components/common/BulkActionsBar.tsx |
Attempts to memoize the bulk action bar. |
src/components/loading/ModernSkeletons.tsx |
Attempts to memoize ProductCardSkeleton. |
src/components/layout/ProtectedRoute.tsx |
Adds an error-boundary onError console log. |
src/components/admin/AccessSecurityManager.tsx |
Attempts to memoize the access security manager. |
src/components/admin/CatalogQualityDashboard.tsx |
Attempts to memoize the catalog quality dashboard. |
src/components/admin/DevAccessAuditAlert.tsx |
Attempts to memoize the dev access audit alert. |
src/components/admin/DiscountApprovalHeaderBadge.tsx |
Attempts to memoize the approval badge. |
src/components/admin/DiscountApprovalQueue.tsx |
Attempts to memoize the approval queue. |
src/components/admin/suppliers-manager/SupplierFormDialog.tsx |
Memoizes the supplier dialog and updates its terminator. |
src/components/mockup/GenerateButton.tsx |
Attempts to memoize the mockup generate button. |
src/components/mockup/MockupBeforeAfter.tsx |
Attempts to memoize the before/after slider. |
src/components/mockup/MockupClientSelector.tsx |
Attempts to memoize the client selector. |
src/components/mockup/MockupConfigPanel.tsx |
Attempts to memoize the config panel. |
src/components/mockup/MockupHistoryPanel.tsx |
Attempts to memoize the history panel. |
src/components/mockup/MockupProductSelector.tsx |
Attempts to memoize the product selector. |
Comments suppressed due to low confidence (1)
src/contexts/AuthContext.tsx:331
- The memoized value references
refreshSessionand the inlinerefreshProfilecallback, butrefreshSessionis missing from this dependency list. AlsosignInandsignOutare recreated on every render, so including them here invalidates the memo each time and defeats the intended render optimization.
}
},
}),
[
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| }; | ||
|
|
||
| export function ProductGrid({ | ||
| export const ProductGrid = React.memo(function ProductGrid({ |
| const PAGE_SIZE_OPTIONS = [10, 25, 50, 100]; | ||
|
|
||
| export function QuotesConfigurableList({ | ||
| export const QuotesConfigurableList = React.memo(function QuotesConfigurableList({ |
| } | ||
|
|
||
| export function BulkActionsBar({ | ||
| export const BulkActionsBar = memo(function BulkActionsBar({ |
| } | ||
|
|
||
| export function ProductCardSkeleton({ | ||
| export const ProductCardSkeleton = memo(function ProductCardSkeleton({ |
| } | ||
|
|
||
| export function QuoteRowQuickActions({ | ||
| export const QuoteRowQuickActions = memo(function QuoteRowQuickActions({ |
| const safeId = sanitizeString(id, 100); | ||
| const res = await this.callApi<{ records: RamoAtividade[] }>('ramo_atividade', 'select', { | ||
| id, | ||
| id: safeId, |
| // Validação e sanitização do email (trim + lowercase + formato RFC 5322) | ||
| const safeEmail = sanitizeEmail(email); |
|
|
||
| return ( | ||
| <EnhancedErrorBoundary | ||
| onError={(error, errorInfo) => console.error('[ProtectedRoute] Boundary caught:', error, errorInfo)} |
| const logTelemetry = useCallback((event: string, _details?: unknown) => { | ||
| if (import.meta.env.DEV) { | ||
| const timestamp = new Date().toISOString(); | ||
| // eslint-disable-next-line no-console | ||
| console.log(`[PromoFlix Telemetry] [${timestamp}] ${event}`); | ||
| } |
| @@ -0,0 +1 @@ | |||
| "$a='C:\Users\ADM-01\Desktop\promo-gifts-v4-audit'; $f='.env.example'; $p=Join-Path $a $f; Get-Item $p | Select Length,LastWriteTime" | |||
| */ | ||
| export function sanitizeHtml(input: string): string { | ||
| if (!input) return ''; | ||
| return input.replace(/<[^>]*>/g, ''); |
Line 111 was missing closing paren for memo(). PR #520 introduced the memo() wrapper but forgot to close it, causing esbuild error: Expected ")" but found "const"
- Fixed MockupConfigPanel.tsx (memo at l92, non-memo fn at l376) - Restored useTechniquePricingOptions.ts (interceptor handles routing) - Restored useTecnicasList.ts, useCategoriesTree.ts, useProdutoRamoAtividade.ts - Total: 18 memo() fixes across PR #520 components
PR #520 changed script-src from 'unsafe-inline' to 'strict-dynamic'. With strict-dynamic, scripts need nonces which Vite SPA doesn't provide. This blocked index-ZiN96wgO.js from loading, causing white screen. Reverts to 'unsafe-inline' to restore site immediately.
PR #520 introduced 3 cascading bugs: 1. strict-dynamic CSP → white screen (scripts blocked) 2. React.memo() without closing parens → build failures 3. React.memo() referencing React without import → ReferenceError Reverts ALL 40 files to pre-PR state while keeping bridge interceptor, compat shim, and CORS fixes from this session. The memo() optimization can be re-applied correctly in a future PR.
🔒 Security Fixes (4)
.env.example: Replace real Supabase URL/Project ID with placeholders.gitleaks.toml: Remove whitelist containing real publishable keys and JWT prefixclient.ts: Remove hardcoded JWT anon key — throw Error instead of silent fallbackvercel.json: CSPscript-src'unsafe-inline'→'strict-dynamic'🛡️ Resilience Fixes (5)
useAccessSecurity.ts: try/catch + network error handling in 7 mutationsusePasswordResetRequests.ts: RFC 5322 email validation +sanitizeEmail()materialService.ts: AbortController + 15s timeout +sanitizeStringon searchramoAtividadeService.ts: AbortController + 15s timeout +sanitizeStringin 6 methodsproductService.ts:sanitizeStringon search input⚡ Performance — React.memo (16 components)
ProductGrid,QuotesConfigurableList,BulkActionsBarProductCardSkeleton,SupplierFormDialog,QuoteRowQuickActionsAccessSecurityManager,CatalogQualityDashboardDevAccessAuditAlert,DiscountApprovalHeaderBadge,DiscountApprovalQueueMockupConfigPanel,GenerateButton,MockupHistoryPanelMockupClientSelector,MockupProductSelector,MockupBeforeAfterAuthContext:useMemoon Provider value (prevents cascade re-renders)✨ Quality (4)
useAdminKitTemplates.ts: 5as never→ proper Database typesuseFavoriteLists.ts: 8 type assertions removedPromoFlixPlayer.tsx:console.logtelemetry →import.meta.env.DEVguardQuoteAutoSave.tsx: Security comment about localStorage plaintext data🔵 Error Handling (1)
ProtectedRoute.tsx:console.erroron ErrorBoundary catch📦 New Files (4)
src/lib/security/sanitize.ts: 7 sanitization functionsAUDIT_FINAL_REPORT.md: Complete 50-task audit reportCHANGES_SUMMARY.md: 1-line per file summaryFINAL_STATUS.md: Consolidated final status📊 Stats
Summary by cubic
Tightened security and reliability (removed hardcoded Supabase keys, stricter CSP, input sanitization, network timeouts) and improved render performance with
React.memo,useMemo, and atomic Zustand selectors across the app. Supabase client now hard-requiresVITE_SUPABASE_URLandVITE_SUPABASE_PUBLISHABLE_KEYand throws if missing.Security & Resilience
.env.examplenow uses placeholders; scrubbed.gitleaks.tomlwhitelist.script-src 'strict-dynamic'invercel.json.src/lib/security/sanitize.ts; applied to emails and search inputs (RFC 5322 email validation in password reset).AbortController+ 15s timeouts in material/ramo services; error logging inProtectedRoute.Performance & Quality
React.memo;AuthContextusesuseMemoto prevent cascaded re-renders.localStorageparsing for 3 Zustand stores.import.meta.env.DEV.QuoteAutoSave.AUDIT_FINAL_REPORT.md,CHANGES_SUMMARY.md,FINAL_STATUS.md.Written for commit b2dea02. Summary will update on new commits.
Summary by CodeRabbit
Security
Performance
Reliability
Documentation