TencentCloud/TencentDB-Agent-Memory · error
Storage key must be relative, got absolute: ${key}
Error message
Storage key must be relative, got absolute: ${key} What it means
LocalStorageBackend.resolvePath() maps storage object keys to file paths under a configured rootDir. As part of a path-traversal security fix (CR-6), it rejects any key that starts with '/' or '\' because such keys are absolute paths and could target arbitrary filesystem locations instead of staying inside rootDir. Keys must be relative path segments joined under the backend root.
Source
Thrown at MemoryCore/src/core/storage/local-backend.ts:69
* rootDir). Affects standalone mode where user-controllable fields like
* instanceId / sceneName / sessionKey end up in the key.
*
* Rejected:
* - Empty key
* - Keys containing NUL (\0) — POSIX/Linux path terminator, can confuse
* downstream tooling (sqlite, file managers).
* - Keys with leading "/" or "\" (absolute paths).
* - Keys whose resolved path falls outside rootDir (../ traversal).
*/
private resolvePath(key: string): string {
if (!key || typeof key !== "string") {
throw new Error(`Invalid storage key: ${JSON.stringify(key)}`);
}
if (key.includes("\0")) {
throw new Error("Storage key must not contain NUL character");
}
if (key.startsWith("/") || key.startsWith("\\")) {
throw new Error(`Storage key must be relative, got absolute: ${key}`);
}
// Normalize key separators to OS path separators
const normalized = key.split("/").join(sep);
// Compute the absolute resolved path; resolve() collapses ".." segments.
const absRoot = resolve(this.rootDir);
const absResolved = resolve(absRoot, normalized);
// Ensure the resolved path stays inside rootDir. Append sep so that
// a key like "../rootDir2/foo" (which resolves to a sibling directory
// whose name happens to start with rootDir's name) is also rejected.
const rootWithSep = absRoot.endsWith(sep) ? absRoot : absRoot + sep;
if (absResolved !== absRoot && !absResolved.startsWith(rootWithSep)) {
throw new Error(`Path traversal rejected: key "${key}" escapes rootDir`);
}
return absResolved;View on GitHub (pinned to 3efcd317b8)
Solutions
- Strip leading '/' or '\\' (and collapse duplicate separators) from the key before passing it to the backend.
- Fix the source of the key (config or user input) so it is stored as a relative path segment; validate at ingestion.
- If an absolute path is genuinely needed, configure the backend's rootDir to that location and use a relative key instead.
Example fix
// before
const key = `${sessionKey}/memory.json`; // sessionKey = "/data/instances/abc"
await storage.putObject(key, data);
// after
const relKey = sessionKey.replace(/^[\\/]+/, "");
const key = `${relKey}/memory.json`;
await storage.putObject(key, data); Defensive patterns
Strategy: validation
Validate before calling
function isSafeRelativeKey(key: string): boolean {
return typeof key === "string" && key.length > 0 && !key.startsWith("/") && !key.startsWith("\\") && !key.includes("\0");
}
if (!isSafeRelativeKey(key)) throw new Error(`key must be relative: ${key}`); Type guard
function isRelativeKey(key: unknown): key is string {
return typeof key === "string" && key.length > 0 && !key.startsWith("/") && !key.startsWith("\\");
} Try / catch
try {
await storage.putObject(key, data);
} catch (e) {
if (e instanceof Error && e.message.startsWith("Storage key must be relative")) {
key = key.replace(/^[\\/]+/, "");
await storage.putObject(key, data);
} else throw e;
} Prevention
- Always build keys from sanitized relative segments; strip leading slashes from user input at ingestion.
- Validate config fields like sessionKey/instanceId against /^[^\\/]/ before they reach storage keys.
- Add a unit test asserting keys beginning with '/' or '\\' are rejected.
When it happens
Trigger: Calling putObject/getObject/appendObject/list (any method that calls resolvePath) with a key that begins with '/' (POSIX absolute, e.g. '/etc/passwd') or '\\' (Windows absolute, e.g. '\\\\server\\share\\file'). Commonly produced by joining user-controlled fields like instanceId, sceneName or sessionKey that already contain a leading slash into the key template.
Common situations: A config value such as sessionKey or instanceId was set to an absolute path by mistake; code migrated from an API that accepted absolute paths; string concatenation like root + '/' + key where key already starts with '/'; on Windows, UNC paths ('\\\\server\\share') pasted into a config field.
Related errors
- Path traversal rejected in scoped storage key: ${key}
- Path traversal rejected: key "${key}" escapes rootDir
- Invalid generation log key
- invalid team_id for template path: ${teamId}
- Generation log object key exceeds COS limit
AI-assisted analysis of TencentCloud/TencentDB-Agent-Memory@3efcd317b8 (2026-09-01).
Data as JSON: /api/errors/1376fe8affc4cc09.
Report an issue: GitHub.