@wrongstack/acp 0.299.0 → 0.301.0

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/agent.js CHANGED
@@ -1446,6 +1446,7 @@ var WsBridgeTransport = class {
1446
1446
  };
1447
1447
 
1448
1448
  // src/agent/wrongstack-acp-agent.ts
1449
+ import { timingSafeEqual } from "node:crypto";
1449
1450
  import { createServer } from "node:http";
1450
1451
  import { isIP } from "node:net";
1451
1452
  import { fileURLToPath } from "node:url";
@@ -1513,10 +1514,10 @@ var WrongStackACPServer = class {
1513
1514
  this.httpServer = createServer(async (req, res) => {
1514
1515
  if (authToken) {
1515
1516
  const url = new URL(requestPath(req.url), `http://${host}:${port}`);
1516
- const queryToken = url.searchParams.get("token");
1517
1517
  const bearerToken = headerValue(req.headers.authorization)?.replace(/^Bearer\s+/i, "");
1518
- const supplied = queryToken ?? bearerToken ?? "";
1519
- if (supplied !== authToken) {
1518
+ const queryToken = url.searchParams.get("token");
1519
+ const queryOk = queryToken !== null && isLoopbackPeer(req) && timingSafeTokenEqual(queryToken, authToken);
1520
+ if (!queryOk && !timingSafeTokenEqual(bearerToken ?? "", authToken)) {
1520
1521
  res.writeHead(401, { "Content-Type": "application/json" });
1521
1522
  res.end(JSON.stringify({ error: { code: -32001, message: "Unauthorized" } }));
1522
1523
  return;
@@ -1630,6 +1631,17 @@ var WrongStackACPServer = class {
1630
1631
  var defaultEchoRunTurn = async (_input, _emit) => {
1631
1632
  return { stopReason: "end_turn" };
1632
1633
  };
1634
+ function timingSafeTokenEqual(supplied, expected) {
1635
+ if (!supplied || !expected) return false;
1636
+ const a = Buffer.from(supplied);
1637
+ const b = Buffer.from(expected);
1638
+ if (a.length !== b.length) return false;
1639
+ return timingSafeEqual(a, b);
1640
+ }
1641
+ function isLoopbackPeer(req) {
1642
+ const address = req.socket.remoteAddress?.replace(/^::ffff:/i, "");
1643
+ return address !== void 0 && isLoopbackHost(address);
1644
+ }
1633
1645
  function headerValue(value) {
1634
1646
  return Array.isArray(value) ? value[0] : value;
1635
1647
  }
package/dist/index.js CHANGED
@@ -1384,6 +1384,7 @@ function toolToPriority(tool) {
1384
1384
  }
1385
1385
 
1386
1386
  // src/agent/wrongstack-acp-agent.ts
1387
+ import { timingSafeEqual } from "node:crypto";
1387
1388
  import { createServer } from "node:http";
1388
1389
  import { isIP } from "node:net";
1389
1390
  import { fileURLToPath } from "node:url";
@@ -1451,10 +1452,10 @@ var WrongStackACPServer = class {
1451
1452
  this.httpServer = createServer(async (req, res) => {
1452
1453
  if (authToken) {
1453
1454
  const url = new URL(requestPath(req.url), `http://${host}:${port}`);
1454
- const queryToken = url.searchParams.get("token");
1455
1455
  const bearerToken = headerValue(req.headers.authorization)?.replace(/^Bearer\s+/i, "");
1456
- const supplied = queryToken ?? bearerToken ?? "";
1457
- if (supplied !== authToken) {
1456
+ const queryToken = url.searchParams.get("token");
1457
+ const queryOk = queryToken !== null && isLoopbackPeer(req) && timingSafeTokenEqual(queryToken, authToken);
1458
+ if (!queryOk && !timingSafeTokenEqual(bearerToken ?? "", authToken)) {
1458
1459
  res.writeHead(401, { "Content-Type": "application/json" });
1459
1460
  res.end(JSON.stringify({ error: { code: -32001, message: "Unauthorized" } }));
1460
1461
  return;
@@ -1568,6 +1569,17 @@ var WrongStackACPServer = class {
1568
1569
  var defaultEchoRunTurn = async (_input, _emit) => {
1569
1570
  return { stopReason: "end_turn" };
1570
1571
  };
1572
+ function timingSafeTokenEqual(supplied, expected) {
1573
+ if (!supplied || !expected) return false;
1574
+ const a = Buffer.from(supplied);
1575
+ const b = Buffer.from(expected);
1576
+ if (a.length !== b.length) return false;
1577
+ return timingSafeEqual(a, b);
1578
+ }
1579
+ function isLoopbackPeer(req) {
1580
+ const address = req.socket.remoteAddress?.replace(/^::ffff:/i, "");
1581
+ return address !== void 0 && isLoopbackHost(address);
1582
+ }
1571
1583
  function headerValue(value) {
1572
1584
  return Array.isArray(value) ? value[0] : value;
1573
1585
  }
@@ -1,4 +1,5 @@
1
1
  // src/agent/wrongstack-acp-agent.ts
2
+ import { timingSafeEqual } from "node:crypto";
2
3
  import { createServer } from "node:http";
3
4
  import { isIP } from "node:net";
4
5
  import { fileURLToPath } from "node:url";
@@ -1091,10 +1092,10 @@ var WrongStackACPServer = class {
1091
1092
  this.httpServer = createServer(async (req, res) => {
1092
1093
  if (authToken) {
1093
1094
  const url = new URL(requestPath(req.url), `http://${host}:${port}`);
1094
- const queryToken = url.searchParams.get("token");
1095
1095
  const bearerToken = headerValue(req.headers.authorization)?.replace(/^Bearer\s+/i, "");
1096
- const supplied = queryToken ?? bearerToken ?? "";
1097
- if (supplied !== authToken) {
1096
+ const queryToken = url.searchParams.get("token");
1097
+ const queryOk = queryToken !== null && isLoopbackPeer(req) && timingSafeTokenEqual(queryToken, authToken);
1098
+ if (!queryOk && !timingSafeTokenEqual(bearerToken ?? "", authToken)) {
1098
1099
  res.writeHead(401, { "Content-Type": "application/json" });
1099
1100
  res.end(JSON.stringify({ error: { code: -32001, message: "Unauthorized" } }));
1100
1101
  return;
@@ -1208,6 +1209,17 @@ var WrongStackACPServer = class {
1208
1209
  var defaultEchoRunTurn = async (_input, _emit) => {
1209
1210
  return { stopReason: "end_turn" };
1210
1211
  };
1212
+ function timingSafeTokenEqual(supplied, expected) {
1213
+ if (!supplied || !expected) return false;
1214
+ const a = Buffer.from(supplied);
1215
+ const b = Buffer.from(expected);
1216
+ if (a.length !== b.length) return false;
1217
+ return timingSafeEqual(a, b);
1218
+ }
1219
+ function isLoopbackPeer(req) {
1220
+ const address = req.socket.remoteAddress?.replace(/^::ffff:/i, "");
1221
+ return address !== void 0 && isLoopbackHost(address);
1222
+ }
1211
1223
  function headerValue(value) {
1212
1224
  return Array.isArray(value) ? value[0] : value;
1213
1225
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrongstack/acp",
3
- "version": "0.299.0",
3
+ "version": "0.301.0",
4
4
  "license": "MIT",
5
5
  "description": "ACP (Agent Client Protocol) integration for WrongStack — client + agent support",
6
6
  "keywords": [
@@ -52,7 +52,7 @@
52
52
  ],
53
53
  "dependencies": {
54
54
  "@agentclientprotocol/sdk": "^1.3.0",
55
- "@wrongstack/core": "0.299.0"
55
+ "@wrongstack/core": "0.301.0"
56
56
  },
57
57
  "devDependencies": {
58
58
  "@types/node": "^26.1.2",