Skip to content

URL_REGEX rejects URLs containing square brackets in query parameters — no reference/link preview extracted #63164

Description

@LexioJ

Issue Description

Component: OCP\IURLGenerator::URL_REGEX / OC\Collaboration\Reference\ReferenceManager::extractReferences()

Current behavior:

URLs containing literal square brackets — typically PHP-style array query parameters like ?c[menu]=Overview — are not extracted as references at all. Messages in Talk (and any other app using the references API) render such links as plain text with no rich preview, even when a registered IReferenceProvider would match and resolve them.

// lib/public/IURLGenerator.php
public const URL_REGEX_NO_MODIFIERS = '(\s|\n|^)(https?:\/\/)([-A-Z0-9+_.]+(?::[0-9]+)?(?:\/[-A-Z0-9+&@#%?=~_|!:,.;()]*)*)(\s|\n|$)';

Two properties of this pattern combine to reject the URL entirely rather than merely truncating it:

  1. [ and ] are not in the path/query character class, and
  2. the match must be terminated by (\s|\n|$) — so when the scan hits [, the required whitespace boundary can't be satisfied and the whole candidate fails.

Steps to reproduce:

POST /ocs/v2.php/references/extract?format=json
{"text": "see https://example.com/pages/UI.php?operation=details&class=VirtualMachine&id=2904&c[menu]=ConfigManagementOverview please", "resolve": true}

Result: "references": [] — nothing extracted. The same URL without &c[menu]=…, or with the brackets percent-encoded (c%5Bmenu%5D), extracts and resolves correctly.

Expected behavior:

The URL should be extracted (with the brackets included), matching what browsers, GitHub, Slack, and other linkifiers do.

Real-world impact:

Applications like iTop (ITSM) append UI-state parameters such as &c[menu]=ConfigManagementOverview to their detail-page URLs. Browsers show the decoded form in the address bar, so that is what users copy and paste into Talk. Any reference provider app (e.g. integration_itop) is never consulted because extraction fails one layer above it — and there is no extension point for apps to work around this.

Strictly speaking, RFC 3986 requires brackets in a query component to be percent-encoded, so such URLs are technically non-compliant — but they are what real applications emit and real browsers display, and leniency here matches the de-facto behavior of every mainstream URL detector.

Suggested fix:

Add \[\] to the path/query character class:

public const URL_REGEX_NO_MODIFIERS = '(\s|\n|^)(https?:\/\/)([-A-Z0-9+_.]+(?::[0-9]+)?(?:\/[-A-Z0-9+&@#%?=~_|!:,.;()\[\]]*)*)(\s|\n|$)';

One trade-off to decide: with this change, a URL written inside markdown link syntax [label](https://…) could consume a trailing )] — but the current pattern already includes () in the character class, so that ambiguity exists today and is tracked separately.

Related (not duplicates): #55849 / PR #55850 concern the same constant but a different boundary problem (markdown ]( prefix); this issue is about the character class rejecting brackets inside the URL itself.

Nextcloud version: reproduced on 34.0.2

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    To triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions