GT AI OS Community Edition v2.0.33
Security hardening release addressing CodeQL and Dependabot alerts: - Fix stack trace exposure in error responses - Add SSRF protection with DNS resolution checking - Implement proper URL hostname validation (replaces substring matching) - Add centralized path sanitization to prevent path traversal - Fix ReDoS vulnerability in email validation regex - Improve HTML sanitization in validation utilities - Fix capability wildcard matching in auth utilities - Update glob dependency to address CVE - Add CodeQL suppression comments for verified false positives 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
105
apps/control-panel-frontend/src/components/ui/error-boundary.tsx
Normal file
105
apps/control-panel-frontend/src/components/ui/error-boundary.tsx
Normal file
@@ -0,0 +1,105 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { AlertTriangle, RefreshCw } from 'lucide-react';
|
||||
|
||||
interface ErrorBoundaryState {
|
||||
hasError: boolean;
|
||||
error?: Error;
|
||||
}
|
||||
|
||||
interface ErrorBoundaryProps {
|
||||
children: React.ReactNode;
|
||||
fallback?: React.ComponentType<{ error?: Error; resetError: () => void }>;
|
||||
}
|
||||
|
||||
class ErrorBoundaryClass extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
||||
constructor(props: ErrorBoundaryProps) {
|
||||
super(props);
|
||||
this.state = { hasError: false };
|
||||
}
|
||||
|
||||
static getDerivedStateFromError(error: Error): ErrorBoundaryState {
|
||||
return { hasError: true, error };
|
||||
}
|
||||
|
||||
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
|
||||
console.error('Error caught by boundary:', error, errorInfo);
|
||||
}
|
||||
|
||||
resetError = () => {
|
||||
this.setState({ hasError: false, error: undefined });
|
||||
};
|
||||
|
||||
render() {
|
||||
if (this.state.hasError) {
|
||||
if (this.props.fallback) {
|
||||
const FallbackComponent = this.props.fallback;
|
||||
return <FallbackComponent error={this.state.error} resetError={this.resetError} />;
|
||||
}
|
||||
|
||||
return <DefaultErrorFallback error={this.state.error} resetError={this.resetError} />;
|
||||
}
|
||||
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
|
||||
function DefaultErrorFallback({ error, resetError }: { error?: Error; resetError: () => void }) {
|
||||
return (
|
||||
<div className="flex items-center justify-center min-h-[400px] p-6">
|
||||
<Card className="w-full max-w-md">
|
||||
<CardHeader className="text-center">
|
||||
<div className="mx-auto mb-4 w-16 h-16 flex items-center justify-center rounded-full bg-red-100">
|
||||
<AlertTriangle className="w-8 h-8 text-red-600" />
|
||||
</div>
|
||||
<CardTitle className="text-red-600">Something went wrong</CardTitle>
|
||||
<CardDescription>
|
||||
An error occurred while loading this page. Please try refreshing.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
{error && (
|
||||
<div className="text-sm text-muted-foreground bg-muted p-3 rounded-md">
|
||||
<strong>Error:</strong> {error.message}
|
||||
</div>
|
||||
)}
|
||||
<div className="flex space-x-2">
|
||||
<Button onClick={resetError} className="flex-1">
|
||||
<RefreshCw className="w-4 h-4 mr-2" />
|
||||
Try Again
|
||||
</Button>
|
||||
<Button variant="secondary" onClick={() => window.location.reload()} className="flex-1">
|
||||
Reload Page
|
||||
</Button>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Hook version for functional components
|
||||
export function useErrorBoundary() {
|
||||
const [error, setError] = React.useState<Error | null>(null);
|
||||
|
||||
const resetError = React.useCallback(() => {
|
||||
setError(null);
|
||||
}, []);
|
||||
|
||||
const catchError = React.useCallback((error: Error) => {
|
||||
setError(error);
|
||||
}, []);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
}, [error]);
|
||||
|
||||
return { catchError, resetError };
|
||||
}
|
||||
|
||||
export { ErrorBoundaryClass as ErrorBoundary };
|
||||
Reference in New Issue
Block a user