fix: remove CSP-blocked inline event handlers (onerror, onclick)
- Remove all onerror="this.style.display='none'" from avatar imgs in layout_header.php, DashboardView.php, and TicketView.php (PHP + JS) - Replace onclick SLA dismiss with data-action="dismiss-priority-banner" attribute; handler wired via existing click delegation in TicketView.php - Global capture-phase error delegation in layout_footer.php handles all avatar image failures by adding .lt-avatar-img-err class (CSS display:none) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -331,7 +331,7 @@ include __DIR__ . '/layout_header.php';
|
|||||||
<div class="workload-item">
|
<div class="workload-item">
|
||||||
<div class="lt-avatar lt-avatar--sm <?= $avatarColor ?>" aria-hidden="true" title="<?= htmlspecialchars($name) ?>">
|
<div class="lt-avatar lt-avatar--sm <?= $avatarColor ?>" aria-hidden="true" title="<?= htmlspecialchars($name) ?>">
|
||||||
<?php if ($userId > 0): ?>
|
<?php if ($userId > 0): ?>
|
||||||
<img src="/api/user_avatar.php?user_id=<?= $userId ?>" alt="" class="lt-avatar-img" onerror="this.style.display='none'">
|
<img src="/api/user_avatar.php?user_id=<?= $userId ?>" alt="" class="lt-avatar-img">
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
<span class="lt-avatar-initials"><?= htmlspecialchars($initials) ?></span>
|
<span class="lt-avatar-initials"><?= htmlspecialchars($initials) ?></span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+10
-10
@@ -212,12 +212,7 @@ $progressClass = $slaBreached ? 'lt-progress--red' : ($slaPct >= 75 ? 'lt-progr
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="lt-alert-close" aria-label="Dismiss"
|
<button type="button" class="lt-alert-close" data-action="dismiss-priority-banner" aria-label="Dismiss">✕</button>
|
||||||
onclick="(function(btn){
|
|
||||||
var id=btn.closest('[data-alert-id]').dataset.alertId;
|
|
||||||
try{sessionStorage.setItem('lt_dismissed_'+id,'1');}catch(e){}
|
|
||||||
btn.closest('.lt-alert').classList.add('dismissed');
|
|
||||||
})(this)">✕</button>
|
|
||||||
</div>
|
</div>
|
||||||
<script nonce="<?= htmlspecialchars($nonce, ENT_QUOTES, 'UTF-8') ?>">
|
<script nonce="<?= htmlspecialchars($nonce, ENT_QUOTES, 'UTF-8') ?>">
|
||||||
(function(){
|
(function(){
|
||||||
@@ -564,8 +559,7 @@ $progressClass = $slaBreached ? 'lt-progress--red' : ($slaPct >= 75 ? 'lt-progr
|
|||||||
<?php if ($commentUserId > 0): ?>
|
<?php if ($commentUserId > 0): ?>
|
||||||
<img src="/api/user_avatar.php?user_id=<?= $commentUserId ?>"
|
<img src="/api/user_avatar.php?user_id=<?= $commentUserId ?>"
|
||||||
alt=""
|
alt=""
|
||||||
class="lt-avatar-img"
|
class="lt-avatar-img">
|
||||||
onerror="this.style.display='none'">
|
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
<span class="lt-avatar-initials"><?= htmlspecialchars($initials) ?></span>
|
<span class="lt-avatar-initials"><?= htmlspecialchars($initials) ?></span>
|
||||||
</div>
|
</div>
|
||||||
@@ -978,7 +972,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
for (var i = 0; i < (w.display_name || '').length; i++) hash = ((hash << 5) - hash + (w.display_name || '').charCodeAt(i)) | 0;
|
for (var i = 0; i < (w.display_name || '').length; i++) hash = ((hash << 5) - hash + (w.display_name || '').charCodeAt(i)) | 0;
|
||||||
var color = avatarColors[Math.abs(hash) % 4];
|
var color = avatarColors[Math.abs(hash) % 4];
|
||||||
html += '<div class="lt-avatar lt-avatar--xs ' + color + '" title="' + lt.escHtml(w.display_name) + '" aria-label="' + lt.escHtml(w.display_name) + '">' +
|
html += '<div class="lt-avatar lt-avatar--xs ' + color + '" title="' + lt.escHtml(w.display_name) + '" aria-label="' + lt.escHtml(w.display_name) + '">' +
|
||||||
'<img src="/api/user_avatar.php?user_id=' + w.user_id + '" alt="" class="lt-avatar-img" onerror="this.style.display=\'none\'">' +
|
'<img src="/api/user_avatar.php?user_id=' + w.user_id + '" alt="" class="lt-avatar-img">' +
|
||||||
'<span class="lt-avatar-initials">' + lt.escHtml(initials) + '</span>' +
|
'<span class="lt-avatar-initials">' + lt.escHtml(initials) + '</span>' +
|
||||||
'</div>';
|
'</div>';
|
||||||
});
|
});
|
||||||
@@ -1121,6 +1115,12 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
if (typeof editComment === 'function') editComment(parseInt(commentId, 10));
|
if (typeof editComment === 'function') editComment(parseInt(commentId, 10));
|
||||||
} else if (action === 'delete-comment' && commentId) {
|
} else if (action === 'delete-comment' && commentId) {
|
||||||
if (typeof deleteComment === 'function') deleteComment(parseInt(commentId, 10));
|
if (typeof deleteComment === 'function') deleteComment(parseInt(commentId, 10));
|
||||||
|
} else if (action === 'dismiss-priority-banner') {
|
||||||
|
var banner = target.closest('[data-alert-id]');
|
||||||
|
if (banner) {
|
||||||
|
try { sessionStorage.setItem('lt_dismissed_' + banner.dataset.alertId, '1'); } catch(ex) {}
|
||||||
|
banner.classList.add('dismissed');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1237,7 +1237,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
' data-action="delete-comment" data-comment-id="' + commentId + '" aria-label="Delete comment">Del</button>' : '';
|
' data-action="delete-comment" data-comment-id="' + commentId + '" aria-label="Delete comment">Del</button>' : '';
|
||||||
var threadLine = parentId ? '<div class="thread-line" aria-hidden="true"></div>' : '';
|
var threadLine = parentId ? '<div class="thread-line" aria-hidden="true"></div>' : '';
|
||||||
var avatarImg = userId > 0 ?
|
var avatarImg = userId > 0 ?
|
||||||
'<img src="/api/user_avatar.php?user_id=' + userId + '" alt="" class="lt-avatar-img" onerror="this.style.display=\'none\'">' : '';
|
'<img src="/api/user_avatar.php?user_id=' + userId + '" alt="" class="lt-avatar-img">' : '';
|
||||||
|
|
||||||
var div = document.createElement('div');
|
var div = document.createElement('div');
|
||||||
div.className = 'comment ' + depthClass + ' ' + threadClass;
|
div.className = 'comment ' + depthClass + ' ' + threadClass;
|
||||||
|
|||||||
@@ -166,7 +166,6 @@ $_lt_assetVer = $GLOBALS['config']['ASSET_VERSION'] ?? '20260329';
|
|||||||
<img src="/api/user_avatar.php?user_id=<?= $_lt_userId ?>"
|
<img src="/api/user_avatar.php?user_id=<?= $_lt_userId ?>"
|
||||||
alt=""
|
alt=""
|
||||||
class="lt-avatar-img"
|
class="lt-avatar-img"
|
||||||
onerror="this.style.display='none'">
|
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
<span class="lt-avatar-initials"><?= htmlspecialchars($_lt_initials) ?></span>
|
<span class="lt-avatar-initials"><?= htmlspecialchars($_lt_initials) ?></span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user