Skip to content

fix(timeline): prevent pasted inline positioning from overlaying the page - #26247

Open
orthagh wants to merge 2 commits into
glpi-project:12.0/bugfixesfrom
orthagh:fix/timeline-richtext-positioning
Open

orthagh wants to merge 2 commits into
glpi-project:12.0/bugfixesfrom
orthagh:fix/timeline-richtext-positioning

Conversation

@orthagh

@orthagh orthagh commented Nov 6, 2026

Copy link
Copy Markdown
Member

Checklist before requesting a review

  • I have read the CONTRIBUTING document.
  • I have performed a self-review of my code.

Description

Content pasted from some web apps (e.g. virtualized log viewers) carries inline position: absolute; top: 0; left: 0; transform: translateY(…) on every line. The rich text sanitizer keeps style attributes, so once saved in a ticket these elements escape their timeline item and overlay the whole page.

This neutralizes inline position and transform for rich text displayed in the ITIL timeline (description, followups, tasks, solutions, validations). Content outside the timeline (KB, login page, notes…) is left untouched, as it is authored by admins who may rely on positioning on purpose. TinyMCE is not affected (iframe).

Minimal reproduction, as a followup content:

<p>before</p>
<div style="position: absolute; top: 0px; left: 0px; width: 745px; transform: translateY(238px);">log line 1</div>
<div style="position: absolute; top: 0px; left: 0px; width: 745px; transform: translateY(255px);">log line 2</div>
<p>after</p>

…page

Content pasted from some web apps (e.g. virtualized log viewers) carries
inline position:absolute and transform styles on every line. Once in a
ticket, it escapes the timeline item and overlays the whole page.
Neutralize inline position and transform in ITIL timeline rich text.
@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

Code Review by Qodo


View medium (2)
🟠 **Medium**
1. Overbroad selectors flatten legitimate timeline layout styles 🐞 Bug
Description
The rule .itil-timeline .rich_text_container [style*="position"] { position: static !important; }
uses a substring attribute selector, so it forces static on any inline style containing "position"
(including position: relative/sticky), and [style*="transform"] strips every transform,
including harmless rotations or scalings, going beyond the absolute-positioning and translation
scope the PR describes. It also cannot override inline declarations marked !important (e.g.
style="position: absolute !important; top: 0"), since an inline !important beats a stylesheet
!important in the author cascade, so such pasted content still escapes the timeline item and
overlays the page.
Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The CSS-only override in css/includes/components/_richtext.scss has two problems in the ITIL timeline. First, the substring selectors `[style*="position"]` and `[style*="transform"]` match any inline style containing those words, so harmless `position: relative`/`sticky` and rotations or scalings are also neutralized, which goes beyond the absolute-positioning and translation scope the PR describes. Second, the stylesheet `!important` cannot beat inline declarations that also use `!important`, so pasted content such as `style="position: absolute !important; top: 0"` or `transform: ... !important` still overlays the page.
## Fix Focus Areas
- css/includes/components/_richtext.scss[109-117]
## Recommended Fix
Neutralize the declarations where the content is rendered for the timeline, not in CSS alone. In the timeline rendering path, pass the rich text through a filter that removes `position` and `transform` properties (including their `!important` variants) from style attributes before output, or make the sanitizer drop those properties for that context. Narrow the targeting to the properties actually in scope (absolute positioning and translation) rather than matching any style containing the substring. Keep the CSS rule only as defence in depth. Add a test that renders `position: absolute !important` content in a timeline item and asserts it is not absolutely positioned, and that harmless `position: relative` or rotation styles are preserved.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

2. Linked issue and AI-use disclosure are missing 🐞 Bug
Description
The PR description contains no linked issue and no statement about whether AI tools were used, both
of which CONTRIBUTING.md requires from outside contributors. The author's association is not visible
here, so this applies unless the author is a glpi-project member.

Resolved findings
1. No regression test covers the timeline positioning fix ✓ Resolved

Resolving commit: e98b8b7

Resolution reason
Added an e2e Playwright test that creates a ticket with pasted positioned/transformed HTML and
asserts that inside the itil-timeline the styles compute to position: static and transform: none,
covering the timeline positioning fix.
Description
The change adds only a SCSS rule and no test, so nothing verifies that pasted position/transform
styles are neutralized inside the timeline or that content outside the timeline is untouched. The
project requires a bug fix to ship with a test that fails without the change.

@orthagh

orthagh commented Nov 6, 2026 •

Copy link
Copy Markdown
Member Author
  • 2. Overbroad selectors: intentional — the rule only applies to the ITIL timeline, where no user-supplied inline positioning or transform is wanted; inline !important is a known limitation, not worth sanitizer changes that would alter stored content.
  • 3. Linked issue / AI disclosure: not applicable

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant