-
Notifications
You must be signed in to change notification settings - Fork 74
fix(frontend): prevent PII leaks in production console logs #262
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,8 +2,7 @@ | |||||||||||||||||
|
|
||||||||||||||||||
| import { useEffect } from 'react'; | ||||||||||||||||||
| import { Button } from '@/components/ui/button'; | ||||||||||||||||||
| import { AlertTriangle, RefreshCw, Home } from 'lucide-react'; | ||||||||||||||||||
| import { errorReporter } from '@/lib/error-reporting'; | ||||||||||||||||||
| import { logger } from '@/lib/logger'; | ||||||||||||||||||
|
|
||||||||||||||||||
| export default function Error({ | ||||||||||||||||||
| error, | ||||||||||||||||||
|
|
@@ -13,67 +12,24 @@ export default function Error({ | |||||||||||||||||
| reset: () => void; | ||||||||||||||||||
| }) { | ||||||||||||||||||
| useEffect(() => { | ||||||||||||||||||
| errorReporter.reportError(error, { | ||||||||||||||||||
| level: 'page', | ||||||||||||||||||
| context: { | ||||||||||||||||||
| digest: error.digest, | ||||||||||||||||||
| type: 'route-error' | ||||||||||||||||||
| } | ||||||||||||||||||
| }); | ||||||||||||||||||
| logger.error('Application error:', error); | ||||||||||||||||||
| }, [error]); | ||||||||||||||||||
|
Comment on lines
14
to
16
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only log sanitized error identifiers in production. Passing the full 🛡️ Proposed fix useEffect(() => {
- logger.error('Application error:', error);
+ logger.error('Application error', error.digest ? { digest: error.digest } : undefined);
+ logger.debug('Application error details', error);
}, [error]);📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
|
|
||||||||||||||||||
| const handleGoHome = () => { | ||||||||||||||||||
| if (typeof window !== 'undefined') { | ||||||||||||||||||
| window.location.href = '/'; | ||||||||||||||||||
| } | ||||||||||||||||||
| }; | ||||||||||||||||||
|
|
||||||||||||||||||
| return ( | ||||||||||||||||||
| <div className="flex min-h-[400px] flex-col items-center justify-center gap-4 p-6 text-center"> | ||||||||||||||||||
| <div className="rounded-full bg-red-100 dark:bg-red-900/30 p-3"> | ||||||||||||||||||
| <AlertTriangle className="h-8 w-8 text-red-600 dark:text-red-400" /> | ||||||||||||||||||
| </div> | ||||||||||||||||||
|
|
||||||||||||||||||
| <div className="space-y-2"> | ||||||||||||||||||
| <h2 className="text-xl font-semibold text-foreground">Page Error</h2> | ||||||||||||||||||
| <p className="text-sm text-muted-foreground max-w-md"> | ||||||||||||||||||
| This page encountered an unexpected error. You can try again or return to the home page. | ||||||||||||||||||
| </p> | ||||||||||||||||||
| {error.digest && ( | ||||||||||||||||||
| <p className="text-xs text-muted-foreground mt-2"> | ||||||||||||||||||
| Error ID: {error.digest} | ||||||||||||||||||
| </p> | ||||||||||||||||||
| )} | ||||||||||||||||||
|
|
||||||||||||||||||
| {process.env.NODE_ENV === 'development' && ( | ||||||||||||||||||
| <details className="mt-4 text-left"> | ||||||||||||||||||
| <summary className="cursor-pointer text-xs text-muted-foreground hover:text-foreground"> | ||||||||||||||||||
| Error Details (Development) | ||||||||||||||||||
| </summary> | ||||||||||||||||||
| <div className="mt-2 p-3 bg-muted rounded-md text-xs font-mono text-left overflow-auto max-h-32"> | ||||||||||||||||||
| <div className="text-red-600 dark:text-red-400 font-semibold"> | ||||||||||||||||||
| {error.name}: {error.message} | ||||||||||||||||||
| </div> | ||||||||||||||||||
| {error.stack && ( | ||||||||||||||||||
| <pre className="mt-2 text-muted-foreground whitespace-pre-wrap"> | ||||||||||||||||||
| {error.stack} | ||||||||||||||||||
| </pre> | ||||||||||||||||||
| )} | ||||||||||||||||||
| </div> | ||||||||||||||||||
| </details> | ||||||||||||||||||
| )} | ||||||||||||||||||
| <div className="flex min-h-[400px] flex-col items-center justify-center gap-4 p-4 text-center"> | ||||||||||||||||||
| <div className="rounded-full bg-red-100 p-3"> | ||||||||||||||||||
| <svg className="h-6 w-6 text-red-600" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||||||||||||||||
| <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" /> | ||||||||||||||||||
| </svg> | ||||||||||||||||||
| </div> | ||||||||||||||||||
|
|
||||||||||||||||||
| <div className="flex gap-2"> | ||||||||||||||||||
| <Button onClick={reset} variant="outline" size="sm"> | ||||||||||||||||||
| <RefreshCw className="w-4 h-4 mr-2" /> | ||||||||||||||||||
| Try again | ||||||||||||||||||
| </Button> | ||||||||||||||||||
| <Button onClick={handleGoHome} variant="default" size="sm"> | ||||||||||||||||||
| <Home className="w-4 h-4 mr-2" /> | ||||||||||||||||||
| Go home | ||||||||||||||||||
| </Button> | ||||||||||||||||||
| <div> | ||||||||||||||||||
| <h2 className="text-lg font-semibold text-foreground">Something went wrong</h2> | ||||||||||||||||||
| <p className="text-sm text-muted-foreground mt-1">An unexpected error occurred</p> | ||||||||||||||||||
| {error.digest && <p className="text-xs text-muted-foreground mt-2">Error ID: {error.digest}</p>} | ||||||||||||||||||
| </div> | ||||||||||||||||||
| <Button onClick={reset} variant="outline"> | ||||||||||||||||||
| Try again | ||||||||||||||||||
| </Button> | ||||||||||||||||||
| </div> | ||||||||||||||||||
| ); | ||||||||||||||||||
| } | ||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don’t escalate fallback stats failures to production errors.
This path intentionally falls back without user-facing error UI, but
logger.erroremits the raw caught error in production. Use a debug-gated warning unless there is sanitized telemetry behind it.🔧 Proposed fix
} catch (err) { // Fallback: show loading state instead of error UI - logger.error('Business stats error:', err); + logger.warn('Business stats error', err); } finally {📝 Committable suggestion
🤖 Prompt for AI Agents