Merge pull request #179 from shanelord01/audit/remediation-clean

Automated Security & Quality Audit via Claude Code
This commit is contained in:
Maurice
2026-03-31 20:53:48 +02:00
committed by GitHub
28 changed files with 540 additions and 81 deletions

View File

@@ -3,7 +3,6 @@ import { Routes, Route, Navigate, useLocation } from 'react-router-dom'
import { useAuthStore } from './store/authStore'
import { useSettingsStore } from './store/settingsStore'
import LoginPage from './pages/LoginPage'
import RegisterPage from './pages/RegisterPage'
import DashboardPage from './pages/DashboardPage'
import TripPlannerPage from './pages/TripPlannerPage'
import FilesPage from './pages/FilesPage'
@@ -14,7 +13,6 @@ import AtlasPage from './pages/AtlasPage'
import SharedTripPage from './pages/SharedTripPage'
import { ToastContainer } from './components/shared/Toast'
import { TranslationProvider, useTranslation } from './i18n'
import DemoBanner from './components/Layout/DemoBanner'
import { authApi } from './api/client'
interface ProtectedRouteProps {

View File

@@ -72,11 +72,15 @@ export default function GitHubPanel() {
}
}
const escapeHtml = (str) => str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;')
const inlineFormat = (text) => {
return text
return escapeHtml(text)
.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
.replace(/`(.+?)`/g, '<code style="font-size:11px;padding:1px 4px;border-radius:4px;background:var(--bg-secondary)">$1</code>')
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank" rel="noopener noreferrer" style="color:#3b82f6;text-decoration:underline">$1</a>')
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_, label, url) => {
const safeUrl = url.startsWith('http://') || url.startsWith('https://') ? url : '#'
return `<a href="${escapeHtml(safeUrl)}" target="_blank" rel="noopener noreferrer" style="color:#3b82f6;text-decoration:underline">${label}</a>`
})
}
for (const line of lines) {

View File

@@ -13,7 +13,7 @@ export async function calculateRoute(
}
const coords = waypoints.map((p) => `${p.lng},${p.lat}`).join(';')
const url = `${OSRM_BASE}/driving/${coords}?overview=full&geometries=geojson&steps=false`
const url = `${OSRM_BASE}/${profile}/${coords}?overview=full&geometries=geojson&steps=false`
const response = await fetch(url, { signal })
if (!response.ok) {

View File

@@ -29,7 +29,7 @@ interface AuthState {
login: (email: string, password: string) => Promise<LoginResult>
completeMfaLogin: (mfaToken: string, code: string) => Promise<AuthResponse>
register: (username: string, email: string, password: string) => Promise<AuthResponse>
register: (username: string, email: string, password: string, invite_token?: string) => Promise<AuthResponse>
logout: () => void
/** Pass `{ silent: true }` to refresh the user without toggling global isLoading (avoids unmounting protected routes). */
loadUser: (opts?: { silent?: boolean }) => Promise<void>
@@ -126,6 +126,11 @@ export const useAuthStore = create<AuthState>((set, get) => ({
logout: () => {
disconnect()
localStorage.removeItem('auth_token')
// Clear service worker caches containing sensitive data
if ('caches' in window) {
caches.delete('api-data').catch(() => {})
caches.delete('user-uploads').catch(() => {})
}
set({
user: null,
token: null,
@@ -151,13 +156,20 @@ export const useAuthStore = create<AuthState>((set, get) => ({
})
connect(token)
} catch (err: unknown) {
localStorage.removeItem('auth_token')
set({
user: null,
token: null,
isAuthenticated: false,
isLoading: false,
})
// Only clear auth state on 401 (invalid/expired token), not on network errors
const isAuthError = err && typeof err === 'object' && 'response' in err &&
(err as { response?: { status?: number } }).response?.status === 401
if (isAuthError) {
localStorage.removeItem('auth_token')
set({
user: null,
token: null,
isAuthenticated: false,
isLoading: false,
})
} else {
set({ isLoading: false })
}
}
},