chore: prevent sensitive data caching
This commit is contained in:
parent
eaef04a0a0
commit
6b0f90f355
6 changed files with 35 additions and 5 deletions
|
|
@ -238,6 +238,24 @@ func (s *APIV1Service) UpdateUser(ctx context.Context, request *v1pb.UpdateUserR
|
|||
case "email":
|
||||
update.Email = &request.User.Email
|
||||
case "avatar_url":
|
||||
// Validate avatar MIME type to prevent XSS during upload
|
||||
if request.User.AvatarUrl != "" {
|
||||
imageType, _, err := extractImageInfo(request.User.AvatarUrl)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "invalid avatar format: %v", err)
|
||||
}
|
||||
// Only allow safe image formats for avatars
|
||||
allowedAvatarTypes := map[string]bool{
|
||||
"image/png": true,
|
||||
"image/jpeg": true,
|
||||
"image/jpg": true,
|
||||
"image/gif": true,
|
||||
"image/webp": true,
|
||||
}
|
||||
if !allowedAvatarTypes[imageType] {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "invalid avatar image type: %s. Only PNG, JPEG, GIF, and WebP are allowed", imageType)
|
||||
}
|
||||
}
|
||||
update.AvatarURL = &request.User.AvatarUrl
|
||||
case "description":
|
||||
update.Description = &request.User.Description
|
||||
|
|
|
|||
|
|
@ -35,8 +35,12 @@ func (*FrontendService) Serve(_ context.Context, e *echo.Echo) {
|
|||
if util.HasPrefixes(c.Path(), "/api", "/memos.api.v1") {
|
||||
return true
|
||||
}
|
||||
// Skip setting cache headers for index.html
|
||||
// For index.html and root path, set no-cache headers to prevent browser caching
|
||||
// This prevents sensitive data from being accessible via browser back button after logout
|
||||
if c.Path() == "/" || c.Path() == "/index.html" {
|
||||
c.Response().Header().Set(echo.HeaderCacheControl, "no-cache, no-store, must-revalidate")
|
||||
c.Response().Header().Set("Pragma", "no-cache")
|
||||
c.Response().Header().Set("Expires", "0")
|
||||
return false
|
||||
}
|
||||
// Set Cache-Control header for static assets.
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||
<meta http-equiv="Pragma" content="no-cache" />
|
||||
<meta http-equiv="Expires" content="0" />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
||||
<link rel="icon" type="image/webp" href="/logo.webp" />
|
||||
<link rel="manifest" href="/site.webmanifest" />
|
||||
|
|
|
|||
|
|
@ -64,7 +64,9 @@ const UserMenu = observer((props: Props) => {
|
|||
|
||||
keysToRemove.forEach((key) => localStorage.removeItem(key));
|
||||
|
||||
window.location.href = Routes.AUTH;
|
||||
// Use replace() instead of href to prevent back button from showing cached sensitive data
|
||||
// This removes the current page from browser history
|
||||
window.location.replace(Routes.AUTH);
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -92,7 +92,9 @@ function getAuthFailureRedirect(currentPath: string): string | null {
|
|||
|
||||
function performRedirect(redirectUrl: string | null): void {
|
||||
if (redirectUrl) {
|
||||
window.location.href = redirectUrl;
|
||||
// Use replace() instead of href to prevent back button from showing cached sensitive data
|
||||
// This removes the current page from browser history after authentication failure
|
||||
window.location.replace(redirectUrl);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,12 +24,13 @@ const RootLayout = observer(() => {
|
|||
if (!currentUser) {
|
||||
// If disallowPublicVisibility is enabled, redirect to the login page if the user is not logged in.
|
||||
if (instanceStore.state.memoRelatedSetting.disallowPublicVisibility) {
|
||||
window.location.href = Routes.AUTH;
|
||||
// Use replace() to prevent back button from showing cached sensitive data
|
||||
window.location.replace(Routes.AUTH);
|
||||
return;
|
||||
} else if (
|
||||
([Routes.ROOT, Routes.ATTACHMENTS, Routes.INBOX, Routes.ARCHIVED, Routes.SETTING] as string[]).includes(location.pathname)
|
||||
) {
|
||||
window.location.href = Routes.EXPLORE;
|
||||
window.location.replace(Routes.EXPLORE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue