diff --git a/src/membrane/audit-trail.js b/src/membrane/audit-trail.js index c5cce2b9..0534c267 100644 --- a/src/membrane/audit-trail.js +++ b/src/membrane/audit-trail.js @@ -98,8 +98,8 @@ function persist(entry) { const filePath = path.join(AUDIT_DIR, `${dateStr}.jsonl`); fs.appendFileSync(filePath, JSON.stringify(entry) + '\n', 'utf8'); } catch (err) { - // 审计系统自身不能阻塞请求流,静默记录错误 - console.error('[AUDIT] persist error:', err.message); + // 审计系统自身不能阻塞请求流,记录到 stderr + process.stderr.write(`[AUDIT] persist error: ${err.message}\n`); } } diff --git a/src/membrane/bingshuo-module.js b/src/membrane/bingshuo-module.js index d6a01ced..50eb1db1 100644 --- a/src/membrane/bingshuo-module.js +++ b/src/membrane/bingshuo-module.js @@ -100,6 +100,16 @@ function verify(params) { .update(payload) .digest('hex'); + // 长度检查(防止 timingSafeEqual 抛异常) + if (signature.length !== expectedSig.length) { + recordImpersonation('invalid-signature-length'); + return { + verified: false, + reason: 'signature-mismatch', + state: bingshuoModule.state, + }; + } + if (!crypto.timingSafeEqual( Buffer.from(signature, 'hex'), Buffer.from(expectedSig, 'hex') diff --git a/src/membrane/gateway.js b/src/membrane/gateway.js index 91c1abd5..a2722463 100644 --- a/src/membrane/gateway.js +++ b/src/membrane/gateway.js @@ -48,10 +48,14 @@ function createGateway(options) { const extraPaths = opts.passthroughPaths || []; const allPassthrough = PASSTHROUGH_PATHS.concat(extraPaths); - // 定期清理过期权限(每60秒) - setInterval(() => { - permissionEngine.cleanup(); - }, 60 * 1000); + // 定期清理过期权限(每60秒)· 单例模式防止重复 + if (!createGateway._cleanupStarted) { + createGateway._cleanupStarted = true; + const interval = setInterval(() => { + permissionEngine.cleanup(); + }, 60 * 1000); + interval.unref(); + } return function languageMembrane(req, res, next) { const startTime = Date.now(); diff --git a/src/membrane/module-protocol/module-registry.js b/src/membrane/module-protocol/module-registry.js index 060c49b9..013bc155 100644 --- a/src/membrane/module-protocol/module-registry.js +++ b/src/membrane/module-protocol/module-registry.js @@ -49,7 +49,8 @@ function loadRegistry() { try { return JSON.parse(fs.readFileSync(REGISTRY_PATH, 'utf8')); - } catch (_) { + } catch (err) { + process.stderr.write(`[MODULE-REGISTRY] parse error: ${err.message}\n`); return { modules: [], updated_at: new Date().toISOString() }; } } diff --git a/src/membrane/persona-room/room-manager.js b/src/membrane/persona-room/room-manager.js index 1ac0b588..90421015 100644 --- a/src/membrane/persona-room/room-manager.js +++ b/src/membrane/persona-room/room-manager.js @@ -111,8 +111,8 @@ function queryExperience(personaId, category, limit) { try { const data = JSON.parse(fs.readFileSync(path.join(catDir, file), 'utf8')); results.push(data); - } catch (_) { - // skip corrupt files + } catch (err) { + process.stderr.write(`[ROOM] corrupt file skipped: ${file} (${err.message})\n`); } }