fix: Phase 5 — XSS sanitization, cookie security, redirect validation, input trimming

- BootScreen + Settings: v-html now uses DOMPurify.sanitize() for SVG content
- FileBrowser cookie: added Secure flag and 24h expiration
- TOTP secret: hidden by default with reveal toggle button
- Login redirect: validates URL is local-origin before redirecting
- Auth fields: password inputs trimmed before submission
- Route params: appId validated against safe pattern, invalid IDs redirect to /apps

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-18 00:55:00 +00:00
parent 5853b6a065
commit 3418c273d4
10 changed files with 84 additions and 24 deletions

View File

@@ -52,7 +52,7 @@
<div class="boot-icon-inner">
<Transition name="icon-morph" mode="out-in">
<div v-if="!bootDone" :key="currentIcon" class="boot-pixel-wrap" :class="{ 'boot-glitch': glitching }">
<div v-html="icons[currentIcon]" />
<div v-html="sanitizedIcon" />
</div>
<div v-else key="logo" class="boot-logo-inner-logo">
<AnimatedLogo size="xl" no-border fit />
@@ -70,7 +70,8 @@
</template>
<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, nextTick, watch } from 'vue'
import { ref, computed, onMounted, onBeforeUnmount, nextTick, watch } from 'vue'
import DOMPurify from 'dompurify'
import AnimatedLogo from '@/components/AnimatedLogo.vue'
const props = defineProps<{ visible: boolean }>()
@@ -158,6 +159,8 @@ const bootMessages = [
{ delay: 23500, prefix: '***', text: 'ALL SYSTEMS OPERATIONAL', type: 'ready' },
]
const sanitizedIcon = computed(() => DOMPurify.sanitize(icons[currentIcon.value] || '', { USE_PROFILES: { svg: true } }))
// Starfield
let animFrame = 0
const stars: { x: number; y: number; z: number }[] = []