mirror of
https://github.com/modelcontextprotocol/servers.git
synced 2026-02-19 11:54:58 -05:00
fix(memory): implement atomic writes to prevent race condition
Fixes race condition vulnerability where concurrent operations could corrupt memory.json file by writing incomplete or malformed data. Changes: - Add atomic write operations using temporary files and rename - Import crypto.randomBytes for generating unique temp file names - Add proper error handling and cleanup for temp files - Use same pattern as filesystem server for consistency This resolves JSON parsing errors like 'Unexpected non-whitespace character after JSON' that occurred when multiple processes attempted simultaneous file writes. Fixes #2579 Co-authored-by: Ola Hungerford <olaservo@users.noreply.github.com>
This commit is contained in:
@@ -9,6 +9,7 @@ import {
|
||||
import { promises as fs } from 'fs';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { randomBytes } from 'crypto';
|
||||
|
||||
// Define memory file path using environment variable with fallback
|
||||
const defaultMemoryPath = path.join(path.dirname(fileURLToPath(import.meta.url)), 'memory.json');
|
||||
@@ -63,7 +64,22 @@ class KnowledgeGraphManager {
|
||||
...graph.entities.map(e => JSON.stringify({ type: "entity", ...e })),
|
||||
...graph.relations.map(r => JSON.stringify({ type: "relation", ...r })),
|
||||
];
|
||||
await fs.writeFile(MEMORY_FILE_PATH, lines.join("\n"));
|
||||
|
||||
// Use atomic rename to prevent race conditions where concurrent writes
|
||||
// could corrupt the file. Rename operations are atomic on all filesystems.
|
||||
const tempPath = `${MEMORY_FILE_PATH}.${randomBytes(16).toString('hex')}.tmp`;
|
||||
try {
|
||||
await fs.writeFile(tempPath, lines.join("\n"), 'utf-8');
|
||||
await fs.rename(tempPath, MEMORY_FILE_PATH);
|
||||
} catch (error) {
|
||||
// Clean up temp file on failure
|
||||
try {
|
||||
await fs.unlink(tempPath);
|
||||
} catch (unlinkError) {
|
||||
// Ignore unlink errors - temp file might not exist or already cleaned up
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async createEntities(entities: Entity[]): Promise<Entity[]> {
|
||||
|
||||
Reference in New Issue
Block a user