@@ -17,6 +17,30 @@ const customLinks = new Map([
1717 [ "Vector2" , "/reference/Vector2" ]
1818] ) ;
1919
20+ function sanitizeUrl ( url ) {
21+ if ( typeof url !== "string" ) return null ;
22+
23+ // Allow root-relative URLs (e.g. "/reference/Vector3")
24+ if ( url . startsWith ( "/" ) ) {
25+ return url ;
26+ }
27+
28+ try {
29+ const parsed = new URL ( url , window . location . origin ) ;
30+ const protocol = parsed . protocol . toLowerCase ( ) ;
31+
32+ // Only allow http/https URLs
33+ if ( protocol === "http:" || protocol === "https:" ) {
34+ return parsed . href ;
35+ }
36+ } catch ( e ) {
37+ // If URL construction fails, treat as unsafe
38+ return null ;
39+ }
40+
41+ return null ;
42+ }
43+
2044function extractFunctions ( tmLanguage , textContent ) {
2145 const result = new Set ( ) ;
2246
@@ -93,13 +117,19 @@ function initKeywordLinker() {
93117 url = `https://www.lua.org/manual/5.1/manual.html#pdf-${ text } ` ;
94118 }
95119
120+ const safeUrl = sanitizeUrl ( url ) ;
121+ if ( ! safeUrl ) {
122+ // Do not create a link if the URL is unsafe
123+ return ;
124+ }
125+
96126 const a = document . createElement ( "a" ) ;
97- a . href = url ;
127+ a . href = safeUrl ;
98128 a . textContent = text ;
99129 a . className = "mta-keyword-link" ;
100130
101131 // Open external links in a new tab
102- const isExternalURL = / ^ h t t p s ? : \/ \/ / . test ( url ) ;
132+ const isExternalURL = / ^ h t t p s ? : \/ \/ / . test ( safeUrl ) ;
103133 if ( isExternalURL ) {
104134 a . target = "_blank" ;
105135 a . rel = "noopener noreferrer" ;
0 commit comments