Stored HTML Injection in BOM Validation Results via Unescaped Part Name
Summary
Part-DB renders BOM validation information messages using Twig's |raw filter. These messages include translated placeholders populated with user-controlled Part names.
A user who can edit a Part name can store HTML markup in the Part name. When another user imports a BOM CSV referencing that Part ID, the malicious Part name is rendered as HTML in the victim's BOM validation result page.
This results in a cross-user stored HTML injection issue. JavaScript execution appears to be blocked by the current Content Security Policy, but arbitrary HTML links, forms, images, and CSS-based UI elements can still be injected into a trusted Part-DB page.
Affected Version
Tested on Part-DB version 2.12.1 using the official Docker image.
Affected Components
Relevant code paths identified during review:
src/Services/ImportExportSystem/BOMValidationService.php
templates/projects/_bom_validation_results.html.twig
templates/projects/import_bom_map_fields.html.twig
translations/messages.en.xlf
The vulnerable rendering sink is the BOM validation result template, where information messages are rendered using {{ info|raw }}.
The Part name is inserted into the translated partdb_link_success message and then rendered as raw HTML.
Impact
This is a cross-user stored HTML injection issue.
The attacker needs permission to create or edit a Part name. The victim needs permission to import a BOM into a Project.
The issue was reproduced with two non-admin users using the Editor permission preset:
- Attacker user: creates/edits a Part name containing HTML markup.
- Victim user: imports a BOM CSV referencing the attacker's Part ID.
- Result: the attacker's HTML is rendered in the victim's BOM validation result page.
The current CSP appears to block inline JavaScript execution, such as <script> tags and inline event handlers. However, the injection still allows arbitrary HTML to be rendered inside the victim's trusted Part-DB page, including links, forms, tracking images, and CSS-based UI redressing/phishing overlays.
Proof of Concept
Step 1: Attacker creates a malicious Part name
Log in as a non-admin user with the Editor preset and create or edit a Part.
Set the Part name to the following payload:
<a href=//attacker.example style=color:red;font-size:20px>Re-authenticate</a>
In the test environment, this Part was saved with ID 2.
Step 2: Victim imports a BOM CSV referencing the malicious Part
Log in as a different non-admin user with the Editor preset.
Create a Project and import the following BOM CSV as Generic CSV:
Part-DB ID,Designator,Quantity
2,R1,1
,R2,2
Map the CSV columns as follows:
Part-DB ID -> Part-DB ID
Designator -> Designator
Quantity -> Quantity
The second row intentionally contains an invalid quantity/designator combination. This forces the BOM validation page to render the validation result object. The issue is demonstrated in the Information section, where the Part name from line 1 is rendered as HTML.
Step 3: Observe the injected HTML in the victim's validation result page
After clicking Preview, the validation result page displays:
Line 1: Successfully linked to Part-DB part "Re-authenticate" (ID: 2).
However, Re-authenticate is not rendered as plain text. It is rendered as a red HTML link controlled by the attacker.
Expected Behavior
User-controlled Part names should be escaped before being rendered in BOM validation messages.
The payload should be displayed as plain text, for example:
<a href=//attacker.example style=color:red;font-size:20px>Re-authenticate</a>
Actual Behavior
The Part name is inserted into the translated validation message and rendered through {{ info|raw }}, causing attacker-controlled HTML to be interpreted by the browser.
Why this is security-relevant
This is not an administrative feature or an intended rich-text field. The malicious content is stored in a normal Part name field and later rendered in another user's BOM validation result page.
The victim does not need to edit or directly view the malicious Part. The payload is triggered when the victim imports a BOM CSV referencing the Part ID.
This crosses a user boundary because one user controls the stored Part name and another user renders it during BOM validation.
Suggested Fix
Avoid rendering BOM validation information messages with |raw unless all placeholders are safely escaped.
For example, change the template rendering from:
to:
or:
If some validation messages intentionally contain trusted HTML, then user-controlled placeholders should be escaped before interpolation. For example:
'%name%' => htmlspecialchars($existing_part->getName(), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8')
The same pattern should be reviewed for other BOM validation placeholders, including CSV-controlled values such as designators, package fields, and quantities.
Notes
JavaScript execution was not required to demonstrate the issue. The current CSP appears to block inline JavaScript execution, but arbitrary HTML injection still occurs and can be used for phishing, UI redressing, external links, injected forms, or tracking images inside a trusted Part-DB page.
The issue was reproduced on Part-DB 2.12.1 with two non-admin users using the Editor permission preset.
Stored HTML Injection in BOM Validation Results via Unescaped Part Name
Summary
Part-DB renders BOM validation information messages using Twig's
|rawfilter. These messages include translated placeholders populated with user-controlled Part names.A user who can edit a Part name can store HTML markup in the Part name. When another user imports a BOM CSV referencing that Part ID, the malicious Part name is rendered as HTML in the victim's BOM validation result page.
This results in a cross-user stored HTML injection issue. JavaScript execution appears to be blocked by the current Content Security Policy, but arbitrary HTML links, forms, images, and CSS-based UI elements can still be injected into a trusted Part-DB page.
Affected Version
Tested on Part-DB version 2.12.1 using the official Docker image.
Affected Components
Relevant code paths identified during review:
src/Services/ImportExportSystem/BOMValidationService.phptemplates/projects/_bom_validation_results.html.twigtemplates/projects/import_bom_map_fields.html.twigtranslations/messages.en.xlfThe vulnerable rendering sink is the BOM validation result template, where information messages are rendered using
{{ info|raw }}.The Part name is inserted into the translated
partdb_link_successmessage and then rendered as raw HTML.Impact
This is a cross-user stored HTML injection issue.
The attacker needs permission to create or edit a Part name. The victim needs permission to import a BOM into a Project.
The issue was reproduced with two non-admin users using the Editor permission preset:
The current CSP appears to block inline JavaScript execution, such as
<script>tags and inline event handlers. However, the injection still allows arbitrary HTML to be rendered inside the victim's trusted Part-DB page, including links, forms, tracking images, and CSS-based UI redressing/phishing overlays.Proof of Concept
Step 1: Attacker creates a malicious Part name
Log in as a non-admin user with the Editor preset and create or edit a Part.
Set the Part name to the following payload:
In the test environment, this Part was saved with ID
2.Step 2: Victim imports a BOM CSV referencing the malicious Part
Log in as a different non-admin user with the Editor preset.
Create a Project and import the following BOM CSV as
Generic CSV:Map the CSV columns as follows:
The second row intentionally contains an invalid quantity/designator combination. This forces the BOM validation page to render the validation result object. The issue is demonstrated in the Information section, where the Part name from line 1 is rendered as HTML.
Step 3: Observe the injected HTML in the victim's validation result page
After clicking Preview, the validation result page displays:
However,
Re-authenticateis not rendered as plain text. It is rendered as a red HTML link controlled by the attacker.Expected Behavior
User-controlled Part names should be escaped before being rendered in BOM validation messages.
The payload should be displayed as plain text, for example:
Actual Behavior
The Part name is inserted into the translated validation message and rendered through
{{ info|raw }}, causing attacker-controlled HTML to be interpreted by the browser.Why this is security-relevant
This is not an administrative feature or an intended rich-text field. The malicious content is stored in a normal Part name field and later rendered in another user's BOM validation result page.
The victim does not need to edit or directly view the malicious Part. The payload is triggered when the victim imports a BOM CSV referencing the Part ID.
This crosses a user boundary because one user controls the stored Part name and another user renders it during BOM validation.
Suggested Fix
Avoid rendering BOM validation information messages with
|rawunless all placeholders are safely escaped.For example, change the template rendering from:
to:
or:
If some validation messages intentionally contain trusted HTML, then user-controlled placeholders should be escaped before interpolation. For example:
The same pattern should be reviewed for other BOM validation placeholders, including CSV-controlled values such as designators, package fields, and quantities.
Notes
JavaScript execution was not required to demonstrate the issue. The current CSP appears to block inline JavaScript execution, but arbitrary HTML injection still occurs and can be used for phishing, UI redressing, external links, injected forms, or tracking images inside a trusted Part-DB page.
The issue was reproduced on Part-DB 2.12.1 with two non-admin users using the Editor permission preset.