aegis-bridge 2.3.6 → 2.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/hooks.js CHANGED
@@ -14,6 +14,7 @@
14
14
  * Issue #169: Phase 1 — HTTP hooks infrastructure.
15
15
  * Issue #169: Phase 3 — Hook-driven status detection.
16
16
  */
17
+ import { isValidUUID } from './validation.js';
17
18
  /** CC hook events that require a decision response. */
18
19
  const DECISION_EVENTS = new Set(['PreToolUse', 'PermissionRequest']);
19
20
  /** Permission modes that should be auto-approved via hook response. */
@@ -105,6 +106,10 @@ export function registerHookRoutes(app, deps) {
105
106
  if (!sessionId) {
106
107
  return reply.status(400).send({ error: 'Missing session ID — provide X-Session-Id header or sessionId query param' });
107
108
  }
109
+ // Issue #580: Reject non-UUID session IDs before getSession lookup.
110
+ if (!isValidUUID(sessionId)) {
111
+ return reply.status(400).send({ error: 'Invalid session ID — must be a UUID' });
112
+ }
108
113
  const session = deps.sessions.getSession(sessionId);
109
114
  if (!session) {
110
115
  return reply.status(404).send({ error: `Session ${sessionId} not found` });
package/dist/server.js CHANGED
@@ -155,11 +155,15 @@ function setupAuth(authManager) {
155
155
  return;
156
156
  // Hook routes — exact match: /v1/hooks/{eventName} (alpha only, no path traversal)
157
157
  // Issue #394: Require valid X-Session-Id for known sessions instead of blanket bypass.
158
+ // Issue #580: Validate UUID format before getSession lookup.
158
159
  // CC hooks run from localhost and always include the session ID they were started with.
159
160
  const hookMatch = /^\/v1\/hooks\/[A-Za-z]+$/.exec(urlPath);
160
161
  if (hookMatch) {
161
162
  const hookSessionId = req.headers['x-session-id']
162
163
  || req.query?.sessionId;
164
+ if (hookSessionId && !isValidUUID(hookSessionId)) {
165
+ return reply.status(400).send({ error: 'Invalid session ID — must be a UUID' });
166
+ }
163
167
  if (hookSessionId && sessions.getSession(hookSessionId)) {
164
168
  return; // valid session — allow
165
169
  }
@@ -437,11 +441,10 @@ app.get('/v1/sessions', async (req) => {
437
441
  const total = all.length;
438
442
  const start = (page - 1) * limit;
439
443
  const items = all.slice(start, start + limit);
444
+ const totalPages = Math.ceil(total / limit);
440
445
  return {
441
446
  sessions: items,
442
- total,
443
- page,
444
- limit,
447
+ pagination: { page, limit, total, totalPages },
445
448
  };
446
449
  });
447
450
  // Backwards compat: /sessions (no prefix) returns raw array
@@ -182,8 +182,8 @@ export function registerWsTerminalRoute(app, sessions, tmux, auth) {
182
182
  await sessions.sendMessage(sessionId, msg.text);
183
183
  }
184
184
  else if (msg.type === 'resize') {
185
- const cols = clamp(msg.cols ?? 80, 1, 1000, 80);
186
- const rows = clamp(msg.rows ?? 24, 1, 1000, 24);
185
+ const cols = clamp(msg.cols ?? 80, 10, 500, 80);
186
+ const rows = clamp(msg.rows ?? 24, 5, 200, 24);
187
187
  await tmux.resizePane(session.windowId, cols, rows);
188
188
  }
189
189
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aegis-bridge",
3
- "version": "2.3.6",
3
+ "version": "2.3.7",
4
4
  "type": "module",
5
5
  "description": "Orchestrate Claude Code sessions via API. Create, brief, monitor, refine, ship.",
6
6
  "main": "dist/server.js",