Harden CSP by removing unsafe-inline for scripts
Refactored all inline event handlers (onclick, onchange, onsubmit) to use
addEventListener with data-action attributes and event delegation pattern.
Changes:
- views/*.php: Replaced inline handlers with data-action attributes
- views/admin/*.php: Same refactoring for all admin views
- assets/js/dashboard.js: Added event delegation for bulk/quick action modals
- assets/js/ticket.js: Added event delegation for dynamic elements
- assets/js/markdown.js: Refactored toolbar button handlers
- assets/js/keyboard-shortcuts.js: Refactored modal close button
- SecurityHeadersMiddleware.php: Enabled strict CSP with nonces
The CSP now uses script-src 'self' 'nonce-{nonce}' instead of 'unsafe-inline',
significantly improving XSS protection.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -356,17 +356,36 @@ function createEditorToolbar(textareaId, containerId) {
|
||||
const toolbar = document.createElement('div');
|
||||
toolbar.className = 'editor-toolbar';
|
||||
toolbar.innerHTML = `
|
||||
<button type="button" onclick="toolbarBold('${textareaId}')" title="Bold (Ctrl+B)"><b>B</b></button>
|
||||
<button type="button" onclick="toolbarItalic('${textareaId}')" title="Italic (Ctrl+I)"><i>I</i></button>
|
||||
<button type="button" onclick="toolbarCode('${textareaId}')" title="Code"></></button>
|
||||
<button type="button" data-toolbar-action="bold" data-textarea="${textareaId}" title="Bold (Ctrl+B)"><b>B</b></button>
|
||||
<button type="button" data-toolbar-action="italic" data-textarea="${textareaId}" title="Italic (Ctrl+I)"><i>I</i></button>
|
||||
<button type="button" data-toolbar-action="code" data-textarea="${textareaId}" title="Code"></></button>
|
||||
<span class="toolbar-separator"></span>
|
||||
<button type="button" onclick="toolbarHeading('${textareaId}')" title="Heading">H</button>
|
||||
<button type="button" onclick="toolbarList('${textareaId}')" title="List">≡</button>
|
||||
<button type="button" onclick="toolbarQuote('${textareaId}')" title="Quote">"</button>
|
||||
<button type="button" data-toolbar-action="heading" data-textarea="${textareaId}" title="Heading">H</button>
|
||||
<button type="button" data-toolbar-action="list" data-textarea="${textareaId}" title="List">≡</button>
|
||||
<button type="button" data-toolbar-action="quote" data-textarea="${textareaId}" title="Quote">"</button>
|
||||
<span class="toolbar-separator"></span>
|
||||
<button type="button" onclick="toolbarLink('${textareaId}')" title="Link">🔗</button>
|
||||
<button type="button" data-toolbar-action="link" data-textarea="${textareaId}" title="Link">🔗</button>
|
||||
`;
|
||||
|
||||
// Add event delegation for toolbar buttons
|
||||
toolbar.addEventListener('click', function(e) {
|
||||
const btn = e.target.closest('[data-toolbar-action]');
|
||||
if (!btn) return;
|
||||
|
||||
const action = btn.dataset.toolbarAction;
|
||||
const targetId = btn.dataset.textarea;
|
||||
|
||||
switch (action) {
|
||||
case 'bold': toolbarBold(targetId); break;
|
||||
case 'italic': toolbarItalic(targetId); break;
|
||||
case 'code': toolbarCode(targetId); break;
|
||||
case 'heading': toolbarHeading(targetId); break;
|
||||
case 'list': toolbarList(targetId); break;
|
||||
case 'quote': toolbarQuote(targetId); break;
|
||||
case 'link': toolbarLink(targetId); break;
|
||||
}
|
||||
});
|
||||
|
||||
container.insertBefore(toolbar, container.firstChild);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user