Fix XSS: escape table data and sanitize sort/pagination URL params
- htmlspecialchars() on category, type, status in table rows - htmlspecialchars() on data-status attributes in quick-action buttons - Restrict $currentDir to 'asc'|'desc' to prevent class injection - htmlspecialchars() on all http_build_query URLs in pagination and sort headers - htmlspecialchars() on AuditLogView pagination URLs Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -291,7 +291,7 @@ $nonce = SecurityHeadersMiddleware::getNonce();
|
||||
// Previous page button
|
||||
if ($page > 1) {
|
||||
$currentParams['page'] = $page - 1;
|
||||
$prevUrl = '?' . http_build_query($currentParams);
|
||||
$prevUrl = htmlspecialchars('?' . http_build_query($currentParams), ENT_QUOTES, 'UTF-8');
|
||||
echo "<button data-action='navigate' data-url='$prevUrl' aria-label='Previous page'>[ « ]</button>";
|
||||
}
|
||||
|
||||
@@ -299,14 +299,14 @@ $nonce = SecurityHeadersMiddleware::getNonce();
|
||||
for ($i = 1; $i <= $totalPages; $i++) {
|
||||
$activeClass = ($i === $page) ? 'active' : '';
|
||||
$currentParams['page'] = $i;
|
||||
$pageUrl = '?' . http_build_query($currentParams);
|
||||
$pageUrl = htmlspecialchars('?' . http_build_query($currentParams), ENT_QUOTES, 'UTF-8');
|
||||
echo "<button class='$activeClass' data-action='navigate' data-url='$pageUrl'>$i</button>";
|
||||
}
|
||||
|
||||
// Next page button
|
||||
if ($page < $totalPages) {
|
||||
$currentParams['page'] = $page + 1;
|
||||
$nextUrl = '?' . http_build_query($currentParams);
|
||||
$nextUrl = htmlspecialchars('?' . http_build_query($currentParams), ENT_QUOTES, 'UTF-8');
|
||||
echo "<button data-action='navigate' data-url='$nextUrl' aria-label='Next page'>[ » ]</button>";
|
||||
}
|
||||
?>
|
||||
@@ -393,7 +393,7 @@ $nonce = SecurityHeadersMiddleware::getNonce();
|
||||
<?php endif; ?>
|
||||
<?php
|
||||
$currentSort = isset($_GET['sort']) ? $_GET['sort'] : 'ticket_id';
|
||||
$currentDir = isset($_GET['dir']) ? $_GET['dir'] : 'desc';
|
||||
$currentDir = (isset($_GET['dir']) && $_GET['dir'] === 'asc') ? 'asc' : 'desc';
|
||||
|
||||
$columns = [
|
||||
'ticket_id' => 'Ticket ID',
|
||||
@@ -417,7 +417,7 @@ $nonce = SecurityHeadersMiddleware::getNonce();
|
||||
$sortClass = ($currentSort === $col) ? "sort-$currentDir" : '';
|
||||
$ariaSort = ($currentSort === $col) ? "aria-sort='" . ($currentDir === 'asc' ? 'ascending' : 'descending') . "'" : '';
|
||||
$sortParams = array_merge($_GET, ['sort' => $col, 'dir' => $newDir]);
|
||||
$sortUrl = '?' . http_build_query($sortParams);
|
||||
$sortUrl = htmlspecialchars('?' . http_build_query($sortParams), ENT_QUOTES, 'UTF-8');
|
||||
echo "<th scope='col' class='$sortClass' data-action='navigate' data-url='$sortUrl' $ariaSort>$label</th>";
|
||||
}
|
||||
}
|
||||
@@ -440,9 +440,10 @@ $nonce = SecurityHeadersMiddleware::getNonce();
|
||||
echo "<td><a href='/ticket/{$row['ticket_id']}' class='ticket-link'>{$row['ticket_id']}</a></td>";
|
||||
echo "<td><span>{$row['priority']}</span></td>";
|
||||
echo "<td>" . htmlspecialchars($row['title']) . "</td>";
|
||||
echo "<td>{$row['category']}</td>";
|
||||
echo "<td>{$row['type']}</td>";
|
||||
echo "<td><span class='status-" . str_replace(' ', '-', $row['status']) . "'>{$row['status']}</span></td>";
|
||||
echo "<td>" . htmlspecialchars($row['category']) . "</td>";
|
||||
echo "<td>" . htmlspecialchars($row['type']) . "</td>";
|
||||
$statusSlug = htmlspecialchars(str_replace(' ', '-', $row['status']), ENT_QUOTES);
|
||||
echo "<td><span class='status-" . $statusSlug . "'>" . htmlspecialchars($row['status']) . "</span></td>";
|
||||
echo "<td>" . htmlspecialchars($creator) . "</td>";
|
||||
echo "<td>" . htmlspecialchars($assignedTo) . "</td>";
|
||||
echo "<td class='ts-cell' data-ts='" . htmlspecialchars($row['created_at'], ENT_QUOTES, 'UTF-8') . "' title='" . date('Y-m-d H:i T', strtotime($row['created_at'])) . "'>" . date('Y-m-d H:i', strtotime($row['created_at'])) . "</td>";
|
||||
@@ -451,7 +452,7 @@ $nonce = SecurityHeadersMiddleware::getNonce();
|
||||
echo "<td class='quick-actions-cell'>";
|
||||
echo "<div class='quick-actions'>";
|
||||
echo "<button data-action='view-ticket' data-ticket-id='" . $row['ticket_id'] . "' class='quick-action-btn' title='View' aria-label='View ticket " . $row['ticket_id'] . "'>></button>";
|
||||
echo "<button data-action='quick-status' data-ticket-id='" . $row['ticket_id'] . "' data-status='" . $row['status'] . "' class='quick-action-btn' title='Change Status' aria-label='Change status for ticket " . $row['ticket_id'] . "'>~</button>";
|
||||
echo "<button data-action='quick-status' data-ticket-id='" . (int)$row['ticket_id'] . "' data-status='" . htmlspecialchars($row['status'], ENT_QUOTES) . "' class='quick-action-btn' title='Change Status' aria-label='Change status for ticket " . (int)$row['ticket_id'] . "'>~</button>";
|
||||
echo "<button data-action='quick-assign' data-ticket-id='" . $row['ticket_id'] . "' class='quick-action-btn' title='Assign' aria-label='Assign ticket " . $row['ticket_id'] . "'>@</button>";
|
||||
echo "</div>";
|
||||
echo "</td>";
|
||||
@@ -496,12 +497,12 @@ $nonce = SecurityHeadersMiddleware::getNonce();
|
||||
<span class="ts-cell" data-ts="<?php echo htmlspecialchars($row['updated_at'], ENT_QUOTES, 'UTF-8'); ?>" title="<?php echo date('Y-m-d H:i', strtotime($row['updated_at'])); ?>"><?php echo date('M j', strtotime($row['updated_at'])); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ticket-card-status <?php echo $statusClass; ?>">
|
||||
<?php echo $row['status']; ?>
|
||||
<div class="ticket-card-status <?php echo htmlspecialchars($statusClass); ?>">
|
||||
<?php echo htmlspecialchars($row['status']); ?>
|
||||
</div>
|
||||
<div class="ticket-card-actions">
|
||||
<button data-action="view-ticket" data-ticket-id="<?php echo $row['ticket_id']; ?>" title="View" aria-label="View ticket <?php echo $row['ticket_id']; ?>">></button>
|
||||
<button data-action="quick-status" data-ticket-id="<?php echo $row['ticket_id']; ?>" data-status="<?php echo $row['status']; ?>" title="Status" aria-label="Change status for ticket <?php echo $row['ticket_id']; ?>">~</button>
|
||||
<button data-action="view-ticket" data-ticket-id="<?php echo (int)$row['ticket_id']; ?>" title="View" aria-label="View ticket <?php echo (int)$row['ticket_id']; ?>">></button>
|
||||
<button data-action="quick-status" data-ticket-id="<?php echo (int)$row['ticket_id']; ?>" data-status="<?php echo htmlspecialchars($row['status'], ENT_QUOTES); ?>" title="Status" aria-label="Change status for ticket <?php echo (int)$row['ticket_id']; ?>">~</button>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
@@ -149,7 +149,7 @@ $nonce = SecurityHeadersMiddleware::getNonce();
|
||||
for ($i = 1; $i <= min($totalPages, 10); $i++) {
|
||||
$params['page'] = $i;
|
||||
$activeClass = ($i == $page) ? 'active' : '';
|
||||
$url = '?' . http_build_query($params);
|
||||
$url = htmlspecialchars('?' . http_build_query($params), ENT_QUOTES, 'UTF-8');
|
||||
echo "<a href='$url' class='btn btn-small $activeClass'>$i</a> ";
|
||||
}
|
||||
if ($totalPages > 10) {
|
||||
|
||||
Reference in New Issue
Block a user