fix: incomplete URL substring sanitization in linkedin-browser-extension. (#16586)
Tighten LinkedIn browser extension popup URL handling by parsing the active tab URL and matching on protocol, hostname, and pathname instead of substring checks, preventing logic from running on non-LinkedIn hosts. Resolves [Code Scanning Alert 209](https://github.com/twentyhq/twenty/security/code-scanning/209) and [Code Scanning Alert 210](https://github.com/twentyhq/twenty/security/code-scanning/210).
This commit is contained in:
+42
-29
@@ -12,19 +12,28 @@ function App() {
|
||||
useEffect(() => {
|
||||
browser.tabs.query({ active: true, currentWindow: true }, function(tabs) {
|
||||
const currentTab = tabs[0];
|
||||
if(currentTab.url?.includes('https://www.linkedin.com/in')) {
|
||||
sendMessage('getPersonviaRelay').then(data => {
|
||||
setValue({...data, type: 'person' })
|
||||
})
|
||||
}
|
||||
|
||||
if(currentTab.url?.includes('https://www.linkedin.com/company')) {
|
||||
sendMessage('getCompanyviaRelay').then(data => {
|
||||
setValue({...data, type: 'company'})
|
||||
})
|
||||
if (!currentTab.url) {
|
||||
return;
|
||||
}
|
||||
|
||||
let url = new URL(currentTab.url);
|
||||
|
||||
const isLinkedinHost =
|
||||
url.protocol === 'https:' && url.hostname === 'www.linkedin.com';
|
||||
|
||||
if (isLinkedinHost && url.pathname.startsWith('/in/')) {
|
||||
sendMessage('getPersonviaRelay').then((data) => {
|
||||
setValue({ ...data, type: 'person' });
|
||||
});
|
||||
}
|
||||
|
||||
if (isLinkedinHost && url.pathname.startsWith('/company/')) {
|
||||
sendMessage('getCompanyviaRelay').then((data) => {
|
||||
setValue({ ...data, type: 'company' });
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
}, []);
|
||||
|
||||
const isPersonValue = (val: Value): val is PersonValue => {
|
||||
@@ -38,25 +47,29 @@ function App() {
|
||||
return (
|
||||
<StyledMain>
|
||||
<h1>{JSON.stringify(value)}</h1>
|
||||
{
|
||||
isPersonValue(value) &&
|
||||
<button onClick={async () => {
|
||||
await sendMessage('createPerson', {
|
||||
firstName: value.firstName,
|
||||
lastName: value.lastName,
|
||||
});
|
||||
|
||||
}}>save person to twenty</button>
|
||||
}
|
||||
{
|
||||
isCompanyValue(value) &&
|
||||
<button onClick={async () => {
|
||||
await sendMessage('createCompany', {
|
||||
name: value.companyName
|
||||
});
|
||||
|
||||
}}>save company to twenty</button>
|
||||
}
|
||||
{isPersonValue(value) && (
|
||||
<button
|
||||
onClick={async () => {
|
||||
await sendMessage('createPerson', {
|
||||
firstName: value.firstName,
|
||||
lastName: value.lastName,
|
||||
});
|
||||
}}
|
||||
>
|
||||
save person to twenty
|
||||
</button>
|
||||
)}
|
||||
{isCompanyValue(value) && (
|
||||
<button
|
||||
onClick={async () => {
|
||||
await sendMessage('createCompany', {
|
||||
name: value.companyName,
|
||||
});
|
||||
}}
|
||||
>
|
||||
save company to twenty
|
||||
</button>
|
||||
)}
|
||||
</StyledMain>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user