fix(19.7): RB-IN-01 the My account URL check refuses control characters
Browsers strip tab and newline from URLs, so "/\t/host" passed the SPA's same-origin check and resolved off-site. The check now refuses any ASCII control character first, as Go's url.Parse does on the server, and an absolute URL must parse with a host, so both sides apply one rule.
This commit is contained in:
@@ -157,6 +157,21 @@ describe('My account contributions', () => {
|
||||
expect(toasts.value.map((toast) => toast.text)).toEqual(['Done.'])
|
||||
})
|
||||
|
||||
// RB-IN-01: browsers strip tab and newline, so these resolve off-site.
|
||||
for (const url of ['/\t/evil.example/x', '/\n/evil.example', '/\r\n/evil.example', '/x\u0000', 'https://']) {
|
||||
it(`a ${JSON.stringify(url)} URL answer renders no link and never opens a window`, async () => {
|
||||
const opened = vi.spyOn(window, 'open').mockImplementation(() => null)
|
||||
const { wrapper } = await openAccount({
|
||||
[`POST ${OPEN}`]: envelope({ message: 'Done.', url }),
|
||||
})
|
||||
await wrapper.find('[data-account-contribution-action="open"]').trigger('click')
|
||||
await flushPromises()
|
||||
expect(opened).not.toHaveBeenCalled()
|
||||
expect(wrapper.find('[data-account-contribution-url]').exists()).toBe(false)
|
||||
expect(wrapper.html()).not.toContain('evil.example')
|
||||
})
|
||||
}
|
||||
|
||||
it('a section with error: true shows the section error text', async () => {
|
||||
setBundle({ ...langFixture.data, ...strings, 'backend::lang.myaccount.section_error': { other: 'This section could not be loaded.' } }, 'en')
|
||||
const { wrapper } = await openAccount({
|
||||
|
||||
Reference in New Issue
Block a user