webcake-landing-mcp 1.5.7 → 1.5.8
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/dist/auth/oauth-server.js +22 -1
- package/dist/changelog.json +7 -7
- package/dist/smoke.js +4 -0
- package/package.json +1 -1
|
@@ -263,6 +263,27 @@ export async function getClient(clientId) {
|
|
|
263
263
|
return undefined;
|
|
264
264
|
return (await getStore()).getClient(clientId);
|
|
265
265
|
}
|
|
266
|
+
const LOOPBACK_HOSTS = new Set(["localhost", "127.0.0.1", "[::1]"]);
|
|
267
|
+
/**
|
|
268
|
+
* Exact match, except an http loopback redirect ignores the port (RFC 8252 §7.3):
|
|
269
|
+
* native clients like Claude Code register `http://localhost/callback` and then
|
|
270
|
+
* redirect to an ephemeral port per session (`http://localhost:3118/callback`).
|
|
271
|
+
*/
|
|
272
|
+
export function redirectMatches(registered, requested) {
|
|
273
|
+
if (registered === requested)
|
|
274
|
+
return true;
|
|
275
|
+
let a, b;
|
|
276
|
+
try {
|
|
277
|
+
a = new URL(registered);
|
|
278
|
+
b = new URL(requested);
|
|
279
|
+
}
|
|
280
|
+
catch {
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
return (a.protocol === "http:" && b.protocol === "http:" &&
|
|
284
|
+
LOOPBACK_HOSTS.has(a.hostname) && a.hostname === b.hostname &&
|
|
285
|
+
a.pathname === b.pathname && a.search === b.search);
|
|
286
|
+
}
|
|
266
287
|
/**
|
|
267
288
|
* Validate an /authorize request and park it. Returns an `internalState` to send
|
|
268
289
|
* to the login page as its `state`; the callback uses it to find this request.
|
|
@@ -275,7 +296,7 @@ export async function startAuthorize(p) {
|
|
|
275
296
|
if (!client) {
|
|
276
297
|
return { ok: false, error: "invalid_client", error_description: "Unknown client_id. Register first via /register.", redirectable: false };
|
|
277
298
|
}
|
|
278
|
-
if (!p.redirect_uri || !client.redirect_uris.
|
|
299
|
+
if (!p.redirect_uri || !client.redirect_uris.some((r) => redirectMatches(r, p.redirect_uri))) {
|
|
279
300
|
return { ok: false, error: "invalid_request", error_description: "redirect_uri does not match a registered URI.", redirectable: false };
|
|
280
301
|
}
|
|
281
302
|
// From here errors CAN go back to the client's redirect_uri.
|
package/dist/changelog.json
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"v": "1.5.8",
|
|
4
|
+
"d": "13/10/2026",
|
|
5
|
+
"type": "Fixed",
|
|
6
|
+
"en": "The OAuth authorize endpoint now accepts http://localhost/127.0.0.1/[::1] redirect URIs on any port as long as the scheme, host, path, and query…",
|
|
7
|
+
"vi": "Endpoint OAuth authorize nay chấp nhận redirect URI http://localhost/127.0.0.1/[::1] ở bất kỳ port nào miễn là scheme, host, path, và query khớp với…"
|
|
8
|
+
},
|
|
2
9
|
{
|
|
3
10
|
"v": "1.5.7",
|
|
4
11
|
"d": "13/10/2026",
|
|
@@ -33,12 +40,5 @@
|
|
|
33
40
|
"type": "Added",
|
|
34
41
|
"en": "validate_page now detects inline base64 images (data:image/…;base64,… URIs) anywhere in an element's specials, a styles background, gallery…",
|
|
35
42
|
"vi": "validate_page nay phát hiện ảnh base64 nhúng (URI data:image/…;base64,…) ở bất kỳ đâu trong specials của phần tử, nền styles, gallery item.link,…"
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
"v": "1.5.2",
|
|
39
|
-
"d": "25/08/2026",
|
|
40
|
-
"type": "Fixed",
|
|
41
|
-
"en": "Colors written in any CSS notation other than the legacy rgba(r,g,b,a) form (hex, rgb(), hsl(), CSS named colors, and the modern space/slash rgba()…",
|
|
42
|
-
"vi": "Các giá trị màu được viết ở bất kỳ dạng CSS nào khác ngoài dạng rgba(r,g,b,a) kiểu cũ (hex, rgb(), hsl(), tên màu CSS, và cú pháp rgba() mới dùng…"
|
|
43
43
|
}
|
|
44
44
|
]
|
package/dist/smoke.js
CHANGED
|
@@ -18,6 +18,7 @@ import { toEditorUrl, toEditorLoginUrl, toPreviewUrl, buildPublishRequestRedacte
|
|
|
18
18
|
import { normalizePhoto, resolvePexelsKey, pexelsKeyFromHeaders, resolvePexelsProxyBase, buildSearchQuery, PEXELS_PROXY_DEFAULT, variantPixels, annotateVariantSizes } from "./persistence/pexels-client.js";
|
|
19
19
|
import { putDraft, getDraft, updateDraft, deleteDraft } from "./persistence/draft-cache.js";
|
|
20
20
|
import { buildConnectUrl, parseCallback } from "./auth/login.js";
|
|
21
|
+
import { redirectMatches } from "./auth/oauth-server.js";
|
|
21
22
|
import { isLocalPath, resolveLocalPath, sniffMime, localContentType } from "./tools/media.js";
|
|
22
23
|
import { buildMicrolinkUrl } from "./persistence/screenshot-client.js";
|
|
23
24
|
import { isPrivateHost, isAllowedScreenshotUrl } from "./persistence/screenshot-playwright.js";
|
|
@@ -122,6 +123,9 @@ const good = {
|
|
|
122
123
|
};
|
|
123
124
|
const r1 = validatePage(good);
|
|
124
125
|
check("good page valid", r1.valid, r1.errors);
|
|
126
|
+
check("oauth redirect: exact claude.ai match", redirectMatches("https://claude.ai/api/mcp/auth_callback", "https://claude.ai/api/mcp/auth_callback"));
|
|
127
|
+
check("oauth redirect: loopback any port (Claude Code)", redirectMatches("http://localhost/callback", "http://localhost:3118/callback") && redirectMatches("http://127.0.0.1/callback", "http://127.0.0.1:51234/callback"));
|
|
128
|
+
check("oauth redirect: rejects other path/host/https port drift", !redirectMatches("http://localhost/callback", "http://localhost:3118/evil") && !redirectMatches("http://localhost/callback", "http://127.0.0.1:3118/callback") && !redirectMatches("https://claude.ai/api/mcp/auth_callback", "https://claude.ai:8443/api/mcp/auth_callback") && !redirectMatches("http://evil.com/callback", "http://evil.com:1/callback"));
|
|
125
129
|
check("good page has no dangling-target warnings", r1.warnings.length === 0, r1.warnings);
|
|
126
130
|
check("good page stats", r1.stats.sections === 2 && r1.stats.ids === 3, r1.stats);
|
|
127
131
|
console.log("== validate: catches problems ==");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "webcake-landing-mcp",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.8",
|
|
4
4
|
"description": "MCP server exposing Webcake landing-page element schemas + AI usage hints, and persisting LLM-generated page sources to a Webcake backend.",
|
|
5
5
|
"mcpName": "io.github.vuluu2k/webcake-landing-mcp",
|
|
6
6
|
"type": "module",
|