@linkforty/core 1.26.0 → 1.27.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/dist/lib/launchpad.d.ts +29 -4
- package/dist/lib/launchpad.d.ts.map +1 -1
- package/dist/lib/launchpad.js +32 -6
- package/dist/lib/launchpad.js.map +1 -1
- package/dist/lib/launchpad.test.js +21 -1
- package/dist/lib/launchpad.test.js.map +1 -1
- package/dist/lib/link-safety.d.ts +11 -0
- package/dist/lib/link-safety.d.ts.map +1 -1
- package/dist/lib/link-safety.js +22 -0
- package/dist/lib/link-safety.js.map +1 -1
- package/dist/routes/redirect.d.ts.map +1 -1
- package/dist/routes/redirect.interstitial.test.d.ts +2 -0
- package/dist/routes/redirect.interstitial.test.d.ts.map +1 -0
- package/dist/routes/redirect.interstitial.test.js +128 -0
- package/dist/routes/redirect.interstitial.test.js.map +1 -0
- package/dist/routes/redirect.js +165 -100
- package/dist/routes/redirect.js.map +1 -1
- package/dist/routes/redirect.launchpad.test.js +143 -0
- package/dist/routes/redirect.launchpad.test.js.map +1 -1
- package/llms.txt +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -243,7 +243,7 @@ Automatically redirects users to the appropriate URL based on device type (iOS/A
|
|
|
243
243
|
|
|
244
244
|
**Launchpad page (desktop):** A link to app-only content has nowhere to send a desktop visitor. When the chain resolves no web destination (link → template → workspace `appConfig`), a desktop request gets a hosted landing page instead of an error: the link's title, description and image (`ogTitle` / `ogDescription` / `ogImageUrl`, falling back to `title` / `description`), the app's icon and name, App Store / Google Play buttons, and a QR code so the visitor can finish on their phone. The page is `noindex`, sent with `Cache-Control: no-store` and a content-security policy that allows no script without a per-response nonce, and it never navigates on its own — no timers, no automatic scheme attempts.
|
|
245
245
|
|
|
246
|
-
By default it appears **only** where the alternative is nothing; a link that resolves to a destination still gets its 302. Two knobs change that:
|
|
246
|
+
When the link does have a web destination, the page offers it as a "Continue on the web" link, so a visitor is never trapped. By default it appears **only** where the alternative is nothing; a link that resolves to a destination still gets its 302. Two knobs change that:
|
|
247
247
|
|
|
248
248
|
- `organizations.settings.launchpad` (per workspace):
|
|
249
249
|
|
|
@@ -251,6 +251,7 @@ By default it appears **only** where the alternative is nothing; a link that res
|
|
|
251
251
|
{
|
|
252
252
|
"launchpad": {
|
|
253
253
|
"desktop": "no-destination", // "no-destination" (default) | "always" | "off"
|
|
254
|
+
"mobile": "store", // "store" (default) | "page"
|
|
254
255
|
"appName": "Ride Alert",
|
|
255
256
|
"appIconUrl": "https://cdn.example/icon.png",
|
|
256
257
|
"accentColor": "#0f766e"
|
|
@@ -262,6 +263,8 @@ By default it appears **only** where the alternative is nothing; a link that res
|
|
|
262
263
|
|
|
263
264
|
With `desktop: "off"` (or `launchpad_mode: "off"`), a link with no web destination gets the plain "This link opens in an app" page instead.
|
|
264
265
|
|
|
266
|
+
**Launchpad page (mobile):** With `mobile: "page"`, a phone visitor whose platform has no Universal Link / App Link on the link gets the same page instead of the store redirect or the scheme interstitial: an "Open in app" button when the link has a URI scheme (a tap, not a navigation — the URL fragment is appended on tap), the visitor's own store button, and the web fallback as a "Continue on the web" link. That last one matters inside in-app browsers (Gmail, Facebook, Instagram…), which bypass Universal Links: the store redirect would send someone who *has* the app to the store, so the redirect path prefers the web fallback there to give the OS a second chance on the next hop — and the page keeps that hop available as a tap. Links that carry a Universal Link / App Link keep their 302 regardless, because the OS resolves the installed case before the request reaches this server. `launchpad_mode: "off"` opts a link out; `"on"` does not force the page onto a workspace that chose `"store"`. The default, `"store"`, is unchanged behaviour.
|
|
267
|
+
|
|
265
268
|
Two hooks on `RedirectRouteOptions` let a host application extend the page without forking it — see [Server Options](#server-options).
|
|
266
269
|
|
|
267
270
|
### QR Codes
|
package/dist/lib/launchpad.d.ts
CHANGED
|
@@ -35,9 +35,11 @@ export interface LaunchpadSettings {
|
|
|
35
35
|
/** When a desktop visitor gets the page. Default `no-destination`. */
|
|
36
36
|
desktop?: LaunchpadDesktopMode;
|
|
37
37
|
/**
|
|
38
|
-
* What a mobile visitor
|
|
39
|
-
*
|
|
40
|
-
*
|
|
38
|
+
* What a mobile visitor gets when the link has no Universal Link / App Link
|
|
39
|
+
* for their platform. Default `store`: today's behaviour — a redirect to the
|
|
40
|
+
* store, or the scheme interstitial when the link has a URI scheme. `page`
|
|
41
|
+
* serves the launchpad page instead, with "Open in app" as a button the
|
|
42
|
+
* visitor taps rather than a navigation the page performs.
|
|
41
43
|
*/
|
|
42
44
|
mobile?: LaunchpadMobileMode;
|
|
43
45
|
/** Shown in the page header, and as the `<title>` fallback. */
|
|
@@ -104,6 +106,21 @@ export declare function shouldServeLaunchpadOnDesktop(input: {
|
|
|
104
106
|
orgMode?: LaunchpadDesktopMode;
|
|
105
107
|
linkMode?: LaunchpadLinkMode;
|
|
106
108
|
}): boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Whether a mobile visitor gets the page.
|
|
111
|
+
*
|
|
112
|
+
* Only when the workspace chose `page`, and never for a platform whose link
|
|
113
|
+
* carries a Universal Link / App Link: the OS resolves the installed case
|
|
114
|
+
* before this server sees the click, and the 302 to that URL must stay so it
|
|
115
|
+
* can. A link's `on` does not force the page onto a workspace that chose
|
|
116
|
+
* `store` — that would be the extra hop other products had to add a skip flag
|
|
117
|
+
* for — but `off` still opts a link out.
|
|
118
|
+
*/
|
|
119
|
+
export declare function shouldServeLaunchpadOnMobile(input: {
|
|
120
|
+
mobileMode?: LaunchpadMobileMode;
|
|
121
|
+
linkMode?: LaunchpadLinkMode;
|
|
122
|
+
hasAppOpenPath: boolean;
|
|
123
|
+
}): boolean;
|
|
107
124
|
/** Content from the link row alone: what any deployment can show with no extra machinery. */
|
|
108
125
|
export declare function defaultLaunchpadContent(link: LaunchpadLinkFields, settings: LaunchpadSettings): LaunchpadContent;
|
|
109
126
|
/** A fresh CSP nonce per response. */
|
|
@@ -126,6 +143,14 @@ export interface LaunchpadPageContext {
|
|
|
126
143
|
pageUrl: string;
|
|
127
144
|
iosUrl: string | null;
|
|
128
145
|
androidUrl: string | null;
|
|
146
|
+
/**
|
|
147
|
+
* The link's web destination, when it has one. Rendered as a plain
|
|
148
|
+
* "Continue on the web" link so the page is never a dead end: a desktop
|
|
149
|
+
* visitor in `always` mode still has the destination the 302 would have
|
|
150
|
+
* given them, and a phone visitor inside an in-app browser keeps the path
|
|
151
|
+
* that lets a Universal Link fire on the next hop.
|
|
152
|
+
*/
|
|
153
|
+
webUrl?: string | null;
|
|
129
154
|
/**
|
|
130
155
|
* The app's URI-scheme URL for this link, or null. When set, an "Open in app"
|
|
131
156
|
* button is rendered whose only job is to navigate to it on tap. The URL
|
|
@@ -138,7 +163,7 @@ export interface LaunchpadPageContext {
|
|
|
138
163
|
nonce: string;
|
|
139
164
|
/**
|
|
140
165
|
* When set, the page reports `view` on load and `cta_ios` / `cta_android` /
|
|
141
|
-
* `cta_open` on the matching tap via `navigator.sendBeacon`, as a JSON body
|
|
166
|
+
* `cta_open` / `cta_web` on the matching tap via `navigator.sendBeacon`, as a JSON body
|
|
142
167
|
* `{ linkId, event }`. No cookies, no identifiers. Absent by default; the
|
|
143
168
|
* endpoint is the host application's to provide.
|
|
144
169
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"launchpad.d.ts","sourceRoot":"","sources":["../../src/lib/launchpad.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,MAAM,MAAM,oBAAoB,GAAG,gBAAgB,GAAG,QAAQ,GAAG,KAAK,CAAC;AACvE,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,MAAM,CAAC;AACnD,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,IAAI,GAAG,KAAK,CAAC;AAEzD;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,sEAAsE;IACtE,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B
|
|
1
|
+
{"version":3,"file":"launchpad.d.ts","sourceRoot":"","sources":["../../src/lib/launchpad.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/launchpad.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { randomBytes } from 'crypto';
|
|
2
|
-
import { escapeHtml, safeHref } from './link-safety.js';
|
|
2
|
+
import { escapeHtml, safeHref, safeSchemeHref } from './link-safety.js';
|
|
3
3
|
const DESKTOP_MODES = ['no-destination', 'always', 'off'];
|
|
4
4
|
const MOBILE_MODES = ['store', 'page'];
|
|
5
5
|
const LINK_MODES = ['inherit', 'on', 'off'];
|
|
@@ -54,6 +54,23 @@ export function shouldServeLaunchpadOnDesktop(input) {
|
|
|
54
54
|
return !input.hasWebDestination;
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Whether a mobile visitor gets the page.
|
|
59
|
+
*
|
|
60
|
+
* Only when the workspace chose `page`, and never for a platform whose link
|
|
61
|
+
* carries a Universal Link / App Link: the OS resolves the installed case
|
|
62
|
+
* before this server sees the click, and the 302 to that URL must stay so it
|
|
63
|
+
* can. A link's `on` does not force the page onto a workspace that chose
|
|
64
|
+
* `store` — that would be the extra hop other products had to add a skip flag
|
|
65
|
+
* for — but `off` still opts a link out.
|
|
66
|
+
*/
|
|
67
|
+
export function shouldServeLaunchpadOnMobile(input) {
|
|
68
|
+
if ((input.linkMode ?? 'inherit') === 'off')
|
|
69
|
+
return false;
|
|
70
|
+
if ((input.mobileMode ?? 'store') !== 'page')
|
|
71
|
+
return false;
|
|
72
|
+
return !input.hasAppOpenPath;
|
|
73
|
+
}
|
|
57
74
|
/** Content from the link row alone: what any deployment can show with no extra machinery. */
|
|
58
75
|
export function defaultLaunchpadContent(link, settings) {
|
|
59
76
|
const image = link.og_image_url && safeHref(link.og_image_url) ? link.og_image_url : null;
|
|
@@ -125,6 +142,9 @@ const STYLES = `
|
|
|
125
142
|
.lp-btn { display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem; padding: 0.8rem 1.25rem; border-radius: 10px; font-size: 0.95rem; font-weight: 600; text-decoration: none; border: 1px solid var(--lp-line); background: var(--lp-surface); color: var(--lp-ink); }
|
|
126
143
|
.lp-btn-primary { background: var(--lp-accent); border-color: var(--lp-accent); color: var(--lp-accent-ink); }
|
|
127
144
|
.lp-btn:focus-visible { outline: 2px solid var(--lp-accent); outline-offset: 2px; }
|
|
145
|
+
.lp-web { margin: -0.5rem 0 0; font-size: 0.95rem; }
|
|
146
|
+
.lp-web a { color: var(--lp-muted); text-decoration: underline; text-underline-offset: 3px; }
|
|
147
|
+
.lp-web a:hover { color: var(--lp-ink); }
|
|
128
148
|
.lp-qr { display: flex; align-items: center; gap: 1.25rem; padding: 1rem; border: 1px solid var(--lp-line); border-radius: 14px; background: var(--lp-surface); }
|
|
129
149
|
.lp-qr img { width: 132px; height: 132px; border-radius: 8px; background: #fff; flex: none; }
|
|
130
150
|
.lp-qr strong { display: block; font-size: 1rem; margin-bottom: 0.2rem; }
|
|
@@ -190,24 +210,29 @@ export function renderLaunchpadPage(ctx) {
|
|
|
190
210
|
const hero = content.heroHtml
|
|
191
211
|
? `<section class="lp-hero">${content.heroHtml}</section>`
|
|
192
212
|
: `<section class="lp-hero">${imageUrl ? `<img src="${imageUrl}" alt="">` : ''}<h1>${title}</h1>${description ? `<p>${description}</p>` : ''}</section>`;
|
|
213
|
+
const schemeUrl = ctx.schemeUrl && safeSchemeHref(ctx.schemeUrl) ? escapeHtml(ctx.schemeUrl) : null;
|
|
193
214
|
const buttons = [
|
|
194
|
-
|
|
195
|
-
? `<a class="lp-btn lp-btn-primary" id="lp-open" data-lp-cta="cta_open" data-scheme="${
|
|
215
|
+
schemeUrl
|
|
216
|
+
? `<a class="lp-btn lp-btn-primary" id="lp-open" data-lp-cta="cta_open" data-scheme="${schemeUrl}" href="${schemeUrl}">Open in app</a>`
|
|
196
217
|
: '',
|
|
197
218
|
iosUrl
|
|
198
|
-
? `<a class="lp-btn${
|
|
219
|
+
? `<a class="lp-btn${schemeUrl ? '' : ' lp-btn-primary'}" data-lp-cta="cta_ios" href="${iosUrl}">Download on the App Store</a>`
|
|
199
220
|
: '',
|
|
200
221
|
androidUrl
|
|
201
|
-
? `<a class="lp-btn${
|
|
222
|
+
? `<a class="lp-btn${schemeUrl || iosUrl ? '' : ' lp-btn-primary'}" data-lp-cta="cta_android" href="${androidUrl}">Get it on Google Play</a>`
|
|
202
223
|
: '',
|
|
203
224
|
]
|
|
204
225
|
.filter(Boolean)
|
|
205
226
|
.join('');
|
|
227
|
+
const webUrl = ctx.webUrl && safeHref(ctx.webUrl) ? escapeHtml(ctx.webUrl) : null;
|
|
206
228
|
const actions = buttons ? `<section class="lp-actions">${buttons}</section>` : '';
|
|
229
|
+
const web = webUrl
|
|
230
|
+
? `<p class="lp-web"><a data-lp-cta="cta_web" href="${webUrl}">Continue on the web</a></p>`
|
|
231
|
+
: '';
|
|
207
232
|
const qr = ctx.showQr
|
|
208
233
|
? `<section class="lp-qr"><img src="/api/links/${escapeHtml(ctx.linkId)}/qr?format=svg&size=264" alt="QR code for this link" width="132" height="132"><div><strong>Scan to open on your phone</strong><p>Point your phone's camera at the code to open this link there.</p></div></section>`
|
|
209
234
|
: '';
|
|
210
|
-
const needsScript = Boolean(
|
|
235
|
+
const needsScript = Boolean(schemeUrl || ctx.beaconUrl);
|
|
211
236
|
const bodyAttrs = [
|
|
212
237
|
`data-link-id="${escapeHtml(ctx.linkId)}"`,
|
|
213
238
|
ctx.beaconUrl ? `data-beacon="${escapeHtml(ctx.beaconUrl)}"` : '',
|
|
@@ -228,6 +253,7 @@ ${head}
|
|
|
228
253
|
${header}
|
|
229
254
|
${hero}
|
|
230
255
|
${actions}
|
|
256
|
+
${web}
|
|
231
257
|
${qr}
|
|
232
258
|
</main>
|
|
233
259
|
${needsScript ? `<script nonce="${nonce}">${SCRIPT}</script>` : ''}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"launchpad.js","sourceRoot":"","sources":["../../src/lib/launchpad.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"launchpad.js","sourceRoot":"","sources":["../../src/lib/launchpad.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { defaultLaunchpadContent, launchpadContentSecurityPolicy, readLaunchpadLinkMode, readLaunchpadSettings, renderLaunchpadPage, shouldServeLaunchpadOnDesktop, } from './launchpad.js';
|
|
2
|
+
import { defaultLaunchpadContent, launchpadContentSecurityPolicy, readLaunchpadLinkMode, readLaunchpadSettings, renderLaunchpadPage, shouldServeLaunchpadOnDesktop, shouldServeLaunchpadOnMobile, } from './launchpad.js';
|
|
3
3
|
describe('shouldServeLaunchpadOnDesktop', () => {
|
|
4
4
|
/** The full decision table: link mode × workspace mode × whether a destination exists. */
|
|
5
5
|
const table = [
|
|
@@ -18,6 +18,20 @@ describe('shouldServeLaunchpadOnDesktop', () => {
|
|
|
18
18
|
it(name, () => expect(shouldServeLaunchpadOnDesktop(input)).toBe(expected));
|
|
19
19
|
}
|
|
20
20
|
});
|
|
21
|
+
describe('shouldServeLaunchpadOnMobile', () => {
|
|
22
|
+
const table = [
|
|
23
|
+
['defaults → store', { hasAppOpenPath: false }, false],
|
|
24
|
+
['store explicitly → store', { hasAppOpenPath: false, mobileMode: 'store' }, false],
|
|
25
|
+
['page → page', { hasAppOpenPath: false, mobileMode: 'page' }, true],
|
|
26
|
+
['page, but a Universal Link / App Link → the OS handles it', { hasAppOpenPath: true, mobileMode: 'page' }, false],
|
|
27
|
+
['page, link off → store', { hasAppOpenPath: false, mobileMode: 'page', linkMode: 'off' }, false],
|
|
28
|
+
['page, link on → page', { hasAppOpenPath: false, mobileMode: 'page', linkMode: 'on' }, true],
|
|
29
|
+
['store, link on → still store (on never forces a hop)', { hasAppOpenPath: false, mobileMode: 'store', linkMode: 'on' }, false],
|
|
30
|
+
];
|
|
31
|
+
for (const [name, input, expected] of table) {
|
|
32
|
+
it(name, () => expect(shouldServeLaunchpadOnMobile(input)).toBe(expected));
|
|
33
|
+
}
|
|
34
|
+
});
|
|
21
35
|
describe('readLaunchpadSettings', () => {
|
|
22
36
|
it('returns {} for anything that is not a settings object', () => {
|
|
23
37
|
expect(readLaunchpadSettings(null)).toEqual({});
|
|
@@ -192,6 +206,12 @@ describe('renderLaunchpadPage', () => {
|
|
|
192
206
|
expect(html).not.toContain('meta name="description"');
|
|
193
207
|
expect(html).toContain('<meta name="twitter:card" content="summary">');
|
|
194
208
|
});
|
|
209
|
+
it('offers the web destination as a link only when given one that is http(s)', () => {
|
|
210
|
+
expect(renderLaunchpadPage(base)).not.toContain('Continue on the web');
|
|
211
|
+
const html = renderLaunchpadPage({ ...base, webUrl: 'https://example.com/page?a=1&b=2' });
|
|
212
|
+
expect(html).toContain('<a data-lp-cta="cta_web" href="https://example.com/page?a=1&b=2">Continue on the web</a>');
|
|
213
|
+
expect(renderLaunchpadPage({ ...base, webUrl: 'javascript:alert(1)' })).not.toContain('Continue on the web');
|
|
214
|
+
});
|
|
195
215
|
it('uses dark button text on a light accent', () => {
|
|
196
216
|
const html = renderLaunchpadPage({ ...base, content: { ...base.content, theme: { accentColor: '#ffe066' } } });
|
|
197
217
|
expect(html).toContain('--lp-accent: #ffe066; --lp-accent-ink: #16181d;');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"launchpad.test.js","sourceRoot":"","sources":["../../src/lib/launchpad.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"launchpad.test.js","sourceRoot":"","sources":["../../src/lib/launchpad.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -120,6 +120,17 @@ export declare function evaluateLinkSafety(input: LinkSafetyInput): LinkSafetyOu
|
|
|
120
120
|
* rather than the real destination. Callers render that as inert text.
|
|
121
121
|
*/
|
|
122
122
|
export declare function safeHref(destination: string): string | null;
|
|
123
|
+
/**
|
|
124
|
+
* Accept a URI-scheme URL (`myapp://…`, `com.example.app://…`) for an href that
|
|
125
|
+
* is meant to open a native app, rejecting the schemes a browser would execute
|
|
126
|
+
* instead. `safeHref` is the wrong tool here — it admits only http(s), which is
|
|
127
|
+
* the one family a scheme link is not.
|
|
128
|
+
*
|
|
129
|
+
* Returns null when the value has no scheme, or a scheme on the executable list.
|
|
130
|
+
* The check is on the raw string, not `new URL()`: WHATWG parsing of unknown
|
|
131
|
+
* schemes is permissive about whitespace and case, and this must not be.
|
|
132
|
+
*/
|
|
133
|
+
export declare function safeSchemeHref(url: string): string | null;
|
|
123
134
|
/** Minimal HTML escaping for interpolating a URL into markup and an href. */
|
|
124
135
|
export declare function escapeHtml(value: string): string;
|
|
125
136
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link-safety.d.ts","sourceRoot":"","sources":["../../src/lib/link-safety.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;AAE3D,MAAM,WAAW,eAAe;IAC9B,yEAAyE;IACzE,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1B,qEAAqE;IACrE,MAAM,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;IAC9B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;IACxC;;;;;;;;;;;OAWG;IACH,UAAU,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,wEAAwE;AACxE,MAAM,MAAM,cAAc,GAAG,iBAAiB,GAAG,UAAU,GAAG,UAAU,CAAC;AAEzE,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,8CAA8C;IAC9C,KAAK,CAAC,EAAE,cAAc,CAAC;CACxB;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,GAAG,SAAS,GAAG,OAAO,CAE5E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,eAAe,GAAG,kBAAkB,CAMrF;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,eAAe,GAAG,iBAAiB,CAE5E;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ3D;AAED,6EAA6E;AAC7E,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOhD;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACnC,MAAM,CA4DR;AAoBD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CA+BhD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE;IAChD,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,OAAO,EAAE,CAAA;KAAE,CAAC,CAAC;IACrD,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1B,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,CAkBxB"}
|
|
1
|
+
{"version":3,"file":"link-safety.d.ts","sourceRoot":"","sources":["../../src/lib/link-safety.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;AAE3D,MAAM,WAAW,eAAe;IAC9B,yEAAyE;IACzE,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1B,qEAAqE;IACrE,MAAM,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;IAC9B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;IACxC;;;;;;;;;;;OAWG;IACH,UAAU,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,wEAAwE;AACxE,MAAM,MAAM,cAAc,GAAG,iBAAiB,GAAG,UAAU,GAAG,UAAU,CAAC;AAEzE,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,8CAA8C;IAC9C,KAAK,CAAC,EAAE,cAAc,CAAC;CACxB;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,GAAG,SAAS,GAAG,OAAO,CAE5E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,eAAe,GAAG,kBAAkB,CAMrF;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,eAAe,GAAG,iBAAiB,CAE5E;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ3D;AASD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIzD;AAED,6EAA6E;AAC7E,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOhD;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACnC,MAAM,CA4DR;AAoBD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CA+BhD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE;IAChD,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,OAAO,EAAE,CAAA;KAAE,CAAC,CAAC;IACrD,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1B,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,CAkBxB"}
|
package/dist/lib/link-safety.js
CHANGED
|
@@ -70,6 +70,28 @@ export function safeHref(destination) {
|
|
|
70
70
|
}
|
|
71
71
|
return url.protocol === 'http:' || url.protocol === 'https:' ? destination : null;
|
|
72
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* Schemes a browser will execute or treat as local content rather than hand to
|
|
75
|
+
* another application. A URI-scheme link exists to open a native app; nothing on
|
|
76
|
+
* this list is one.
|
|
77
|
+
*/
|
|
78
|
+
const EXECUTABLE_SCHEMES = new Set(['javascript', 'data', 'vbscript', 'file', 'blob', 'about']);
|
|
79
|
+
/**
|
|
80
|
+
* Accept a URI-scheme URL (`myapp://…`, `com.example.app://…`) for an href that
|
|
81
|
+
* is meant to open a native app, rejecting the schemes a browser would execute
|
|
82
|
+
* instead. `safeHref` is the wrong tool here — it admits only http(s), which is
|
|
83
|
+
* the one family a scheme link is not.
|
|
84
|
+
*
|
|
85
|
+
* Returns null when the value has no scheme, or a scheme on the executable list.
|
|
86
|
+
* The check is on the raw string, not `new URL()`: WHATWG parsing of unknown
|
|
87
|
+
* schemes is permissive about whitespace and case, and this must not be.
|
|
88
|
+
*/
|
|
89
|
+
export function safeSchemeHref(url) {
|
|
90
|
+
const match = /^([a-z][a-z0-9+.-]*):/i.exec(url);
|
|
91
|
+
if (!match)
|
|
92
|
+
return null;
|
|
93
|
+
return EXECUTABLE_SCHEMES.has(match[1].toLowerCase()) ? null : url;
|
|
94
|
+
}
|
|
73
95
|
/** Minimal HTML escaping for interpolating a URL into markup and an href. */
|
|
74
96
|
export function escapeHtml(value) {
|
|
75
97
|
return String(value)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link-safety.js","sourceRoot":"","sources":["../../src/lib/link-safety.ts"],"names":[],"mappings":"AA6EA;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAiC;IACjE,OAAO,KAAK,KAAK,iBAAiB,IAAI,KAAK,KAAK,UAAU,CAAC;AAC7D,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,0BAA0B,CAAC,KAAsB;IAC/D,IAAI,KAAK,CAAC,gBAAgB,IAAI,IAAI;QAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC1F,IAAI,KAAK,CAAC,UAAU,IAAI,IAAI;QAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;IAC7E,IAAI,KAAK,CAAC,QAAQ,KAAK,KAAK;QAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;IAC7E,IAAI,KAAK,CAAC,MAAM,IAAI,IAAI;QAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IACrD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC9B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAsB;IACvD,OAAO,0BAA0B,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC;AACnD,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,QAAQ,CAAC,WAAmB;IAC1C,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC;AACpF,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,MAAM,CAAC,KAAK,CAAC;SACjB,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC5B,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,uBAAuB,CACrC,WAAmB,EACnB,UAAkC,EAAE;IAEpC,MAAM,KAAK,GAAG,WAAW,IAAI,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,2BAA2B,CAAC;IACxG,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACxD,2EAA2E;IAC3E,0EAA0E;IAC1E,MAAM,cAAc,GAAG,IAAI;QACzB,CAAC,CAAC,uBAAuB,UAAU,CAAC,IAAI,CAAC,0DAA0D;QACnG,CAAC,CAAC,mGAAmG,CAAC;IACxG,MAAM,UAAU,GAAG,OAAO,CAAC,SAAS;QAClC,CAAC,CAAC,8BAA8B,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,oDAAoD;QACjH,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAuCgB,KAAK;;;;MAIxB,cAAc;MACd,UAAU;;;QAGR,CAAC;AACT,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,YAAY,GAAG;IACnB,KAAK,EAAE,kCAAkC;IACzC,OAAO,EAAE,kCAAkC;IAC3C,IAAI,EAAE,6CAA6C;CAC3C,CAAC;AAEX;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO;;;;;;SAMA,YAAY,CAAC,KAAK;;;;;;;;;;;;;;;;;;;UAmBjB,YAAY,CAAC,OAAO;SACrB,YAAY,CAAC,IAAI;;;QAGlB,CAAC;AACT,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,2BAA2B,CAAC,IAG3C;IACC,IAAI,KAAK,GAA2B,IAAI,CAAC;IACzC,OAAO,GAAG,EAAE;QACV,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,KAAK,GAAG,IAAI;iBACT,KAAK,CACJ;+EACqE,CACtE;iBACA,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;gBACV,MAAM,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;gBACpC,IAAI,SAAS;oBAAE,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;gBACpC,OAAO,SAAS,CAAC,CAAC,CAAC,wCAAwC,CAAC,CAAC,CAAC,EAAE,CAAC;YACnE,CAAC,CAAC;iBACD,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QACrB,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;AACJ,CAAC"}
|
|
1
|
+
{"version":3,"file":"link-safety.js","sourceRoot":"","sources":["../../src/lib/link-safety.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redirect.d.ts","sourceRoot":"","sources":["../../src/routes/redirect.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"redirect.d.ts","sourceRoot":"","sources":["../../src/routes/redirect.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAgB1C,OAAO,EASL,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACvB,MAAM,qBAAqB,CAAC;AAE7B;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAa5D;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAiBhE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,KAAK,GAAG,SAAS,EACzB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,cAAc,EAAE,MAAM,GAAG,IAAI,GAC5B;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAexC;AAmID,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,SAAS,CAAC,EAAE;QACV;;;;WAIG;QACH,cAAc,CAAC,EAAE,CACf,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,QAAQ,EAAE,iBAAiB,KACxB,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,GAAG,gBAAgB,GAAG,IAAI,CAAC;QAChE;;;;WAIG;QACH,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,eAAe,EACxB,OAAO,GAAE,oBAAyB,iBAgtBnC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redirect.interstitial.test.d.ts","sourceRoot":"","sources":["../../src/routes/redirect.interstitial.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The mobile scheme interstitial: the page a phone gets when a link has a URI
|
|
3
|
+
* scheme, which tries the app and falls back to the store.
|
|
4
|
+
*
|
|
5
|
+
* Its two URLs used to be interpolated into JavaScript source with `"` and `<`
|
|
6
|
+
* replaced — enough to keep a value inside its string literal only until the
|
|
7
|
+
* value contained a backslash or a line terminator. They now reach the document
|
|
8
|
+
* as attributes and the script reads them back, so the JavaScript contains no
|
|
9
|
+
* configured value at all.
|
|
10
|
+
*/
|
|
11
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
12
|
+
import Fastify from 'fastify';
|
|
13
|
+
import { redirectRoutes } from './redirect.js';
|
|
14
|
+
import { safeSchemeHref } from '../lib/link-safety.js';
|
|
15
|
+
const query = vi.fn();
|
|
16
|
+
vi.mock('../lib/database.js', () => ({
|
|
17
|
+
db: {
|
|
18
|
+
query: (...args) => query(...args),
|
|
19
|
+
},
|
|
20
|
+
}));
|
|
21
|
+
const IPHONE_UA = 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1';
|
|
22
|
+
function linkRow(overrides = {}) {
|
|
23
|
+
return {
|
|
24
|
+
id: '00000000-0000-0000-0000-0000000000aa',
|
|
25
|
+
short_code: 'abc123',
|
|
26
|
+
title: null,
|
|
27
|
+
og_title: null,
|
|
28
|
+
original_url: null,
|
|
29
|
+
web_fallback_url: null,
|
|
30
|
+
ios_app_store_url: 'https://apps.apple.com/app/id1',
|
|
31
|
+
android_app_store_url: null,
|
|
32
|
+
ios_universal_link: null,
|
|
33
|
+
android_app_link: null,
|
|
34
|
+
app_scheme: 'demo',
|
|
35
|
+
deep_link_path: '/p/1',
|
|
36
|
+
custom_scheme_url: null,
|
|
37
|
+
launchpad_mode: 'inherit',
|
|
38
|
+
is_active: true,
|
|
39
|
+
warn_at: null,
|
|
40
|
+
owner_suspended_at: null,
|
|
41
|
+
expires_at: null,
|
|
42
|
+
targeting_rules: null,
|
|
43
|
+
template_settings: null,
|
|
44
|
+
org_settings: null,
|
|
45
|
+
utm_parameters: null,
|
|
46
|
+
deep_link_parameters: null,
|
|
47
|
+
append_click_id: false,
|
|
48
|
+
...overrides,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function mockDb(row) {
|
|
52
|
+
query.mockReset();
|
|
53
|
+
query.mockImplementation(async (sql) => {
|
|
54
|
+
if (/information_schema\.columns/i.test(sql))
|
|
55
|
+
return { rows: [{ '?column?': 1 }], rowCount: 1 };
|
|
56
|
+
if (/FROM links l/i.test(sql))
|
|
57
|
+
return { rows: row ? [row] : [], rowCount: row ? 1 : 0 };
|
|
58
|
+
return { rows: [], rowCount: 0 };
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
const get = (app) => app.inject({ method: 'GET', url: '/abc123', headers: { 'user-agent': IPHONE_UA } });
|
|
62
|
+
let app;
|
|
63
|
+
beforeEach(async () => {
|
|
64
|
+
app = Fastify();
|
|
65
|
+
await app.register(redirectRoutes);
|
|
66
|
+
await app.ready();
|
|
67
|
+
});
|
|
68
|
+
afterEach(async () => {
|
|
69
|
+
await new Promise((r) => setImmediate(r));
|
|
70
|
+
await app.close();
|
|
71
|
+
});
|
|
72
|
+
describe('scheme interstitial', () => {
|
|
73
|
+
it('serves the interstitial with the scheme and store URLs as attributes, and no configured value inside the script', async () => {
|
|
74
|
+
mockDb(linkRow({ deep_link_parameters: { x: '1', y: 'two words' } }));
|
|
75
|
+
const res = await get(app);
|
|
76
|
+
expect(res.statusCode).toBe(200);
|
|
77
|
+
expect(res.body).toContain('id="open-btn" href="demo://p/1?x=1&y=two+words"');
|
|
78
|
+
expect(res.body).toContain('id="store-btn" href="https://apps.apple.com/app/id1"');
|
|
79
|
+
const script = res.body.slice(res.body.indexOf('<script>'), res.body.indexOf('</script>'));
|
|
80
|
+
expect(script).not.toContain('demo://');
|
|
81
|
+
expect(script).not.toContain('apps.apple.com');
|
|
82
|
+
expect(script).toContain("openBtn.getAttribute('href') + hash");
|
|
83
|
+
expect(script).toContain("window.location.replace(storeBtn.getAttribute('href'))");
|
|
84
|
+
});
|
|
85
|
+
/**
|
|
86
|
+
* A custom scheme URL is operator-configured free text. A backslash before the
|
|
87
|
+
* closing quote, or a line terminator, used to end the JavaScript string
|
|
88
|
+
* literal early and take the whole script — auto-open and fallback timer —
|
|
89
|
+
* with it. Now it is an attribute value, escaped like any other.
|
|
90
|
+
*/
|
|
91
|
+
it('keeps a scheme URL with a quote, a backslash and a line separator out of the script', async () => {
|
|
92
|
+
mockDb(linkRow({ custom_scheme_url: 'demo://open?q="x"\\
</script><img src=x onerror=alert(1)>' }));
|
|
93
|
+
const res = await get(app);
|
|
94
|
+
expect(res.statusCode).toBe(200);
|
|
95
|
+
expect(res.body.match(/<\/script>/g)).toHaveLength(1);
|
|
96
|
+
expect(res.body).not.toContain('<img src=x');
|
|
97
|
+
expect(res.body).toContain('href="demo://open?q="x"\\
</script><img src=x onerror=alert(1)>"');
|
|
98
|
+
});
|
|
99
|
+
it('escapes an ampersand in the title, which the old generator left raw', async () => {
|
|
100
|
+
mockDb(linkRow({ title: 'Cats & Dogs <3' }));
|
|
101
|
+
const res = await get(app);
|
|
102
|
+
expect(res.body).toContain('<h1>Opening Cats & Dogs <3...</h1>');
|
|
103
|
+
});
|
|
104
|
+
it('treats an executable "scheme" as no scheme: store redirect, no interstitial, no scheme in Location', async () => {
|
|
105
|
+
mockDb(linkRow({ app_scheme: 'javascript', deep_link_path: '/%0aalert(1)' }));
|
|
106
|
+
const res = await get(app);
|
|
107
|
+
expect(res.statusCode).toBe(302);
|
|
108
|
+
expect(res.headers.location).toBe('https://apps.apple.com/app/id1');
|
|
109
|
+
expect(res.body).not.toContain('open-btn');
|
|
110
|
+
});
|
|
111
|
+
it('refuses an executable custom scheme URL even when app_scheme itself is fine', async () => {
|
|
112
|
+
mockDb(linkRow({ custom_scheme_url: 'javascript:alert(1)' }));
|
|
113
|
+
const res = await get(app);
|
|
114
|
+
expect(res.statusCode).toBe(302);
|
|
115
|
+
expect(res.headers.location).toBe('demo://p/1');
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
describe('safeSchemeHref', () => {
|
|
119
|
+
it('accepts app schemes and rejects the ones a browser executes', () => {
|
|
120
|
+
expect(safeSchemeHref('demo://p/1')).toBe('demo://p/1');
|
|
121
|
+
expect(safeSchemeHref('com.example.app://p/1')).toBe('com.example.app://p/1');
|
|
122
|
+
expect(safeSchemeHref('https://example.com/p')).toBe('https://example.com/p');
|
|
123
|
+
for (const bad of ['javascript:alert(1)', 'JavaScript://%0aalert(1)', 'data:text/html,hi', 'vbscript:x', 'file:///etc/passwd', 'blob:x', 'about:blank', 'no-scheme', '']) {
|
|
124
|
+
expect(safeSchemeHref(bad)).toBeNull();
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
//# sourceMappingURL=redirect.interstitial.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redirect.interstitial.test.js","sourceRoot":"","sources":["../../src/routes/redirect.interstitial.test.ts"],"names":[],"mappings":"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"}
|