paygate-mcp 8.90.0 → 8.92.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/server.d.ts CHANGED
@@ -380,6 +380,11 @@ export declare class PayGateServer {
380
380
  private syncKeyMutation;
381
381
  /** Resolve the CORS origin based on config and incoming request Origin header */
382
382
  private resolveCorsOrigin;
383
+ /**
384
+ * Check Content-Type is JSON. Returns true if valid, false and sends 415 if not.
385
+ * Exempt paths (like /oauth/token) accept form-urlencoded per RFC 6749.
386
+ */
387
+ private requireJsonContentType;
383
388
  private readBody;
384
389
  stop(): Promise<void>;
385
390
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAgB,eAAe,EAA0B,MAAM,MAAM,CAAC;AAI7E,OAAO,EAAE,aAAa,EAAkB,mBAAmB,EAAkB,MAAM,SAAS,CAAC;AAE7F,OAAO,EAAE,MAAM,EAAiC,MAAM,UAAU,CAAC;AASjE,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAE7C,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,cAAc,EAAqD,MAAM,WAAW,CAAC;AAC9F,OAAO,EAAE,WAAW,EAAmB,MAAM,SAAS,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAS,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEtC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,eAAe,EAA6B,MAAM,cAAc,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,aAAa,EAAqB,MAAM,UAAU,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAG3C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAmGrD,0EAA0E;AAC1E,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,sFAAsF;AACtF,wBAAgB,YAAY,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,GAAG,SAAS,CAErE;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,eAAe,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAsBvF;AAyCD,yCAAyC;AACzC,KAAK,YAAY,GAAG,QAAQ,GAAG,YAAY,CAAC;AAa5C,qBAAa,aAAa;IACxB,iDAAiD;IACjD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,0DAA0D;IAC1D,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;IACpC,8DAA8D;IAC9D,QAAQ,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC1C,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,oEAAoE;IACpE,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC,mEAAmE;IACnE,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,aAAa,CAAqC;IAC1D,wDAAwD;IACxD,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAQ;IAC5C,oDAAoD;IACpD,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,2BAA2B;IAC3B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,0CAA0C;IAC1C,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC,8CAA8C;IAC9C,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC;IACnC,mCAAmC;IACnC,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC,4CAA4C;IAC5C,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,gCAAgC;IAChC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,yEAAyE;IACzE,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAAQ;IAC5C,4DAA4D;IAC5D,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACpC,qDAAqD;IACrD,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,oCAAoC;IACpC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,oDAAoD;IACpD,QAAQ,CAAC,SAAS,EAAE,kBAAkB,CAAC;IACvC,sCAAsC;IACtC,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,oEAAoE;IACpE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAc;IAC/C,yCAAyC;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsB;IAChD,gEAAgE;IAChE,OAAO,CAAC,QAAQ,CAAS;IACzB,wEAAwE;IACxE,OAAO,CAAC,eAAe,CAAS;IAChC,mDAAmD;IACnD,OAAO,CAAC,kBAAkB,CAAiC;IAC3D,kDAAkD;IAClD,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,gDAAgD;IAChD,OAAO,CAAC,iBAAiB,CAAqF;IAC9G,8CAA8C;IAC9C,OAAO,CAAC,wBAAwB,CAA+C;IAC/E,8BAA8B;IAC9B,OAAO,CAAC,gBAAgB,CAOhB;IACR,2CAA2C;IAC3C,OAAO,CAAC,aAAa,CAA+C;IACpE,4CAA4C;IAC5C,OAAO,CAAC,cAAc,CAAK;IAC3B,kCAAkC;IAClC,OAAO,CAAC,kBAAkB,CAOX;IACf,+CAA+C;IAC/C,OAAO,CAAC,iBAAiB,CAAK;IAC9B,qDAAqD;IACrD,OAAO,CAAC,UAAU,CAUV;IACR,gCAAgC;IAChC,OAAO,CAAC,gBAAgB,CAAK;IAC7B,4CAA4C;IAC5C,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAQ;IAC7C,wCAAwC;IACxC,OAAO,CAAC,QAAQ,CAAK;IACrB,sEAAsE;IACtE,OAAO,CAAC,UAAU,CAAuB;IAEzC,0DAA0D;IAC1D,OAAO,KAAK,OAAO,GAElB;gBAGC,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG;QAAE,aAAa,EAAE,MAAM,CAAA;KAAE,EAC1D,QAAQ,CAAC,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,EAClB,mBAAmB,CAAC,EAAE,MAAM,EAC5B,OAAO,CAAC,EAAE,mBAAmB,EAAE,EAC/B,QAAQ,CAAC,EAAE,MAAM;IAkNnB;;;OAGG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIjC;;;;;;;;;;;OAWG;IACH,GAAG,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IAK1B,KAAK,IAAI,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAkF1D,0EAA0E;IAC1E,OAAO,CAAC,iBAAiB;IA4BzB,uDAAuD;IACvD,OAAO,CAAC,QAAQ;IAKhB,wDAAwD;IACxD,OAAO,CAAC,SAAS;YAWH,aAAa;YAulBb,SAAS;IA2RvB;;;OAGG;IACH,OAAO,CAAC,kBAAkB;IA6C1B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAsB9B;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAyCrB;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAuC7B,OAAO,CAAC,UAAU;IAgLlB,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,YAAY;IAwCpB,OAAO,CAAC,UAAU;IA4ElB,OAAO,CAAC,kBAAkB;IAwD1B,kEAAkE;IAClE,OAAO,CAAC,OAAO;YAWD,eAAe;IAyH7B,OAAO,CAAC,cAAc;YA0DR,WAAW;YAkEX,oBAAoB;YA6GpB,oBAAoB;IAyIlC,OAAO,CAAC,eAAe;YA4DT,eAAe;YAiEf,eAAe;YAiDf,gBAAgB;YA2DhB,eAAe;YAwDf,cAAc;YAgFd,cAAc;YA8Dd,eAAe;YAqDf,YAAY;YAiDZ,eAAe;YA6Df,cAAc;YAwDd,aAAa;YAgDb,oBAAoB;YAgDpB,qBAAqB;IA4BnC,OAAO,CAAC,cAAc;IAwCtB,OAAO,CAAC,kBAAkB;IA+B1B,OAAO,CAAC,cAAc;IAuEtB,OAAO,CAAC,qBAAqB;IAkD7B,OAAO,CAAC,iBAAiB;IAmEzB,OAAO,CAAC,mBAAmB;IA2C3B,OAAO,CAAC,sBAAsB;IAoD9B,OAAO,CAAC,mBAAmB;IA+F3B,OAAO,CAAC,eAAe;IA6IvB,OAAO,CAAC,kBAAkB;YAyLZ,kBAAkB;IA4EhC,OAAO,CAAC,aAAa;YAmDP,YAAY;IA6C1B,OAAO,CAAC,WAAW;YA8CL,mBAAmB;IAgCjC,OAAO,CAAC,eAAe;IAcvB,+EAA+E;IAC/E,OAAO,CAAC,mBAAmB;IAS3B,oEAAoE;YACtD,mBAAmB;IA0DjC,yDAAyD;YAC3C,oBAAoB;IAsFlC,yCAAyC;YAC3B,gBAAgB;IA8E9B,uDAAuD;YACzC,iBAAiB;IA8B/B,sEAAsE;IACtE,OAAO,CAAC,kBAAkB;IAmB1B,OAAO,CAAC,qBAAqB;IAO7B,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,eAAe;IAyBvB,OAAO,CAAC,eAAe;YAWT,qBAAqB;IA8CnC,OAAO,CAAC,oBAAoB;IAe5B,OAAO,CAAC,sBAAsB;YAsBhB,mBAAmB;IA+CjC,OAAO,CAAC,oBAAoB;YAcd,oBAAoB;IA0DlC,OAAO,CAAC,sBAAsB;IA2D9B,OAAO,CAAC,wBAAwB;IAuJhC,OAAO,CAAC,qBAAqB;IA6G7B,OAAO,CAAC,wBAAwB;IAuGhC,OAAO,CAAC,kBAAkB;IAqH1B,OAAO,CAAC,uBAAuB;IAkH/B,OAAO,CAAC,mBAAmB;IAgH3B,OAAO,CAAC,oBAAoB;IA4H5B,OAAO,CAAC,qBAAqB;IAkI7B,OAAO,CAAC,mBAAmB;IAuH3B,OAAO,CAAC,qBAAqB;IAgF7B,OAAO,CAAC,uBAAuB;IAuF/B,OAAO,CAAC,sBAAsB;IAqG9B,OAAO,CAAC,sBAAsB;IAsF9B,OAAO,CAAC,sBAAsB;IA2G9B,OAAO,CAAC,mBAAmB;IA8E3B,OAAO,CAAC,sBAAsB;IA6F9B,OAAO,CAAC,mBAAmB;IAmE3B,OAAO,CAAC,qBAAqB;IAqF7B,OAAO,CAAC,iBAAiB;IAwEzB,OAAO,CAAC,gBAAgB;IAqExB,OAAO,CAAC,YAAY;IAiEpB,OAAO,CAAC,oBAAoB;IAiD5B,OAAO,CAAC,kBAAkB;IAiD1B,OAAO,CAAC,sBAAsB;IAmE9B,OAAO,CAAC,mBAAmB;IAgF3B,OAAO,CAAC,eAAe;IAiEvB,OAAO,CAAC,mBAAmB;IAoD3B,OAAO,CAAC,sBAAsB;IA4E9B,OAAO,CAAC,kBAAkB;IAoF1B,OAAO,CAAC,kBAAkB;IA0D1B,OAAO,CAAC,sBAAsB;IA+E9B,OAAO,CAAC,mBAAmB;IA2D3B,OAAO,CAAC,cAAc;IAqDtB,OAAO,CAAC,qBAAqB;IAwD7B,OAAO,CAAC,0BAA0B;IA+DlC,OAAO,CAAC,wBAAwB;IAyEhC,OAAO,CAAC,8BAA8B;IAiFtC,OAAO,CAAC,2BAA2B;IAsEnC,OAAO,CAAC,iBAAiB;IAqDzB,OAAO,CAAC,uBAAuB;IA4D/B,OAAO,CAAC,oBAAoB;IA+C5B,OAAO,CAAC,uBAAuB;IAoE/B,OAAO,CAAC,sBAAsB;IAsD9B,OAAO,CAAC,kBAAkB;IA6D1B,OAAO,CAAC,eAAe;IA4DvB,OAAO,CAAC,sBAAsB;IA8D9B,OAAO,CAAC,oBAAoB;IAmD5B,OAAO,CAAC,oBAAoB;IAqD5B,OAAO,CAAC,uBAAuB;IA0D/B,OAAO,CAAC,yBAAyB;IAuDjC,OAAO,CAAC,oBAAoB;IAqD5B,OAAO,CAAC,uBAAuB;IAmD/B,OAAO,CAAC,iBAAiB;IA+CzB,OAAO,CAAC,mBAAmB;IA8D3B,OAAO,CAAC,qBAAqB;IA0D7B,OAAO,CAAC,uBAAuB;IAkE/B,OAAO,CAAC,oBAAoB;IAoE5B,OAAO,CAAC,uBAAuB;IAwD/B,OAAO,CAAC,2BAA2B;IAyDnC,OAAO,CAAC,mBAAmB;IAwE3B,OAAO,CAAC,mBAAmB;IAsF3B,OAAO,CAAC,gBAAgB;IAsDxB,OAAO,CAAC,kBAAkB;IAsF1B,OAAO,CAAC,sBAAsB;IAiF9B,OAAO,CAAC,cAAc;YAsBR,aAAa;IA8D3B,OAAO,CAAC,gBAAgB;IA6CxB,OAAO,CAAC,kBAAkB;YA2BZ,oBAAoB;IA4FlC,OAAO,CAAC,oBAAoB;IAgC5B,gFAAgF;IAChF,OAAO,CAAC,uBAAuB;IAiD/B,OAAO,CAAC,iBAAiB;IAgGzB,OAAO,CAAC,sBAAsB;YA8BhB,uBAAuB;YAiGvB,uBAAuB;YAmEvB,wBAAwB;IA+CtC,uEAAuE;IACvE,OAAO,CAAC,cAAc;IAQtB,mCAAmC;IACnC,OAAO,CAAC,0BAA0B;YAWpB,kBAAkB;IAkIhC,OAAO,CAAC,kBAAkB;IA2B1B,OAAO,CAAC,gBAAgB;IAyCxB,OAAO,CAAC,kBAAkB;IA4B1B,OAAO,CAAC,mBAAmB;YA6Bb,iBAAiB;IA8H/B,OAAO,CAAC,wBAAwB;YAYlB,yBAAyB;YA2CzB,yBAAyB;YAqDzB,yBAAyB;IAsCvC,OAAO,CAAC,WAAW;IAyBnB,OAAO,CAAC,iBAAiB;IA2CzB,OAAO,CAAC,gBAAgB;IAaxB,OAAO,CAAC,UAAU;IA8ClB,OAAO,CAAC,eAAe;YAeT,gBAAgB;YAwChB,gBAAgB;YAwChB,gBAAgB;YAiChB,mBAAmB;YA+CnB,mBAAmB;IAwCjC,OAAO,CAAC,eAAe;IA2BvB,OAAO,CAAC,oBAAoB;YAed,iBAAiB;YAsDjB,iBAAiB;IA2D/B,OAAO,CAAC,uBAAuB;IAuB/B,OAAO,CAAC,iBAAiB;IAazB,OAAO,CAAC,gBAAgB;YAMV,iBAAiB;YAyCjB,iBAAiB;YAmDjB,iBAAiB;YAoCjB,sBAAsB;YAiDtB,wBAAwB;IA4CtC,OAAO,CAAC,mBAAmB;YAoBb,oBAAoB;YAoDpB,oBAAoB;YAgDpB,wBAAwB;IAqCtC,OAAO,CAAC,mBAAmB;YAOb,oBAAoB;YAoCpB,oBAAoB;IAmClC;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,eAAe;IAUvB,iFAAiF;IACjF,OAAO,CAAC,iBAAiB;IAuBzB;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAiB9B,OAAO,CAAC,QAAQ;IA0DV,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAqC3B;;;;;;;OAOG;IACG,YAAY,CAAC,SAAS,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAiErD,OAAO,CAAC,gBAAgB;IAsExB,OAAO,CAAC,eAAe;YA6GT,mBAAmB;YAoInB,wBAAwB;IA0ItC,OAAO,CAAC,sBAAsB;IA8F9B,OAAO,CAAC,sBAAsB;IA0E9B,qDAAqD;IACrD,OAAO,CAAC,UAAU;CAMnB"}
package/dist/server.js CHANGED
@@ -135,6 +135,44 @@ function clampArray(arr, maxLen) {
135
135
  return arr;
136
136
  return arr.slice(0, maxLen);
137
137
  }
138
+ /**
139
+ * Sanitize error messages before sending to clients — prevents information disclosure.
140
+ * Returns a generic message unless the error is a known-safe validation error.
141
+ * The full error is returned for internal logging only.
142
+ */
143
+ function safeErrorMessage(err, fallback = 'Invalid request') {
144
+ const raw = err instanceof Error ? err.message : String(err);
145
+ // Truncate before regex matching to prevent ReDoS on crafted long strings
146
+ const msg = raw.slice(0, 500);
147
+ // Allow known-safe, controlled error messages to pass through.
148
+ // These are validation messages from our own code, not system/library errors.
149
+ const safePatterns = [
150
+ /^invalid_grant/,
151
+ /^Request body too large$/,
152
+ /^Request body read timeout$/,
153
+ /^Missing required field/i,
154
+ /^Invalid (?:key|token|group|filter|parameter|redirect)/i,
155
+ /^(?:Key|Token|Group|Filter)\b.*\bnot found/i,
156
+ /^Unknown (?:client|action)/i,
157
+ /^Insufficient/i,
158
+ /^Duplicate/i,
159
+ /^Not found/i,
160
+ /^Unauthorized/i,
161
+ /^Forbidden/i,
162
+ /^(?:ACL|Quota|Rate) limit/i,
163
+ /^(?:Group|Filter) (?:must have|rule must)/i,
164
+ /^(?:Group) '.+' already exists/i,
165
+ /^.+(?:is required|are required)/i, // validation messages: "X is required"
166
+ /^Only .+ (?:is |are )?supported/i, // capability constraints
167
+ /^No API key linked/i, // OAuth setup validation
168
+ /^code_challenge/i, // PKCE validation
169
+ ];
170
+ for (const pattern of safePatterns) {
171
+ if (pattern.test(msg))
172
+ return msg;
173
+ }
174
+ return fallback;
175
+ }
138
176
  /** Truncate user-supplied strings to MAX_STRING_FIELD to prevent log injection and memory abuse. */
139
177
  function sanitizeString(value, maxLen = MAX_STRING_FIELD) {
140
178
  if (!value)
@@ -565,6 +603,7 @@ class PayGateServer {
565
603
  this.server.requestTimeout = this.config.requestTimeoutMs ?? 30_000; // 30s max per request (Node default: 0 = none)
566
604
  this.server.headersTimeout = this.config.headersTimeoutMs ?? 10_000; // 10s to receive headers (Node default: 60s)
567
605
  this.server.keepAliveTimeout = this.config.keepAliveTimeoutMs ?? 65_000; // 65s keep-alive (> typical 60s LB idle)
606
+ this.server.maxConnections = this.config.maxConnections ?? 10_000; // Cap concurrent TCP connections to prevent FD exhaustion
568
607
  if (this.config.maxRequestsPerSocket) {
569
608
  this.server.maxRequestsPerSocket = this.config.maxRequestsPerSocket; // Limit pipelined requests per socket
570
609
  }
@@ -714,7 +753,8 @@ class PayGateServer {
714
753
  return this.handleCreateKey(req, res);
715
754
  if (req.method === 'GET')
716
755
  return this.handleListKeys(req, res);
717
- break;
756
+ this.sendError(res, 405, 'Method not allowed. Use GET or POST.');
757
+ return;
718
758
  case '/keys/revoke':
719
759
  return this.handleRevokeKey(req, res);
720
760
  case '/keys/suspend':
@@ -809,7 +849,8 @@ class PayGateServer {
809
849
  return this.handleListTemplates(req, res);
810
850
  if (req.method === 'POST')
811
851
  return this.handleCreateTemplate(req, res);
812
- break;
852
+ this.sendError(res, 405, 'Method not allowed. Use GET or POST.');
853
+ return;
813
854
  case '/keys/templates/delete':
814
855
  return this.handleDeleteTemplate(req, res);
815
856
  case '/topup':
@@ -882,14 +923,16 @@ class PayGateServer {
882
923
  return this.handleGetAlerts(req, res);
883
924
  if (req.method === 'POST')
884
925
  return this.handleConfigureAlerts(req, res);
885
- break;
926
+ this.sendError(res, 405, 'Method not allowed. Use GET or POST.');
927
+ return;
886
928
  // ─── Webhook admin endpoints ─────────────────────────────────────
887
929
  case '/webhooks/dead-letter':
888
930
  if (req.method === 'GET')
889
931
  return this.handleGetDeadLetters(req, res);
890
932
  if (req.method === 'DELETE')
891
933
  return this.handleClearDeadLetters(req, res);
892
- break;
934
+ this.sendError(res, 405, 'Method not allowed. Use GET or DELETE.');
935
+ return;
893
936
  case '/webhooks/replay':
894
937
  return this.handleWebhookReplay(req, res);
895
938
  case '/webhooks/stats':
@@ -907,7 +950,8 @@ class PayGateServer {
907
950
  return this.handleListWebhookFilters(req, res);
908
951
  if (req.method === 'POST')
909
952
  return this.handleCreateWebhookFilter(req, res);
910
- break;
953
+ this.sendError(res, 405, 'Method not allowed. Use GET or POST.');
954
+ return;
911
955
  case '/webhooks/filters/update':
912
956
  return this.handleUpdateWebhookFilter(req, res);
913
957
  case '/webhooks/filters/delete':
@@ -918,7 +962,8 @@ class PayGateServer {
918
962
  return this.handleListTeams(req, res);
919
963
  if (req.method === 'POST')
920
964
  return this.handleCreateTeam(req, res);
921
- break;
965
+ this.sendError(res, 405, 'Method not allowed. Use GET or POST.');
966
+ return;
922
967
  case '/teams/update':
923
968
  return this.handleUpdateTeam(req, res);
924
969
  case '/teams/delete':
@@ -936,7 +981,8 @@ class PayGateServer {
936
981
  case '/tokens':
937
982
  if (req.method === 'POST')
938
983
  return this.handleCreateToken(req, res);
939
- break;
984
+ this.sendError(res, 405, 'Method not allowed. Use POST.');
985
+ return;
940
986
  case '/tokens/revoke':
941
987
  return this.handleRevokeToken(req, res);
942
988
  case '/tokens/revoked':
@@ -947,7 +993,8 @@ class PayGateServer {
947
993
  return this.handleCreateAdminKey(req, res);
948
994
  if (req.method === 'GET')
949
995
  return this.handleListAdminKeys(req, res);
950
- break;
996
+ this.sendError(res, 405, 'Method not allowed. Use GET or POST.');
997
+ return;
951
998
  case '/admin/keys/revoke':
952
999
  return this.handleRevokeAdminKey(req, res);
953
1000
  case '/admin/keys/rotate-bootstrap':
@@ -1282,7 +1329,8 @@ class PayGateServer {
1282
1329
  return this.handleListGroups(req, res);
1283
1330
  if (req.method === 'POST')
1284
1331
  return this.handleCreateGroup(req, res);
1285
- break;
1332
+ this.sendError(res, 405, 'Method not allowed. Use GET or POST.');
1333
+ return;
1286
1334
  case '/groups/update':
1287
1335
  return this.handleUpdateGroup(req, res);
1288
1336
  case '/groups/delete':
@@ -1346,6 +1394,8 @@ class PayGateServer {
1346
1394
  this.sendError(res, 405, 'Method not allowed');
1347
1395
  return;
1348
1396
  }
1397
+ if (!this.requireJsonContentType(req, res))
1398
+ return;
1349
1399
  const body = await this.readBody(req);
1350
1400
  let request;
1351
1401
  try {
@@ -2518,7 +2568,8 @@ class PayGateServer {
2518
2568
  }
2519
2569
  }
2520
2570
  catch (e) {
2521
- results.push({ index: i, action: op.action || 'unknown', success: false, error: e.message || 'Internal error' });
2571
+ this.logger.warn('Bulk operation failed', { index: i, action: op.action, error: e.message });
2572
+ results.push({ index: i, action: op.action || 'unknown', success: false, error: safeErrorMessage(e, 'Operation failed') });
2522
2573
  }
2523
2574
  }
2524
2575
  const succeeded = results.filter(r => r.success).length;
@@ -4187,6 +4238,8 @@ class PayGateServer {
4187
4238
  this.sendError(res, 405, 'Method not allowed');
4188
4239
  return;
4189
4240
  }
4241
+ if (!this.requireJsonContentType(req, res))
4242
+ return;
4190
4243
  const body = await this.readBody(req);
4191
4244
  let params;
4192
4245
  try {
@@ -4221,8 +4274,9 @@ class PayGateServer {
4221
4274
  });
4222
4275
  }
4223
4276
  catch (err) {
4277
+ this.logger.warn('OAuth client registration failed', { error: err.message });
4224
4278
  res.writeHead(400, { 'Content-Type': 'application/json' });
4225
- res.end(JSON.stringify({ error: 'invalid_client_metadata', error_description: err.message }));
4279
+ res.end(JSON.stringify({ error: 'invalid_client_metadata', error_description: safeErrorMessage(err, 'Invalid client metadata') }));
4226
4280
  }
4227
4281
  }
4228
4282
  /** GET/POST /oauth/authorize — Authorization endpoint */
@@ -4291,13 +4345,15 @@ class PayGateServer {
4291
4345
  res.end();
4292
4346
  }
4293
4347
  catch (err) {
4294
- const errorMsg = err.message;
4348
+ const rawMsg = err.message;
4349
+ this.logger.warn('OAuth authorization failed', { error: rawMsg });
4350
+ const safeMsg = safeErrorMessage(err, 'Authorization failed');
4295
4351
  // If there's a redirect URI and client is valid, redirect with error
4296
4352
  if (redirectUri) {
4297
4353
  try {
4298
4354
  const redirectUrl = new URL(redirectUri);
4299
4355
  redirectUrl.searchParams.set('error', 'server_error');
4300
- redirectUrl.searchParams.set('error_description', errorMsg);
4356
+ redirectUrl.searchParams.set('error_description', safeMsg);
4301
4357
  if (state)
4302
4358
  redirectUrl.searchParams.set('state', state);
4303
4359
  res.writeHead(302, { Location: redirectUrl.toString() });
@@ -4307,7 +4363,7 @@ class PayGateServer {
4307
4363
  catch { /* fall through to JSON error */ }
4308
4364
  }
4309
4365
  res.writeHead(400, { 'Content-Type': 'application/json' });
4310
- res.end(JSON.stringify({ error: 'invalid_request', error_description: errorMsg }));
4366
+ res.end(JSON.stringify({ error: 'invalid_request', error_description: safeMsg }));
4311
4367
  }
4312
4368
  }
4313
4369
  /** POST /oauth/token — Token endpoint */
@@ -4320,13 +4376,15 @@ class PayGateServer {
4320
4376
  this.sendError(res, 405, 'Method not allowed');
4321
4377
  return;
4322
4378
  }
4379
+ if (!this.requireJsonContentType(req, res))
4380
+ return;
4323
4381
  const body = await this.readBody(req);
4324
4382
  let params;
4325
4383
  try {
4326
4384
  params = safeJsonParse(body);
4327
4385
  }
4328
4386
  catch {
4329
- // Try URL-encoded form data
4387
+ // Try URL-encoded form data (RFC 6749)
4330
4388
  params = {};
4331
4389
  const query = new URLSearchParams(body);
4332
4390
  for (const [k, v] of query)
@@ -4379,10 +4437,12 @@ class PayGateServer {
4379
4437
  }
4380
4438
  }
4381
4439
  catch (err) {
4382
- const errorMsg = err.message;
4383
- const errorCode = errorMsg.startsWith('invalid_grant') ? 'invalid_grant' : 'invalid_request';
4440
+ const rawMsg = err.message;
4441
+ this.logger.warn('OAuth token exchange failed', { error: rawMsg });
4442
+ const errorCode = rawMsg.startsWith('invalid_grant') ? 'invalid_grant' : 'invalid_request';
4443
+ const safeMsg = safeErrorMessage(err, 'Token exchange failed');
4384
4444
  res.writeHead(400, { 'Content-Type': 'application/json' });
4385
- res.end(JSON.stringify({ error: errorCode, error_description: errorMsg }));
4445
+ res.end(JSON.stringify({ error: errorCode, error_description: safeMsg }));
4386
4446
  }
4387
4447
  }
4388
4448
  /** POST /oauth/revoke — Token revocation (RFC 7009) */
@@ -9646,7 +9706,8 @@ class PayGateServer {
9646
9706
  fileConfig = JSON.parse(raw);
9647
9707
  }
9648
9708
  catch (err) {
9649
- this.sendError(res, 400, `Failed to read config file: ${err.message}`);
9709
+ this.logger.error('Config file read/parse failed', { error: err.message, path: filePath });
9710
+ this.sendError(res, 400, 'Failed to read or parse config file');
9650
9711
  return;
9651
9712
  }
9652
9713
  // Validate the loaded config
@@ -9936,7 +9997,8 @@ class PayGateServer {
9936
9997
  }
9937
9998
  });
9938
9999
  reqObj.on('error', (err) => {
9939
- resolve({ success: false, error: err.message, responseTime: Date.now() - startTime });
10000
+ this.logger.warn('Webhook test delivery failed', { error: err.message, url: parsed.hostname });
10001
+ resolve({ success: false, error: 'Connection failed', responseTime: Date.now() - startTime });
9940
10002
  });
9941
10003
  reqObj.on('timeout', () => {
9942
10004
  reqObj.destroy();
@@ -10003,7 +10065,8 @@ class PayGateServer {
10003
10065
  this.sendJson(res, 201, rule);
10004
10066
  }
10005
10067
  catch (err) {
10006
- this.sendError(res, 400, err.message);
10068
+ this.logger.warn('Webhook filter creation failed', { error: err.message });
10069
+ this.sendError(res, 400, safeErrorMessage(err, 'Failed to create webhook filter'));
10007
10070
  }
10008
10071
  }
10009
10072
  async handleUpdateWebhookFilter(req, res) {
@@ -10052,7 +10115,8 @@ class PayGateServer {
10052
10115
  this.sendJson(res, 200, rule);
10053
10116
  }
10054
10117
  catch (err) {
10055
- this.sendError(res, 400, err.message);
10118
+ this.logger.warn('Webhook filter update failed', { error: err.message });
10119
+ this.sendError(res, 400, safeErrorMessage(err, 'Failed to update webhook filter'));
10056
10120
  }
10057
10121
  }
10058
10122
  async handleDeleteWebhookFilter(req, res) {
@@ -10192,6 +10256,9 @@ class PayGateServer {
10192
10256
  this.sendError(res, 403, 'Insufficient permissions', { requiredRole: minRole, currentRole: record.role });
10193
10257
  return false;
10194
10258
  }
10259
+ // Content-Type enforcement for POST requests (after auth, before body read)
10260
+ if (req.method === 'POST' && !this.requireJsonContentType(req, res))
10261
+ return false;
10195
10262
  return true;
10196
10263
  }
10197
10264
  // ─── /teams — Team management ────────────────────────────────────────────
@@ -10593,7 +10660,8 @@ class PayGateServer {
10593
10660
  this.sendJson(res, 201, group);
10594
10661
  }
10595
10662
  catch (err) {
10596
- this.sendError(res, 400, err.message);
10663
+ this.logger.warn('Group creation failed', { error: err.message });
10664
+ this.sendError(res, 400, safeErrorMessage(err, 'Failed to create group'));
10597
10665
  }
10598
10666
  }
10599
10667
  async handleUpdateGroup(req, res) {
@@ -10643,7 +10711,8 @@ class PayGateServer {
10643
10711
  this.sendJson(res, 200, group);
10644
10712
  }
10645
10713
  catch (err) {
10646
- this.sendError(res, 400, err.message);
10714
+ this.logger.warn('Group update failed', { error: err.message });
10715
+ this.sendError(res, 400, safeErrorMessage(err, 'Failed to update group'));
10647
10716
  }
10648
10717
  }
10649
10718
  async handleDeleteGroup(req, res) {
@@ -10723,7 +10792,8 @@ class PayGateServer {
10723
10792
  this.sendJson(res, 200, { ok: true, message: `Key assigned to group ${groupId}` });
10724
10793
  }
10725
10794
  catch (err) {
10726
- this.sendError(res, 400, err.message);
10795
+ this.logger.warn('Group key assignment failed', { error: err.message, groupId });
10796
+ this.sendError(res, 400, safeErrorMessage(err, 'Failed to assign key to group'));
10727
10797
  }
10728
10798
  }
10729
10799
  async handleRemoveKeyFromGroup(req, res) {
@@ -11011,6 +11081,28 @@ class PayGateServer {
11011
11081
  }
11012
11082
  return '*';
11013
11083
  }
11084
+ /**
11085
+ * Check Content-Type is JSON. Returns true if valid, false and sends 415 if not.
11086
+ * Exempt paths (like /oauth/token) accept form-urlencoded per RFC 6749.
11087
+ */
11088
+ requireJsonContentType(req, res) {
11089
+ if (req.method !== 'POST')
11090
+ return true; // Only enforce for POST
11091
+ const ct = (req.headers['content-type'] || '').toLowerCase();
11092
+ const url = req.url?.split('?')[0] || '/';
11093
+ if (url === '/oauth/token') {
11094
+ // OAuth token endpoint accepts both JSON and form-encoded per RFC 6749
11095
+ if (ct.startsWith('application/json') || ct.startsWith('application/x-www-form-urlencoded'))
11096
+ return true;
11097
+ this.sendError(res, 415, 'Unsupported Media Type. Use application/json or application/x-www-form-urlencoded');
11098
+ return false;
11099
+ }
11100
+ if (!ct.startsWith('application/json')) {
11101
+ this.sendError(res, 415, 'Unsupported Media Type. Use application/json');
11102
+ return false;
11103
+ }
11104
+ return true;
11105
+ }
11014
11106
  readBody(req) {
11015
11107
  return new Promise((resolve, reject) => {
11016
11108
  let body = '';