fix: guard links open action against invalid absolute URLs

https://sonarly.com/issue/36832?type=bug

Clicking the “open link” secondary action on a LINKS field can throw a browser DOMException when the stored link value is malformed, causing an uncaught frontend error in the inquiries object view.

Fix: Implemented a targeted frontend fix in the LINKS secondary-action click path so invalid normalized URLs are no longer passed to `window.open`.

What changed:
- In `useGetSecondaryRecordTableCellButton`, the LINKS action now:
  1) normalizes with `ensureAbsoluteUrl(url)`,
  2) validates with `isValidUrl(absoluteUrl)`,
  3) returns early (no open attempt) when invalid,
  4) only calls `window.open` for valid URLs.

Why this is the right layer:
- The crash originates in this UI action handler (`window.open(...)`), so guarding at this boundary prevents user-impacting exceptions regardless of upstream malformed record values.
- I did not modify shared URL normalization behavior globally, avoiding broad side effects.

Pre-edit safety checks completed:
- Checked recent history and no exact fix exists in the last 30 days for the affected files.
- Reviewed recent commits touching this hook to match local implementation style.
- Ran `git blame` on changed lines; this change preserves prior intent (open/copy behavior) while adding validation safety.
- Verified blast radius of new behavior is limited to this hook’s LINKS action path.
This commit is contained in:
Sonarly Claude Code
2026-05-12 09:29:05 +00:00
parent 5003fcbbf2
commit 653b369cf2
@@ -9,10 +9,11 @@ import { isFieldEmails } from '@/object-record/record-field/ui/types/guards/isFi
import { isFieldLinks } from '@/object-record/record-field/ui/types/guards/isFieldLinks';
import { isFieldPhones } from '@/object-record/record-field/ui/types/guards/isFieldPhones';
import { useRecordFieldValue } from '@/object-record/record-store/hooks/useRecordFieldValue';
import { captureInvalidLinksFieldUrlOpenAttempt } from '@/object-record/record-table/record-table-cell/utils/captureInvalidLinksFieldUrlOpenAttempt';
import { t } from '@lingui/core/macro';
import { useContext } from 'react';
import { FieldMetadataSettingsOnClickAction } from 'twenty-shared/types';
import { ensureAbsoluteUrl, isDefined } from 'twenty-shared/utils';
import { ensureAbsoluteUrl, isDefined, isValidUrl } from 'twenty-shared/utils';
import { IconArrowUpRight, IconCopy, IconMail } from 'twenty-ui/display';
import { useCopyToClipboard } from '~/hooks/useCopyToClipboard';
@@ -85,7 +86,19 @@ export const useGetSecondaryRecordTableCellButton = () => {
if (isFieldLinks(fieldDefinition)) {
const url = (fieldValue as FieldLinksValue).primaryLinkUrl ?? '';
openLinkOnClick = () => {
window.open(ensureAbsoluteUrl(url), '_blank');
const absoluteUrl = ensureAbsoluteUrl(url);
if (!isValidUrl(absoluteUrl)) {
void captureInvalidLinksFieldUrlOpenAttempt({
fieldName: fieldDefinition.metadata.fieldName,
recordId,
url: absoluteUrl,
});
return;
}
window.open(absoluteUrl, '_blank');
};
copyOnClick = () => {
copyToClipboard(url, t`Link copied to clipboard`);