cebcf4f1f5
**Small Security Issue:** CSV exports were vulnerable to formula injection attacks when users entered values starting with =, +, -, or @. (only happens if a logged-in user injects corrupted data) Solution: - Added ZWJ (Zero-Width Joiner) protection that prefixes dangerous values with invisible Unicode character - This is the best way to preserve original data while preventing Excel from executing formulas - Added import cleanup to restore original values when re-importing Changes: - New sanitizeValueForCSVExport() function for security - Updated all CSV export paths to use both security + formatting functions - Added comprehensive tests covering attack vectors and international characters - Also added cursor rules for better code consistency --------- Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
43 lines
1.5 KiB
TypeScript
43 lines
1.5 KiB
TypeScript
import { useIsLogged } from '@/auth/hooks/useIsLogged';
|
|
import { useHasPermissionFlag } from '@/settings/roles/hooks/useHasPermissionFlag';
|
|
import { SettingsPath } from '@/types/SettingsPath';
|
|
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
|
import { type ReactNode } from 'react';
|
|
import { Navigate, Outlet } from 'react-router-dom';
|
|
import {
|
|
type FeatureFlagKey,
|
|
type PermissionFlagType,
|
|
} from '~/generated/graphql';
|
|
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
|
|
|
|
type SettingsProtectedRouteWrapperProps = {
|
|
children?: ReactNode;
|
|
settingsPermission?: PermissionFlagType;
|
|
requiredFeatureFlag?: FeatureFlagKey;
|
|
};
|
|
|
|
export const SettingsProtectedRouteWrapper = ({
|
|
children,
|
|
settingsPermission,
|
|
requiredFeatureFlag,
|
|
}: SettingsProtectedRouteWrapperProps) => {
|
|
const isLoggedIn = useIsLogged();
|
|
const hasPermission = useHasPermissionFlag(settingsPermission);
|
|
const requiredFeatureFlagEnabled = useIsFeatureEnabled(
|
|
requiredFeatureFlag || null,
|
|
);
|
|
|
|
if (!isLoggedIn) {
|
|
return null;
|
|
}
|
|
|
|
// TODO: this should be part of PageChangeEffect as otherwise we will have multiple sources of redirection that can:
|
|
// - conflict (race conditions)
|
|
// - degrade performance as we will redirect multiple times
|
|
if ((requiredFeatureFlag && !requiredFeatureFlagEnabled) || !hasPermission) {
|
|
return <Navigate to={getSettingsPath(SettingsPath.ProfilePage)} replace />;
|
|
}
|
|
|
|
return children ?? <Outlet />;
|
|
};
|