Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a3ab898e04 | |||
| dea67c0d86 | |||
| d13a2c237c | |||
| c592f0aa69 | |||
| 85a2472e4e | |||
| 0cb3256b2d | |||
| 44029862b1 |
@@ -10,7 +10,7 @@
|
||||
"plugins": [
|
||||
{
|
||||
"name": "claude-mem",
|
||||
"version": "7.3.7",
|
||||
"version": "7.3.9",
|
||||
"source": "./plugin",
|
||||
"description": "Persistent memory system for Claude Code - context compression across sessions"
|
||||
}
|
||||
|
||||
@@ -4,6 +4,49 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
|
||||
## [7.3.8] - 2025-12-18
|
||||
|
||||
## Security Fix
|
||||
|
||||
Added localhost-only protection for admin endpoints to prevent DoS attacks when worker service is bound to 0.0.0.0 for remote UI access.
|
||||
|
||||
### Changes
|
||||
- Created `requireLocalhost` middleware to restrict admin endpoints
|
||||
- Applied to `/api/admin/restart` and `/api/admin/shutdown`
|
||||
- Returns 403 Forbidden for non-localhost requests
|
||||
|
||||
### Security Impact
|
||||
Prevents unauthorized shutdown/restart of worker service when exposed on network.
|
||||
|
||||
Fixes security concern raised in #368.
|
||||
|
||||
## [7.3.7] - 2025-12-17
|
||||
|
||||
## Windows Platform Stabilization
|
||||
|
||||
This patch release includes comprehensive improvements for Windows platform stability and reliability.
|
||||
|
||||
### Key Improvements
|
||||
|
||||
- **Worker Readiness Tracking**: Added `/api/readiness` endpoint with MCP/SDK initialization flags to prevent premature connection attempts
|
||||
- **Process Tree Cleanup**: Implemented recursive process enumeration on Windows to prevent zombie socket processes
|
||||
- **Bun Runtime Migration**: Migrated worker wrapper from Node.js to Bun for consistency and reliability
|
||||
- **Centralized Project Name Utility**: Consolidated duplicate project name extraction logic with Windows drive root handling
|
||||
- **Enhanced Error Messages**: Added platform-aware logging and detailed Windows troubleshooting guidance
|
||||
- **Subprocess Console Hiding**: Standardized `windowsHide: true` across all child process spawns to prevent console window flashing
|
||||
|
||||
### Technical Details
|
||||
|
||||
- Worker service tracks MCP and SDK readiness states separately
|
||||
- ChromaSync service properly tracks subprocess PIDs for Windows cleanup
|
||||
- Worker wrapper uses Bun runtime with enhanced socket cleanup via process tree enumeration
|
||||
- Increased timeouts on Windows platform (30s worker startup, 10s hook timeouts)
|
||||
- Logger utility includes platform and PID information for better debugging
|
||||
|
||||
This represents a major reliability improvement for Windows users, eliminating common issues with worker startup failures, orphaned processes, and zombie sockets.
|
||||
|
||||
**Full Changelog**: https://github.com/thedotmack/claude-mem/compare/v7.3.6...v7.3.7
|
||||
|
||||
## [7.3.6] - 2025-12-17
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "claude-mem",
|
||||
"version": "7.3.7",
|
||||
"version": "7.3.9",
|
||||
"description": "Memory compression system for Claude Code - persist context across sessions",
|
||||
"keywords": [
|
||||
"claude",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "claude-mem",
|
||||
"version": "7.3.7",
|
||||
"version": "7.3.9",
|
||||
"description": "Persistent memory system for Claude Code - seamlessly preserve context across sessions",
|
||||
"author": {
|
||||
"name": "Alex Newman"
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "claude-mem-plugin",
|
||||
"version": "7.3.7",
|
||||
"version": "7.3.8",
|
||||
"private": true,
|
||||
"description": "Runtime dependencies for claude-mem bundled hooks",
|
||||
"type": "module",
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -166,7 +166,7 @@ async function buildHooks() {
|
||||
'__DEFAULT_PACKAGE_VERSION__': `"${version}"`
|
||||
},
|
||||
banner: {
|
||||
js: '#!/usr/bin/env bun'
|
||||
js: '#!/usr/bin/env node'
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ import { TimelineService } from './worker/TimelineService.js';
|
||||
import { SessionEventBroadcaster } from './worker/events/SessionEventBroadcaster.js';
|
||||
|
||||
// Import HTTP layer
|
||||
import { createMiddleware, summarizeRequestBody as summarizeBody } from './worker/http/middleware.js';
|
||||
import { createMiddleware, summarizeRequestBody as summarizeBody, requireLocalhost } from './worker/http/middleware.js';
|
||||
import { ViewerRoutes } from './worker/http/routes/ViewerRoutes.js';
|
||||
import { SessionRoutes } from './worker/http/routes/SessionRoutes.js';
|
||||
import { DataRoutes } from './worker/http/routes/DataRoutes.js';
|
||||
@@ -208,8 +208,8 @@ export class WorkerService {
|
||||
}
|
||||
});
|
||||
|
||||
// Admin endpoints for process management
|
||||
this.app.post('/api/admin/restart', async (_req, res) => {
|
||||
// Admin endpoints for process management (localhost-only)
|
||||
this.app.post('/api/admin/restart', requireLocalhost, async (_req, res) => {
|
||||
res.json({ status: 'restarting' });
|
||||
|
||||
// On Windows, if managed by wrapper, send message to parent to handle restart
|
||||
@@ -230,7 +230,7 @@ export class WorkerService {
|
||||
}
|
||||
});
|
||||
|
||||
this.app.post('/api/admin/shutdown', async (_req, res) => {
|
||||
this.app.post('/api/admin/shutdown', requireLocalhost, async (_req, res) => {
|
||||
res.json({ status: 'shutting_down' });
|
||||
|
||||
// On Windows, if managed by wrapper, send message to parent to handle shutdown
|
||||
|
||||
@@ -60,6 +60,34 @@ export function createMiddleware(
|
||||
return middlewares;
|
||||
}
|
||||
|
||||
/**
|
||||
* Middleware to require localhost-only access
|
||||
* Used for admin endpoints that should not be exposed when binding to 0.0.0.0
|
||||
*/
|
||||
export function requireLocalhost(req: Request, res: Response, next: NextFunction): void {
|
||||
const clientIp = req.ip || req.connection.remoteAddress || '';
|
||||
const isLocalhost =
|
||||
clientIp === '127.0.0.1' ||
|
||||
clientIp === '::1' ||
|
||||
clientIp === '::ffff:127.0.0.1' ||
|
||||
clientIp === 'localhost';
|
||||
|
||||
if (!isLocalhost) {
|
||||
logger.warn('SECURITY', 'Admin endpoint access denied - not localhost', {
|
||||
endpoint: req.path,
|
||||
clientIp,
|
||||
method: req.method
|
||||
});
|
||||
res.status(403).json({
|
||||
error: 'Forbidden',
|
||||
message: 'Admin endpoints are only accessible from localhost'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
|
||||
/**
|
||||
* Summarize request body for logging
|
||||
* Used to avoid logging sensitive data or large payloads
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
import express, { Request, Response } from 'express';
|
||||
import path from 'path';
|
||||
import { readFileSync } from 'fs';
|
||||
import { readFileSync, existsSync } from 'fs';
|
||||
import { getPackageRoot } from '../../../../shared/paths.js';
|
||||
import { SSEBroadcaster } from '../../SSEBroadcaster.js';
|
||||
import { DatabaseManager } from '../../DatabaseManager.js';
|
||||
@@ -41,7 +41,19 @@ export class ViewerRoutes extends BaseRouteHandler {
|
||||
*/
|
||||
private handleViewerUI = this.wrapHandler((req: Request, res: Response): void => {
|
||||
const packageRoot = getPackageRoot();
|
||||
const viewerPath = path.join(packageRoot, 'plugin', 'ui', 'viewer.html');
|
||||
|
||||
// Try cache structure first (ui/viewer.html), then marketplace structure (plugin/ui/viewer.html)
|
||||
const viewerPaths = [
|
||||
path.join(packageRoot, 'ui', 'viewer.html'),
|
||||
path.join(packageRoot, 'plugin', 'ui', 'viewer.html')
|
||||
];
|
||||
|
||||
const viewerPath = viewerPaths.find(p => existsSync(p));
|
||||
|
||||
if (!viewerPath) {
|
||||
throw new Error('Viewer UI not found at any expected location');
|
||||
}
|
||||
|
||||
const html = readFileSync(viewerPath, 'utf-8');
|
||||
res.setHeader('Content-Type', 'text/html');
|
||||
res.send(html);
|
||||
|
||||
Reference in New Issue
Block a user