CVE-2019-14667 (Other, published 2019-08-05T20:15Z)
Description: value: Firefly III 4.7.17.4 is vulnerable to multiple stored XSS issues due to the lack of filtration of user-supplied data in the transaction description field and the asset account name. The JavaScript code is executed during a convert transaction action.
Severity: MEDIUM (CVSS v3 base score: 6.1)
Weakness: CWE-79 \u2014 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
Repository: https://github.com/firefly-iii/firefly-iii
Files changed:
resources/views/v1/transactions/convert.twig
Commit message: Fix #2363


Vulnerable code:
                            {{ ExpandedForm.staticText('source_account_asset', '<a href="'~route('accounts.show',[sourceAccount.id])~'">'~sourceAccount.name~'</a>') }}
                                {{ ExpandedForm.staticText('destination_account_expense', '<a href="'~route('accounts.show',[destinationAccount.id])~'">'~destinationAccount.name~'</a>') }}
                                {{ ExpandedForm.staticText('source_account_revenue', '<a href="'~route('accounts.show',[sourceAccount.id])~'">'~sourceAccount.name~'</a>') }}
                            {{ ExpandedForm.staticText('destination_account_asset', '<a href="'~route('accounts.show',[destinationAccount.id])~'">'~destinationAccount.name~'</a>') }}
                            {{ ExpandedForm.staticText('source_account_asset', '<a href="'~route('accounts.show',[sourceAccount.id])~'">'~sourceAccount.name~'</a>') }}
                            {{ ExpandedForm.staticText('destination_account_asset', '<a href="'~route('accounts.show',[destinationAccount.id])~'">'~destinationAccount.name~'</a>') }}
                                            sourceName: sourceAccount.name,
                                            destinationName: destinationAccount.name,
                                {{ ExpandedForm.text('source_account_revenue', destinationAccount.name) }}
                                            sourceName: sourceAccount.name,
                                            destinationName: destinationAccount.name,
                                            sourceName: sourceAccount.name,
                                            destinationName: destinationAccount.name,
                                {{ ExpandedForm.text('destination_account_expense', destinationAccount.name) }}
                                            sourceName: sourceAccount.name,
                                            destinationName: destinationAccount.name,
                                            sourceName: sourceAccount.name,
                                            destinationName: destinationAccount.name,
                            {{ ExpandedForm.text('destination_account_expense', destinationAccount.name) }}
                                            sourceName: sourceAccount.name,
                                            destinationName: destinationAccount.name,
                            {{ ExpandedForm.text('source_account_revenue', sourceAccount.name) }}

Fixed code:
                            {{ ExpandedForm.staticText('source_account_asset', '<a href="'~route('accounts.show',[sourceAccount.id])~'">'~sourceAccount.name|escape~'</a>') }}
                                {{ ExpandedForm.staticText('destination_account_expense', '<a href="'~route('accounts.show',[destinationAccount.id])~'">'~destinationAccount.name|escape~'</a>') }}
                                {{ ExpandedForm.staticText('source_account_revenue', '<a href="'~route('accounts.show',[sourceAccount.id])~'">'~sourceAccount.name|escape~'</a>') }}
                            {{ ExpandedForm.staticText('destination_account_asset', '<a href="'~route('accounts.show',[destinationAccount.id])~'">'~destinationAccount.name|escape~'</a>') }}
                            {{ ExpandedForm.staticText('source_account_asset', '<a href="'~route('accounts.show',[sourceAccount.id])~'">'~sourceAccount.name|escape~'</a>') }}
                            {{ ExpandedForm.staticText('destination_account_asset', '<a href="'~route('accounts.show',[destinationAccount.id])~'">'~destinationAccount.name|escape~'</a>') }}
                                            sourceName: sourceAccount.name|escape,
                                            destinationName: destinationAccount.name|escape,
                                {{ ExpandedForm.text('source_account_revenue', destinationAccount.name|escape) }}
                                            sourceName: sourceAccount.name|escape,
                                            destinationName: destinationAccount.name|escape,
                                            sourceName: sourceAccount.name|escape,
                                            destinationName: destinationAccount.name|escape,
                                {{ ExpandedForm.text('destination_account_expense', destinationAccount.name|escape) }}
                                            sourceName: sourceAccount.name|escape,
                                            destinationName: destinationAccount.name|escape,
                                            sourceName: sourceAccount.name|escape,
                                            destinationName: destinationAccount.name|escape,
                            {{ ExpandedForm.text('destination_account_expense', destinationAccount.name|escape) }}
                                            sourceName: sourceAccount.name|escape,
                                            destinationName: destinationAccount.name|escape,
                            {{ ExpandedForm.text('source_account_revenue', sourceAccount.name|escape) }}