mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-09 16:14:31 +00:00
fix(security): reject ambiguous webhook target matches
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import type { AddressInfo } from "node:net";
|
||||
import type { OpenClawConfig, PluginRuntime } from "openclaw/plugin-sdk";
|
||||
import { createServer } from "node:http";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import type { ResolvedZaloAccount } from "./types.js";
|
||||
import { handleZaloWebhookRequest, registerZaloWebhookTarget } from "./monitor.js";
|
||||
|
||||
@@ -70,4 +70,68 @@ describe("handleZaloWebhookRequest", () => {
|
||||
unregister();
|
||||
}
|
||||
});
|
||||
|
||||
it("rejects ambiguous routing when multiple targets match the same secret", async () => {
|
||||
const core = {} as PluginRuntime;
|
||||
const account: ResolvedZaloAccount = {
|
||||
accountId: "default",
|
||||
enabled: true,
|
||||
token: "tok",
|
||||
tokenSource: "config",
|
||||
config: {},
|
||||
};
|
||||
const sinkA = vi.fn();
|
||||
const sinkB = vi.fn();
|
||||
const unregisterA = registerZaloWebhookTarget({
|
||||
token: "tok",
|
||||
account,
|
||||
config: {} as OpenClawConfig,
|
||||
runtime: {},
|
||||
core,
|
||||
secret: "secret",
|
||||
path: "/hook",
|
||||
mediaMaxMb: 5,
|
||||
statusSink: sinkA,
|
||||
});
|
||||
const unregisterB = registerZaloWebhookTarget({
|
||||
token: "tok",
|
||||
account,
|
||||
config: {} as OpenClawConfig,
|
||||
runtime: {},
|
||||
core,
|
||||
secret: "secret",
|
||||
path: "/hook",
|
||||
mediaMaxMb: 5,
|
||||
statusSink: sinkB,
|
||||
});
|
||||
|
||||
try {
|
||||
await withServer(
|
||||
async (req, res) => {
|
||||
const handled = await handleZaloWebhookRequest(req, res);
|
||||
if (!handled) {
|
||||
res.statusCode = 404;
|
||||
res.end("not found");
|
||||
}
|
||||
},
|
||||
async (baseUrl) => {
|
||||
const response = await fetch(`${baseUrl}/hook`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"x-bot-api-secret-token": "secret",
|
||||
"content-type": "application/json",
|
||||
},
|
||||
body: "{}",
|
||||
});
|
||||
|
||||
expect(response.status).toBe(401);
|
||||
expect(sinkA).not.toHaveBeenCalled();
|
||||
expect(sinkB).not.toHaveBeenCalled();
|
||||
},
|
||||
);
|
||||
} finally {
|
||||
unregisterA();
|
||||
unregisterB();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user