-
No matches found.
@foreach (explode("\n", $outputs) as $line)
- @php
- // Skip empty lines
- if (trim($line) === '') {
- continue;
- }
+ @php
+ // Skip empty lines
+ if (trim($line) === '') {
+ continue;
+ }
- // Escape HTML for safety
- $escapedLine = htmlspecialchars($line);
- @endphp
-
- {!! preg_replace(
- '/(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+Z)/',
- '$1',
- $escapedLine,
- ) !!}
-
+ // Parse timestamp from log line (ISO 8601 format: 2025-12-04T11:48:39.136764033Z)
+ $timestamp = '';
+ $logContent = $line;
+ if (preg_match('/^(\d{4})-(\d{2})-(\d{2})T(\d{2}:\d{2}:\d{2})(?:\.(\d+))?Z?\s*(.*)$/', $line, $matches)) {
+ $year = $matches[1];
+ $month = $matches[2];
+ $day = $matches[3];
+ $time = $matches[4];
+ $microseconds = isset($matches[5]) ? substr($matches[5], 0, 6) : '000000';
+ $logContent = $matches[6];
+
+ // Convert month number to abbreviated name
+ $monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+ $monthName = $monthNames[(int)$month - 1] ?? $month;
+
+ // Format: 2025-Dec-04 09:44:58.198879
+ $timestamp = "{$year}-{$monthName}-{$day} {$time}.{$microseconds}";
+ }
+
+ @endphp
+
+ @if ($timestamp)
+ {{ $timestamp }}
+ @endif
+
+
@endforeach
@else
diff --git a/tests/Unit/LogViewerXssSecurityTest.php b/tests/Unit/LogViewerXssSecurityTest.php
new file mode 100644
index 000000000..98c5df3f1
--- /dev/null
+++ b/tests/Unit/LogViewerXssSecurityTest.php
@@ -0,0 +1,427 @@
+alert("XSS")';
+ $escaped = htmlspecialchars($maliciousLog);
+
+ expect($escaped)->toContain('<script>');
+ expect($escaped)->not->toContain('">';
+ $escaped = htmlspecialchars($maliciousLog);
+
+ expect($escaped)->toContain('<iframe');
+ expect($escaped)->toContain('data:');
+ expect($escaped)->not->toContain('