@vellumai/credential-executor 0.10.12-staging.1 → 0.10.12-staging.2

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.
@@ -109,12 +109,77 @@ export type RemoteWebPairingTokenResponse =
109
109
  // only) so both Node and browser callers share one implementation.
110
110
 
111
111
  /** Why a public base URL can't be advertised in a pairing challenge. */
112
- export type PublicBaseUrlRejection = "unparseable" | "loopback" | "non-https";
112
+ export type PublicBaseUrlRejection =
113
+ | "unparseable"
114
+ | "loopback"
115
+ | "non-https"
116
+ | "service-website";
113
117
 
114
118
  export type PublicBaseUrlResult =
115
119
  | { ok: true; url: string }
116
120
  | { ok: false; reason: PublicBaseUrlRejection };
117
121
 
122
+ /**
123
+ * Hosts that are a tunnel/ingress vendor's own website, not a user's assistant
124
+ * endpoint. These are the tunnel vendors our docs mention, and their sites are
125
+ * exactly where a lost user grabs a URL from — e.g. a Tailscale admin invite
126
+ * link (`login.tailscale.com/admin/invite/…`), which is https and non-loopback
127
+ * and so clears every other check. Pairing refuses them with a targeted message
128
+ * rather than minting a challenge the scanning device can never reach.
129
+ */
130
+ export const TUNNEL_PROVIDER_WEBSITE_HOSTS = [
131
+ "login.tailscale.com",
132
+ "tailscale.com",
133
+ "www.tailscale.com",
134
+ "ngrok.com",
135
+ "dashboard.ngrok.com",
136
+ "dash.cloudflare.com",
137
+ "cloudflare.com",
138
+ "www.cloudflare.com",
139
+ ] as const;
140
+
141
+ /**
142
+ * A URL whose exact host is a tunnel/ingress vendor's own website (see
143
+ * {@link TUNNEL_PROVIDER_WEBSITE_HOSTS}). Exact-host only: a user's real
144
+ * Tailscale endpoint (`*.ts.net`) or Cloudflare-fronted domain is never a
145
+ * listed host, so a legitimate address is never mistaken for a vendor site.
146
+ */
147
+ export function isTunnelProviderWebsiteUrl(url: string): boolean {
148
+ let hostname: string;
149
+ try {
150
+ // WHATWG URL lowercases the hostname during parsing.
151
+ hostname = new URL(url).hostname;
152
+ } catch {
153
+ return false;
154
+ }
155
+ return (TUNNEL_PROVIDER_WEBSITE_HOSTS as readonly string[]).includes(
156
+ hostname,
157
+ );
158
+ }
159
+
160
+ /**
161
+ * The display name of the tunnel/ingress vendor a service-website URL points
162
+ * at (`"Tailscale"` / `"ngrok"` / `"Cloudflare"`), or null when the host is not
163
+ * a known vendor site. Drives the "This is <Name>'s website" pairing guidance.
164
+ */
165
+ export function tunnelProviderWebsiteName(url: string): string | null {
166
+ let hostname: string;
167
+ try {
168
+ hostname = new URL(url).hostname;
169
+ } catch {
170
+ return null;
171
+ }
172
+ if (
173
+ !(TUNNEL_PROVIDER_WEBSITE_HOSTS as readonly string[]).includes(hostname)
174
+ ) {
175
+ return null;
176
+ }
177
+ if (hostname.includes("tailscale")) return "Tailscale";
178
+ if (hostname.includes("ngrok")) return "ngrok";
179
+ if (hostname.includes("cloudflare")) return "Cloudflare";
180
+ return null;
181
+ }
182
+
118
183
  /**
119
184
  * A loopback URL — `localhost`, `[::1]`, or `127.x.x.x`. A pairing link that
120
185
  * encodes a loopback address is unreachable from the scanning device.
@@ -167,6 +232,9 @@ export function resolvePublicBaseUrl(raw: string): PublicBaseUrlResult {
167
232
  if (isLoopbackPublicUrl(normalized)) {
168
233
  return { ok: false, reason: "loopback" };
169
234
  }
235
+ if (isTunnelProviderWebsiteUrl(normalized)) {
236
+ return { ok: false, reason: "service-website" };
237
+ }
170
238
  if (new URL(normalized).protocol !== "https:") {
171
239
  return { ok: false, reason: "non-https" };
172
240
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vellumai/credential-executor",
3
- "version": "0.10.12-staging.1",
3
+ "version": "0.10.12-staging.2",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {