Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent getSelector from returning URLs as selector #32586

Merged
18 changes: 17 additions & 1 deletion js/src/util/index.js
Expand Up @@ -36,7 +36,23 @@ const getSelector = element => {
let selector = element.getAttribute('data-bs-target')

if (!selector || selector === '#') {
const hrefAttr = element.getAttribute('href')
let hrefAttr = element.getAttribute('href')

if (!hrefAttr) {
return null
}

// The only valid content that could double as a selector are ids, so everything starting with . or #
// If a 'real' url is used as the selector, document.querySelector will rightfully
// complain it is invalid. (see twbs#32273)
if (!hrefAttr.includes('#') && !hrefAttr.startsWith('.')) {
RoflCopter24 marked this conversation as resolved.
Show resolved Hide resolved
return null
}

// just in case some cms put out a full url with the anchor appended
if (hrefAttr.includes('#') && !hrefAttr.startsWith('#')) {
hrefAttr = '#' + hrefAttr.split('#')[1]
}

selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : null
}
Expand Down
22 changes: 22 additions & 0 deletions js/tests/unit/util/index.spec.js
Expand Up @@ -57,6 +57,28 @@ describe('Util', () => {
expect(Util.getSelectorFromElement(testEl)).toEqual('.target')
})

it('should return null if a selector from a href is an url without an anchor', () => {
fixtureEl.innerHTML = [
'<a id="test" data-bs-target="#" href="foo/bar.html"></a>',
'<div class="target"></div>'
].join('')

const testEl = fixtureEl.querySelector('#test')

expect(Util.getSelectorFromElement(testEl)).toBeNull()
})

it('should return the anchor if a selector from a href is an url', () => {
fixtureEl.innerHTML = [
'<a id="test" data-bs-target="#" href="foo/bar.html#target"></a>',
'<div id="target"></div>'
].join('')

const testEl = fixtureEl.querySelector('#test')

expect(Util.getSelectorFromElement(testEl)).toEqual('#target')
})

it('should return null if selector not found', () => {
fixtureEl.innerHTML = '<a id="test" href=".target"></a>'

Expand Down