fix: address Cursor Bugbot review comments on PR #631
- Fix shell injection in writeShellExport: use single-quoted token with escaped embedded single quotes instead of double-quoted interpolation - Fix board scanner initial setTimeout not cleared on stop: store the timeout handle and clear it in the stop handler - Fix openclaw-probe test asserting deliver:true when code sends false - Fix Discord notifier thread_id test to check URL query param instead of body, and remove redundant thread_id from post() body payload
This commit is contained in:
parent
36d354e0c2
commit
3716fc751c
|
|
@ -848,6 +848,7 @@ export default function (api: any) {
|
|||
|
||||
let healthInterval: ReturnType<typeof setInterval> | null = null;
|
||||
let boardScanInterval: ReturnType<typeof setInterval> | null = null;
|
||||
let boardScanInitialTimeout: ReturnType<typeof setTimeout> | null = null;
|
||||
let lastKnownIssueIds: Set<number> = new Set();
|
||||
let isFirstBoardScan = true;
|
||||
|
||||
|
|
@ -922,10 +923,14 @@ export default function (api: any) {
|
|||
}
|
||||
};
|
||||
|
||||
setTimeout(scan, 10_000);
|
||||
boardScanInitialTimeout = setTimeout(scan, 10_000);
|
||||
boardScanInterval = setInterval(scan, scanMs);
|
||||
},
|
||||
stop: async () => {
|
||||
if (boardScanInitialTimeout) {
|
||||
clearTimeout(boardScanInitialTimeout);
|
||||
boardScanInitialTimeout = null;
|
||||
}
|
||||
if (boardScanInterval) {
|
||||
clearInterval(boardScanInterval);
|
||||
boardScanInterval = null;
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ describe("openclaw-probe", () => {
|
|||
expect(body.name).toBe("AO");
|
||||
expect(body.sessionKey).toBe("hook:ao:setup-test");
|
||||
expect(body.wakeMode).toBe("now");
|
||||
expect(body.deliver).toBe(true);
|
||||
expect(body.deliver).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -321,7 +321,11 @@ function writeShellExport(token: string): string | undefined {
|
|||
const profileName = shell.endsWith("/zsh") ? ".zshrc" : ".bashrc";
|
||||
const profilePath = join(homedir(), profileName);
|
||||
|
||||
const exportLine = `export OPENCLAW_HOOKS_TOKEN="${token}"`;
|
||||
// Sanitize token: escape shell-special characters to prevent injection
|
||||
// when the profile is sourced. Single-quote the value and escape any
|
||||
// embedded single quotes (the only character that breaks '...' quoting).
|
||||
const safeToken = token.replace(/'/g, "'\\''");
|
||||
const exportLine = `export OPENCLAW_HOOKS_TOKEN='${safeToken}'`;
|
||||
|
||||
// Check if it already exists
|
||||
if (existsSync(profilePath)) {
|
||||
|
|
|
|||
|
|
@ -162,8 +162,9 @@ describe("notifier-discord", () => {
|
|||
});
|
||||
await notifier.notify(makeEvent());
|
||||
|
||||
const body = JSON.parse(fetchMock.mock.calls[0][1].body);
|
||||
expect(body.thread_id).toBe("1234567890");
|
||||
// Discord requires thread_id as a URL query param, not in the JSON body
|
||||
const calledUrl = fetchMock.mock.calls[0][0];
|
||||
expect(calledUrl).toBe("https://discord.com/api/webhooks/123/abc?thread_id=1234567890");
|
||||
});
|
||||
|
||||
it("is a no-op when webhookUrl not configured", async () => {
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ export function create(config?: Record<string, unknown>): Notifier {
|
|||
if (!webhookUrl) return null;
|
||||
const payload: Record<string, unknown> = { username, content: message };
|
||||
if (avatarUrl) payload.avatar_url = avatarUrl;
|
||||
if (threadId) payload.thread_id = threadId;
|
||||
// thread_id is already passed as a URL query param via effectiveUrl
|
||||
await postWithRetry(effectiveUrl!, payload, retries, retryDelayMs);
|
||||
return null;
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue