Enhance task description rendering and security

- Added sanitization and filtering for task descriptions in task_popup.php to prevent XSS attacks.
- Implemented regex patterns to remove potentially harmful HTML tags and attributes.
- Improved link and image handling to ensure only safe URLs and sources are rendered.
- Updated CSS for task popup to allow better text wrapping and overflow handling.
This commit is contained in:
2026-02-23 14:12:06 +01:00
parent 1300f32690
commit 76d3ac33a8
5 changed files with 47 additions and 4 deletions

View File

@@ -26,6 +26,46 @@
$comments_count = is_array( $this -> task['comments'] ) ? count( $this -> task['comments'] ) : 0;
$attachments_count = is_array( $this -> task_attachments ) ? count( $this -> task_attachments ) : 0;
?>
<?
$task_description_html = htmlspecialchars_decode( (string)$this -> task['text'] );
if ( $task_description_html !== '' )
{
$task_description_html = preg_replace( '/<(script|style|iframe|object|embed|link|meta|base|form|input|button|textarea|select)\b[^>]*>.*?<\/\1>/is', '', $task_description_html );
$task_description_html = preg_replace( '/<(script|style|iframe|object|embed|link|meta|base|form|input|button|textarea|select)\b[^>]*\/?>/is', '', $task_description_html );
$task_description_html = preg_replace( '/\son[a-z]+\s*=\s*(".*?"|\'.*?\'|[^\s>]+)/i', '', $task_description_html );
$task_description_html = preg_replace( '/<(\/?)div\b[^>]*>/i', '<br>', $task_description_html );
$task_description_html = preg_replace( '/<(\/?)span\b[^>]*>/i', '', $task_description_html );
$task_description_html = preg_replace( '/\s(style|class|id|width|height|align|valign|border|cellpadding|cellspacing)\s*=\s*(".*?"|\'.*?\'|[^\s>]+)/i', '', $task_description_html );
$task_description_html = preg_replace_callback( '/<a\b[^>]*>/i', function( $matches ) {
if ( preg_match( '/href\s*=\s*("|\')([^"\']+)\1/i', $matches[0], $href ) )
{
$url = trim( $href[2] );
if ( preg_match( '/^(https?:|mailto:|\/|#)/i', $url ) )
return '<a href="' . htmlspecialchars( $url, ENT_QUOTES ) . '" target="_blank" rel="noopener noreferrer">';
}
return '<a>';
}, $task_description_html );
$task_description_html = preg_replace_callback( '/<img\b[^>]*>/i', function( $matches ) {
$attrs = [];
if ( preg_match( '/src\s*=\s*("|\')([^"\']+)\1/i', $matches[0], $src ) )
{
$img_src = trim( $src[2] );
if ( preg_match( '/^(https?:|\/|data:image\/)/i', $img_src ) )
$attrs[] = 'src="' . htmlspecialchars( $img_src, ENT_QUOTES ) . '"';
}
if ( preg_match( '/alt\s*=\s*("|\')([^"\']*)\1/i', $matches[0], $alt ) )
$attrs[] = 'alt="' . htmlspecialchars( $alt[2], ENT_QUOTES ) . '"';
if ( empty( $attrs ) )
return '';
return '<img ' . implode( ' ', $attrs ) . '>';
}, $task_description_html );
$task_description_html = strip_tags( $task_description_html, '<p><br><b><strong><i><em><u><s><ul><ol><li><a><img><blockquote><pre><code><h1><h2><h3><h4><h5><h6><hr>' );
$task_description_html = preg_replace( '/(<br>\s*){3,}/i', '<br><br>', $task_description_html );
}
?>
<div class="content">
<div class="left">
<div class="task-tabs-nav" role="tablist" aria-label="Prze&#322;&#261;cz zak&#322;adk&#281; zadania">
@@ -50,7 +90,7 @@
<? if ( $this -> task['text'] ):?>
<div class="description">
<a href="#" class="fullscreen"><i class="fa fa-expand"></i></a>
<?= htmlspecialchars_decode( $this -> task['text'] );?>
<?= $task_description_html;?>
</div>
<? else:?>
<div class="description description-empty">
@@ -290,6 +330,8 @@
min-height: 320px;
max-height: calc(90vh - 300px);
overflow-y: auto;
overflow-wrap: anywhere;
word-break: break-word;
}
.task_popup .task_details .content .right .client .select2-container--bootstrap-5 .select2-selection {