mirror of
https://github.com/openclaw/openclaw.git
synced 2026-02-08 21:09:23 +08:00
fix: silence unused hook token url param (#9436)
* fix: Gateway authentication token exposed in URL query parameters * fix: silence unused hook token url param * fix: remove gateway auth tokens from URLs (#9436) (thanks @coygeek) * test: fix Windows path separators in audit test (#9436) --------- Co-authored-by: George Pickett <gpickett00@gmail.com>
This commit is contained in:
@@ -112,19 +112,11 @@ export function applySettingsFromUrl(host: SettingsHost) {
|
||||
let shouldCleanUrl = false;
|
||||
|
||||
if (tokenRaw != null) {
|
||||
const token = tokenRaw.trim();
|
||||
if (token && token !== host.settings.token) {
|
||||
applySettings(host, { ...host.settings, token });
|
||||
}
|
||||
params.delete("token");
|
||||
shouldCleanUrl = true;
|
||||
}
|
||||
|
||||
if (passwordRaw != null) {
|
||||
const password = passwordRaw.trim();
|
||||
if (password) {
|
||||
(host as unknown as { password: string }).password = password;
|
||||
}
|
||||
params.delete("password");
|
||||
shouldCleanUrl = true;
|
||||
}
|
||||
|
||||
@@ -151,25 +151,25 @@ describe("control UI routing", () => {
|
||||
expect(container.scrollTop).toBe(maxScroll);
|
||||
});
|
||||
|
||||
it("hydrates token from URL params and strips it", async () => {
|
||||
it("strips token URL params without importing them", async () => {
|
||||
const app = mountApp("/ui/overview?token=abc123");
|
||||
await app.updateComplete;
|
||||
|
||||
expect(app.settings.token).toBe("abc123");
|
||||
expect(app.settings.token).toBe("");
|
||||
expect(window.location.pathname).toBe("/ui/overview");
|
||||
expect(window.location.search).toBe("");
|
||||
});
|
||||
|
||||
it("hydrates password from URL params and strips it", async () => {
|
||||
it("strips password URL params without importing them", async () => {
|
||||
const app = mountApp("/ui/overview?password=sekret");
|
||||
await app.updateComplete;
|
||||
|
||||
expect(app.password).toBe("sekret");
|
||||
expect(app.password).toBe("");
|
||||
expect(window.location.pathname).toBe("/ui/overview");
|
||||
expect(window.location.search).toBe("");
|
||||
});
|
||||
|
||||
it("hydrates token from URL params even when settings already set", async () => {
|
||||
it("does not override stored settings from URL token params", async () => {
|
||||
localStorage.setItem(
|
||||
"openclaw.control.settings.v1",
|
||||
JSON.stringify({ token: "existing-token" }),
|
||||
@@ -177,7 +177,7 @@ describe("control UI routing", () => {
|
||||
const app = mountApp("/ui/overview?token=abc123");
|
||||
await app.updateComplete;
|
||||
|
||||
expect(app.settings.token).toBe("abc123");
|
||||
expect(app.settings.token).toBe("existing-token");
|
||||
expect(window.location.pathname).toBe("/ui/overview");
|
||||
expect(window.location.search).toBe("");
|
||||
});
|
||||
|
||||
@@ -26,23 +26,23 @@ describe("iconForTab", () => {
|
||||
});
|
||||
|
||||
it("returns stable icons for known tabs", () => {
|
||||
expect(iconForTab("chat")).toBe("💬");
|
||||
expect(iconForTab("overview")).toBe("📊");
|
||||
expect(iconForTab("channels")).toBe("🔗");
|
||||
expect(iconForTab("instances")).toBe("📡");
|
||||
expect(iconForTab("sessions")).toBe("📄");
|
||||
expect(iconForTab("cron")).toBe("⏰");
|
||||
expect(iconForTab("skills")).toBe("⚡️");
|
||||
expect(iconForTab("nodes")).toBe("🖥️");
|
||||
expect(iconForTab("config")).toBe("⚙️");
|
||||
expect(iconForTab("debug")).toBe("🐞");
|
||||
expect(iconForTab("logs")).toBe("🧾");
|
||||
expect(iconForTab("chat")).toBe("messageSquare");
|
||||
expect(iconForTab("overview")).toBe("barChart");
|
||||
expect(iconForTab("channels")).toBe("link");
|
||||
expect(iconForTab("instances")).toBe("radio");
|
||||
expect(iconForTab("sessions")).toBe("fileText");
|
||||
expect(iconForTab("cron")).toBe("loader");
|
||||
expect(iconForTab("skills")).toBe("zap");
|
||||
expect(iconForTab("nodes")).toBe("monitor");
|
||||
expect(iconForTab("config")).toBe("settings");
|
||||
expect(iconForTab("debug")).toBe("bug");
|
||||
expect(iconForTab("logs")).toBe("scrollText");
|
||||
});
|
||||
|
||||
it("returns a fallback icon for unknown tab", () => {
|
||||
// TypeScript won't allow this normally, but runtime could receive unexpected values
|
||||
const unknownTab = "unknown" as Tab;
|
||||
expect(iconForTab(unknownTab)).toBe("📁");
|
||||
expect(iconForTab(unknownTab)).toBe("folder");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ export function renderOverview(props: OverviewProps) {
|
||||
<div class="muted" style="margin-top: 8px">
|
||||
This gateway requires auth. Add a token or password, then click Connect.
|
||||
<div style="margin-top: 6px">
|
||||
<span class="mono">openclaw dashboard --no-open</span> → tokenized URL<br />
|
||||
<span class="mono">openclaw dashboard --no-open</span> → open the Control UI<br />
|
||||
<span class="mono">openclaw doctor --generate-gateway-token</span> → set token
|
||||
</div>
|
||||
<div style="margin-top: 6px">
|
||||
@@ -62,8 +62,7 @@ export function renderOverview(props: OverviewProps) {
|
||||
}
|
||||
return html`
|
||||
<div class="muted" style="margin-top: 8px">
|
||||
Auth failed. Re-copy a tokenized URL with
|
||||
<span class="mono">openclaw dashboard --no-open</span>, or update the token, then click Connect.
|
||||
Auth failed. Update the token or password in Control UI settings, then click Connect.
|
||||
<div style="margin-top: 6px">
|
||||
<a
|
||||
class="session-link"
|
||||
|
||||
Reference in New Issue
Block a user