fix(sessions): guard withSessionStoreLock against undefined storePath (#14717) (openclaw#14755) thanks @lailoo

Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: lailoo <20536249+lailoo@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
This commit is contained in:
大猫子
2026-02-15 21:57:51 +08:00
committed by GitHub
parent 3d0e568007
commit 0931a35709
3 changed files with 29 additions and 0 deletions

View File

@@ -299,6 +299,7 @@ Docs: https://docs.openclaw.ai
### Fixes
- Gateway/OpenResponses: harden URL-based `input_file`/`input_image` handling with explicit SSRF deny policy, hostname allowlists (`files.urlAllowlist` / `images.urlAllowlist`), per-request URL input caps (`maxUrlParts`), blocked-fetch audit logging, and regression coverage/docs updates.
- Sessions: guard `withSessionStoreLock` against undefined `storePath` to prevent `path.dirname` crash. (#14717)
- Security: fix unauthenticated Nostr profile API remote config tampering. (#13719) Thanks @coygeek.
- Security: remove bundled soul-evil hook. (#14757) Thanks @Imccccc.
- Security/Audit: add hook session-routing hardening checks (`hooks.defaultSessionKey`, `hooks.allowRequestSessionKey`, and prefix allowlists), and warn when HTTP API endpoints allow explicit session-key routing.

View File

@@ -714,6 +714,11 @@ async function withSessionStoreLock<T>(
fn: () => Promise<T>,
opts: SessionStoreLockOptions = {},
): Promise<T> {
if (!storePath || typeof storePath !== "string") {
throw new Error(
`withSessionStoreLock: storePath must be a non-empty string, got ${JSON.stringify(storePath)}`,
);
}
const timeoutMs = opts.timeoutMs ?? 10_000;
const staleMs = opts.staleMs ?? 30_000;
// `pollIntervalMs` is retained for API compatibility with older lock options.

View File

@@ -0,0 +1,23 @@
/**
* Regression test for #14717: path.dirname(undefined) crash in withSessionStoreLock
*
* When a channel plugin passes undefined as storePath to recordSessionMetaFromInbound,
* the call chain reaches withSessionStoreLock → path.dirname(undefined) → TypeError crash.
* After fix, a clear Error is thrown instead of an unhandled TypeError.
*/
import { describe, expect, it } from "vitest";
import { updateSessionStore } from "./store.js";
describe("withSessionStoreLock storePath guard (#14717)", () => {
it("throws descriptive error when storePath is undefined", async () => {
await expect(
updateSessionStore(undefined as unknown as string, (store) => store),
).rejects.toThrow("withSessionStoreLock: storePath must be a non-empty string");
});
it("throws descriptive error when storePath is empty string", async () => {
await expect(updateSessionStore("", (store) => store)).rejects.toThrow(
"withSessionStoreLock: storePath must be a non-empty string",
);
});
});