You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Compose Box-Dot-heavy invalid URL candidate becomes a link after adding a character #102487
Version Number: v9.4.95-0 Reproducible in staging?: Yes Reproducible in production?: No If this was caught during regression testing, add the test name, ID and link from BrowserStack:#100421 Email or phone of affected tester (no customers):agexptest+pr280926@gmail.com Issue reported by: Applause Internal Team Bug source: Pull Request QA execution Device used: Windows 11/ Chrome, Samsung S23FE/ Android 16, iPhone 13 Mini/ iOS 26.5 App Component: Chat Report View
👋 Friendly reminder that deploy blockers are time-sensitive ⏱ issues! Check out the open `StagingDeployCash` deploy checklist to see the list of PRs included in this release, then work quickly to do one of the following:
Identify the pull request that introduced this issue and revert it.
The link is correct under the existing autolink rule. 'a.'.repeat(4499) + 'a' stays plain because no TLD is one letter long. Typing a letter such as d or e changes the last label to ad or ae. Those are real country-code TLDs, so the string is now a valid hostname.
Production already links this exact message once you send it. It also already highlights shorter versions in the composer. The only change is that the composer now parses text longer than 4,000 characters. That was the goal of the PR. A revert would bring back the related issue above to fix a synthetic 9,000-character input.
📋 Detailed analysis
Why it reproduces only on staging
The PR raised the composer's live-markdown parse limit from 4,000 to CONST.MAX_MARKUP_LENGTH (10,000).
In production (react-native-live-markdown 0.1.336), the composer gets no formatting for text over 4,000 characters: parseExpensiMark.ts#L242
When you send a message, src/libs/ReportUtils.ts:6933-6935 skips Markdown only above MAX_MARKUP_LENGTH (src/CONST/index.ts:5868, 10,000). So this 9,001-character message is already linked after sending on production. The staging composer now shows the same result as the sent message.
No other PR in the checklist is involved
Between production and staging, the parsing-related files (package.json, src/libs/ParsingUtils.ts, src/libs/EmojiUtils.tsx) changed only through the PR above.
Optional follow-up (not a blocker)
To stop absurd hostnames like this from linking, apply DNS limits in expensify-common's URL regex and candidate scanner: 253 characters total and 63 characters per label. This would also change how production renders sent messages. The PR's QA Test 3 should also be updated. It expects no link after you "type several characters", which is wrong for any character that completes a TLD.
Note: this comes from reading the code in expensify-common 2.0.207 and react-native-live-markdown 0.1.342. I did not run the parser locally.
cc JS00001linhvovan29546Uzaifm127, please confirm demotion.
@JS00001 Yes, this will be handled by this PR. It applies the 253 character hostname limit, so the long heavy dotted URL in this issue will no longer become an autolink.
A dotted URL with a hostname below 253 characters will still become an autolink when its labels are valid and it ends with a valid TLD. I think this is expected because it is still a valid hostname format, and I do not think users are likely to paste a URL like a.a.a.a.a.a... in the composer. The long dotted input from this issue is the case we need to handle, and it will no longer become an autolink after this PR.
To prevent those URLs further from becoming autolinks too, ExpensiMark would need to check whether each domain actually exists through a DNS lookup, which is not something the parser does or should do.
Agree with @JS00001 not worth the time. Even with the 253-char hostname limit from #951, any substring under that limit with valid labels ending in a real TLD is still a technically valid hostname, so it'd still autolink. The fix only patches the pathological >253 char case, which isn't a realistic input anyway. I'd vote to close this as won't-fix.
@JS00001 For this issue, the PR is in draft and actively being worked on.
For this issue, all the PRs have been merged, each and everything has been covered, 7 days regression period is going on there. The follow up work needs to be done, which I'm investigating as I mentioned that in this comment
Activity
applause-bot commentedon Sep 29, 2026
While Applause doesn't embed attachments for this bug, here are the links for quick view:
https://platform.applause.com/services/links/v1/external/0053566184c8b90f59c957cb9d9bccc744e8b12f92540105d13c8c03e4304f3c
melvin-bot commentedon Sep 29, 2026
You have been assigned to this deploy blocker because you recently merged this PR: #100421
melvin-bot commentedon Sep 29, 2026
@JS00001 @linhvovan29546 you have been assigned to this deploy blocker because you reviewed the offending PR: #100421
melvin-bot commentedon Sep 29, 2026
💬 A slack conversation has been started in #expensify-open-source
github-actions commentedon Sep 29, 2026
👋 Friendly reminder that deploy blockers are time-sensitive ⏱ issues! Check out the open `StagingDeployCash` deploy checklist to see the list of PRs included in this release, then work quickly to do one of the following:
MelvinBot commentedon Sep 29, 2026
🔍 Investigation Summary
Classification: Frontend, expected behavior newly visible in the composer
Causing PR: fix: preserve Markdown formatting in long messages by
Uzaifm127. That PR made the behavior visible. It did not add a new autolink bug.Related issue: [$250] Chat - Live markdown in composer is removed if the text exceeds 4000 characters
Recommendation: DEMOTE (do not revert)
The link is correct under the existing autolink rule.
'a.'.repeat(4499) + 'a'stays plain because no TLD is one letter long. Typing a letter such asdorechanges the last label toadorae. Those are real country-code TLDs, so the string is now a valid hostname.Production already links this exact message once you send it. It also already highlights shorter versions in the composer. The only change is that the composer now parses text longer than 4,000 characters. That was the goal of the PR. A revert would bring back the related issue above to fix a synthetic 9,000-character input.
📋 Detailed analysis
Why it reproduces only on staging
The PR raised the composer's live-markdown parse limit from 4,000 to
CONST.MAX_MARKUP_LENGTH(10,000).react-native-live-markdown0.1.336), the composer gets no formatting for text over 4,000 characters: parseExpensiMark.ts#L242maxLengthargument: parseExpensiMark.ts#L248-L251. App passes 10,000 from src/libs/ParsingUtils.ts:61-66, and the composer uses it at src/components/RNMarkdownTextInput.tsx:70.Which characters trigger a link
aplus the letter is a ccTLD:c d e f g i l m o q r s t u w x zb h j k n p v y, and any digitThe URL rule has not changed
URL_WEBSITE_REGEXaccepts any number of one-character labels followed by a known TLD. It is the same in expensify-common 2.0.204 (production) and 2.0.207 (staging).findHostnameStart,findKnownTldEnd,findUrlCandidates) in fix: preserve raw HTML parsing and optimize invalid URL scanning. It only speeds up the search. It gives the same result as the old full-text regex. Its dot-heavy test is a performance guard. It does not promise that every variation of that string stays plain.Production already links the sent message
When you send a message, src/libs/ReportUtils.ts:6933-6935 skips Markdown only above
MAX_MARKUP_LENGTH(src/CONST/index.ts:5868, 10,000). So this 9,001-character message is already linked after sending on production. The staging composer now shows the same result as the sent message.No other PR in the checklist is involved
Between production and staging, the parsing-related files (
package.json,src/libs/ParsingUtils.ts,src/libs/EmojiUtils.tsx) changed only through the PR above.Optional follow-up (not a blocker)
To stop absurd hostnames like this from linking, apply DNS limits in
expensify-common's URL regex and candidate scanner: 253 characters total and 63 characters per label. This would also change how production renders sent messages. The PR's QA Test 3 should also be updated. It expects no link after you "type several characters", which is wrong for any character that completes a TLD.Note: this comes from reading the code in
expensify-common2.0.207 andreact-native-live-markdown0.1.342. I did not run the parser locally.cc
JS00001linhvovan29546Uzaifm127, please confirm demotion.view run
linhvovan29546 commentedon Sep 29, 2026
I think we can demote this based on the Investigation Summary above. I’ve tested it in production as well. cc @JS00001 @Uzaifm127
Uzaifm127 commentedon Sep 29, 2026
Yes, we can demote as it is also there in prod. I also agree with Melvin analysis
Screen.Recording.2026-09-29.at.10.20.27.AM.mov
1 remaining item
JS00001 commentedon Oct 2, 2026
@Uzaifm127 are we able to fix this one?
Uzaifm127 commentedon Oct 2, 2026
@JS00001 Yes, this will be handled by this PR. It applies the 253 character hostname limit, so the long heavy dotted URL in this issue will no longer become an autolink.
A dotted URL with a hostname below 253 characters will still become an autolink when its labels are valid and it ends with a valid TLD. I think this is expected because it is still a valid hostname format, and I do not think users are likely to paste a URL like
a.a.a.a.a.a...in the composer. The long dotted input from this issue is the case we need to handle, and it will no longer become an autolink after this PR.To prevent those URLs further from becoming autolinks too, ExpensiMark would need to check whether each domain actually exists through a DNS lookup, which is not something the parser does or should do.
@linhvovan29546 What do you think?
JS00001 commentedon Oct 5, 2026
Looking at this again. I don't know if this is worth the time to handle. This doesnt seem like a realistic case that we'd ever run into
linhvovan29546 commentedon Oct 5, 2026
Agree with @JS00001 not worth the time. Even with the 253-char hostname limit from #951, any substring under that limit with valid labels ending in a real TLD is still a technically valid hostname, so it'd still autolink. The fix only patches the pathological >253 char case, which isn't a realistic input anyway. I'd vote to close this as won't-fix.
Uzaifm127 commentedon Oct 5, 2026
Yep, my vote is also up to close this issue.
JS00001 commentedon Oct 5, 2026
Lets close this one then and go back to the original issue. Is anything left there?
Uzaifm127 commentedon Oct 5, 2026
@JS00001 For this issue, the PR is in draft and actively being worked on.
For this issue, all the PRs have been merged, each and everything has been covered, 7 days regression period is going on there. The follow up work needs to be done, which I'm investigating as I mentioned that in this comment
Thanks