@theia/core 1.73.0-next.43 → 1.73.0-next.52

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.
Files changed (81) hide show
  1. package/README.md +1 -1
  2. package/lib/browser/catalog.json +6 -0
  3. package/lib/browser/messaging/ws-connection-source.d.ts.map +1 -1
  4. package/lib/browser/messaging/ws-connection-source.js +1 -6
  5. package/lib/browser/messaging/ws-connection-source.js.map +1 -1
  6. package/lib/browser/tree/tree-view-welcome-widget.d.ts +1 -0
  7. package/lib/browser/tree/tree-view-welcome-widget.d.ts.map +1 -1
  8. package/lib/browser/tree/tree-view-welcome-widget.js +8 -6
  9. package/lib/browser/tree/tree-view-welcome-widget.js.map +1 -1
  10. package/lib/browser/tree/tree-view-welcome-widget.spec.d.ts +2 -0
  11. package/lib/browser/tree/tree-view-welcome-widget.spec.d.ts.map +1 -0
  12. package/lib/browser/tree/tree-view-welcome-widget.spec.js +68 -0
  13. package/lib/browser/tree/tree-view-welcome-widget.spec.js.map +1 -0
  14. package/lib/electron-node/hosting/electron-ws-origin-validator.d.ts.map +1 -1
  15. package/lib/electron-node/hosting/electron-ws-origin-validator.js +5 -2
  16. package/lib/electron-node/hosting/electron-ws-origin-validator.js.map +1 -1
  17. package/lib/electron-node/hosting/electron-ws-origin-validator.spec.d.ts +2 -0
  18. package/lib/electron-node/hosting/electron-ws-origin-validator.spec.d.ts.map +1 -0
  19. package/lib/electron-node/hosting/electron-ws-origin-validator.spec.js +59 -0
  20. package/lib/electron-node/hosting/electron-ws-origin-validator.spec.js.map +1 -0
  21. package/lib/node/backend-application-module.d.ts.map +1 -1
  22. package/lib/node/backend-application-module.js +2 -0
  23. package/lib/node/backend-application-module.js.map +1 -1
  24. package/lib/node/backend-application.d.ts +9 -0
  25. package/lib/node/backend-application.d.ts.map +1 -1
  26. package/lib/node/backend-application.js +23 -1
  27. package/lib/node/backend-application.js.map +1 -1
  28. package/lib/node/backend-application.spec.js +1 -0
  29. package/lib/node/backend-application.spec.js.map +1 -1
  30. package/lib/node/hosting/backend-hosting-module.d.ts.map +1 -1
  31. package/lib/node/hosting/backend-hosting-module.js +7 -0
  32. package/lib/node/hosting/backend-hosting-module.js.map +1 -1
  33. package/lib/node/hosting/browser-connection-token.d.ts +46 -0
  34. package/lib/node/hosting/browser-connection-token.d.ts.map +1 -0
  35. package/lib/node/hosting/browser-connection-token.js +120 -0
  36. package/lib/node/hosting/browser-connection-token.js.map +1 -0
  37. package/lib/node/hosting/browser-connection-token.spec.d.ts +2 -0
  38. package/lib/node/hosting/browser-connection-token.spec.d.ts.map +1 -0
  39. package/lib/node/hosting/browser-connection-token.spec.js +128 -0
  40. package/lib/node/hosting/browser-connection-token.spec.js.map +1 -0
  41. package/lib/node/hosting/ws-origin-validator.d.ts.map +1 -1
  42. package/lib/node/hosting/ws-origin-validator.js +21 -4
  43. package/lib/node/hosting/ws-origin-validator.js.map +1 -1
  44. package/lib/node/hosting/ws-origin-validator.spec.d.ts +2 -0
  45. package/lib/node/hosting/ws-origin-validator.spec.d.ts.map +1 -0
  46. package/lib/node/hosting/ws-origin-validator.spec.js +131 -0
  47. package/lib/node/hosting/ws-origin-validator.spec.js.map +1 -0
  48. package/lib/node/index.d.ts +1 -0
  49. package/lib/node/index.d.ts.map +1 -1
  50. package/lib/node/index.js +3 -1
  51. package/lib/node/index.js.map +1 -1
  52. package/lib/node/messaging/websocket-endpoint.d.ts +5 -0
  53. package/lib/node/messaging/websocket-endpoint.d.ts.map +1 -1
  54. package/lib/node/messaging/websocket-endpoint.js +14 -5
  55. package/lib/node/messaging/websocket-endpoint.js.map +1 -1
  56. package/lib/node/request/backend-request-facade.d.ts +19 -0
  57. package/lib/node/request/backend-request-facade.d.ts.map +1 -1
  58. package/lib/node/request/backend-request-facade.js +93 -3
  59. package/lib/node/request/backend-request-facade.js.map +1 -1
  60. package/lib/node/request/backend-request-facade.spec.d.ts +2 -0
  61. package/lib/node/request/backend-request-facade.spec.d.ts.map +1 -0
  62. package/lib/node/request/backend-request-facade.spec.js +171 -0
  63. package/lib/node/request/backend-request-facade.spec.js.map +1 -0
  64. package/package.json +4 -4
  65. package/src/browser/messaging/ws-connection-source.ts +1 -6
  66. package/src/browser/tree/tree-view-welcome-widget.spec.ts +80 -0
  67. package/src/browser/tree/tree-view-welcome-widget.tsx +10 -11
  68. package/src/electron-node/hosting/electron-ws-origin-validator.spec.ts +69 -0
  69. package/src/electron-node/hosting/electron-ws-origin-validator.ts +5 -2
  70. package/src/node/backend-application-module.ts +4 -2
  71. package/src/node/backend-application.spec.ts +2 -0
  72. package/src/node/backend-application.ts +18 -0
  73. package/src/node/hosting/backend-hosting-module.ts +10 -0
  74. package/src/node/hosting/browser-connection-token.spec.ts +167 -0
  75. package/src/node/hosting/browser-connection-token.ts +126 -0
  76. package/src/node/hosting/ws-origin-validator.spec.ts +193 -0
  77. package/src/node/hosting/ws-origin-validator.ts +23 -4
  78. package/src/node/index.ts +1 -0
  79. package/src/node/messaging/websocket-endpoint.ts +17 -5
  80. package/src/node/request/backend-request-facade.spec.ts +203 -0
  81. package/src/node/request/backend-request-facade.ts +108 -3
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/node/index.ts"],"names":[],"mappings":"AAgBA,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,SAAS,CAAC;AACxB,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,OAAO,CAAC;AACtB,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/node/index.ts"],"names":[],"mappings":"AAgBA,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,SAAS,CAAC;AACxB,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,OAAO,CAAC;AACtB,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,iCAAiC,EAAE,MAAM,kCAAkC,CAAC"}
package/lib/node/index.js CHANGED
@@ -15,7 +15,7 @@
15
15
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16
16
  // *****************************************************************************
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.FileSystemLocking = void 0;
18
+ exports.BackendRequestAllowedContribution = exports.FileSystemLocking = void 0;
19
19
  const tslib_1 = require("tslib");
20
20
  tslib_1.__exportStar(require("./backend-application"), exports);
21
21
  tslib_1.__exportStar(require("./backend-global"), exports);
@@ -26,4 +26,6 @@ tslib_1.__exportStar(require("./cli"), exports);
26
26
  tslib_1.__exportStar(require("./setting-service"), exports);
27
27
  var filesystem_locking_1 = require("./filesystem-locking");
28
28
  Object.defineProperty(exports, "FileSystemLocking", { enumerable: true, get: function () { return filesystem_locking_1.FileSystemLocking; } });
29
+ var backend_request_facade_1 = require("./request/backend-request-facade");
30
+ Object.defineProperty(exports, "BackendRequestAllowedContribution", { enumerable: true, get: function () { return backend_request_facade_1.BackendRequestAllowedContribution; } });
29
31
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/node/index.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,yCAAyC;AACzC,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;;;AAEhF,gEAAsC;AACtC,2DAAiC;AACjC,kDAAwB;AACxB,6DAAmC;AACnC,sDAA4B;AAC5B,gDAAsB;AACtB,4DAAkC;AAClC,2DAAyD;AAAhD,uHAAA,iBAAiB,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/node/index.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,yCAAyC;AACzC,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;;;AAEhF,gEAAsC;AACtC,2DAAiC;AACjC,kDAAwB;AACxB,6DAAmC;AACnC,sDAA4B;AAC5B,gDAAsB;AACtB,4DAAkC;AAClC,2DAAyD;AAAhD,uHAAA,iBAAiB,OAAA;AAC1B,2EAAqF;AAA5E,2IAAA,iCAAiC,OAAA"}
@@ -16,6 +16,11 @@ export declare class WebsocketEndpoint implements BackendApplicationContribution
16
16
  protected readonly wsHandlers: ConnectionHandlers<Socket<import("socket.io").DefaultEventsMap, import("socket.io").DefaultEventsMap, import("socket.io").DefaultEventsMap, any>>;
17
17
  registerConnectionHandler(spec: string, callback: (params: MessagingService.PathParams, socket: Socket) => void): void;
18
18
  onStart(server: http.Server | https.Server): void;
19
+ /**
20
+ * Secondary validation after connection. The primary check happens in the
21
+ * Socket.IO `allowRequest` callback at handshake time; this is kept as
22
+ * defense-in-depth in case a Socket.IO upgrade path bypasses `allowRequest`.
23
+ */
19
24
  protected allowConnect(request: http.IncomingMessage): Promise<boolean>;
20
25
  protected handleConnection(socket: Socket): Promise<void>;
21
26
  }
@@ -1 +1 @@
1
- {"version":3,"file":"websocket-endpoint.d.ts","sourceRoot":"","sources":["../../../src/node/messaging/websocket-endpoint.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAU,MAAM,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,8BAA8B,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAE9C,qBACa,iBAAkB,YAAW,8BAA8B;IAEpE,SAAS,CAAC,QAAQ,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;IAG1D,SAAS,CAAC,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAGxD,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAEnC,SAAS,CAAC,iBAAiB,SAAS;IACpC,SAAS,CAAC,iBAAiB,SAAO;IAElC,SAAS,CAAC,QAAQ,CAAC,UAAU,oJAAoC;IAEjE,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAItH,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,IAAI;cAqBjC,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC;cAQ7D,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAMlE"}
1
+ {"version":3,"file":"websocket-endpoint.d.ts","sourceRoot":"","sources":["../../../src/node/messaging/websocket-endpoint.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAU,MAAM,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,8BAA8B,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAE9C,qBACa,iBAAkB,YAAW,8BAA8B;IAEpE,SAAS,CAAC,QAAQ,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;IAG1D,SAAS,CAAC,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAGxD,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAEnC,SAAS,CAAC,iBAAiB,SAAS;IACpC,SAAS,CAAC,iBAAiB,SAAO;IAElC,SAAS,CAAC,QAAQ,CAAC,UAAU,oJAAoC;IAEjE,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAItH,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,IAAI;IA4BjD;;;;OAIG;cACa,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC;cAQ7D,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAMlE"}
@@ -35,14 +35,18 @@ let WebsocketEndpoint = class WebsocketEndpoint {
35
35
  const socketServer = new socket_io_1.Server(server, {
36
36
  pingInterval: this.checkAliveTimeout,
37
37
  pingTimeout: this.checkAliveTimeout * 2,
38
- maxHttpBufferSize: this.maxHttpBufferSize
38
+ maxHttpBufferSize: this.maxHttpBufferSize,
39
+ allowRequest: (req, callback) => {
40
+ // eslint-disable-next-line no-null/no-null
41
+ const noError = null;
42
+ this.wsRequestValidator.allowWsUpgrade(req).then(allowed => callback(noError, allowed), error => {
43
+ console.error('Error during WebSocket allowRequest validation:', error);
44
+ callback(error?.message ?? 'Validation error', false);
45
+ });
46
+ }
39
47
  });
40
48
  // Accept every namespace by using /.*/
41
49
  socketServer.of(/.*/).on('connection', async (socket) => {
42
- const request = socket.request;
43
- // Socket.io strips the `origin` header of the incoming request
44
- // We provide a `fix-origin` header in the `WebSocketConnectionProvider`
45
- request.headers.origin = request.headers['fix-origin'];
46
50
  if (await this.allowConnect(socket.request)) {
47
51
  await this.handleConnection(socket);
48
52
  this.messagingListener.onDidWebSocketUpgrade(socket.request, socket);
@@ -52,6 +56,11 @@ let WebsocketEndpoint = class WebsocketEndpoint {
52
56
  }
53
57
  });
54
58
  }
59
+ /**
60
+ * Secondary validation after connection. The primary check happens in the
61
+ * Socket.IO `allowRequest` callback at handshake time; this is kept as
62
+ * defense-in-depth in case a Socket.IO upgrade path bypasses `allowRequest`.
63
+ */
55
64
  async allowConnect(request) {
56
65
  try {
57
66
  return this.wsRequestValidator.allowWsUpgrade(request);
@@ -1 +1 @@
1
- {"version":3,"file":"websocket-endpoint.js","sourceRoot":"","sources":["../../../src/node/messaging/websocket-endpoint.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,oDAAoD;AACpD,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;;;;AAKhF,yCAAsD;AACtD,yCAA2C;AAC3C,oEAA8D;AAC9D,+DAA0D;AAC1D,2EAAiE;AAEjE,gDAA8C;AAGvC,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;IAAvB;QAUO,sBAAiB,GAAG,KAAK,CAAC,CAAC,aAAa;QACxC,sBAAiB,GAAG,GAAG,CAAC,CAAC,SAAS;QAEzB,eAAU,GAAG,IAAI,8CAAkB,EAAU,CAAC;IAyCrE,CAAC;IAvCG,yBAAyB,CAAC,IAAY,EAAE,QAAuE;QAC3G,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,CAAC,MAAkC;QACtC,MAAM,YAAY,GAAG,IAAI,kBAAM,CAAC,MAAM,EAAE;YACpC,YAAY,EAAE,IAAI,CAAC,iBAAiB;YACpC,WAAW,EAAE,IAAI,CAAC,iBAAiB,GAAG,CAAC;YACvC,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;SAC5C,CAAC,CAAC;QACH,uCAAuC;QACvC,YAAY,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,YAAY,EAAE,KAAK,EAAC,MAAM,EAAC,EAAE;YAClD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;YAC/B,+DAA+D;YAC/D,wEAAwE;YACxE,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,CAAW,CAAC;YACjE,IAAI,MAAM,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC1C,MAAM,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;gBACpC,IAAI,CAAC,iBAAiB,CAAC,qBAAqB,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACzE,CAAC;iBAAM,CAAC;gBACJ,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YAC5B,CAAC;QACL,CAAC,CAAC,CAAC;IACP,CAAC;IAES,KAAK,CAAC,YAAY,CAAC,OAA6B;QACtD,IAAI,CAAC;YACD,OAAO,IAAI,CAAC,kBAAkB,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAC3D,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,OAAO,KAAK,CAAC;QACjB,CAAC;IACL,CAAC;IAES,KAAK,CAAC,gBAAgB,CAAC,MAAc;QAC3C,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;QACjC,IAAI,QAAQ,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC;YACvD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,yCAAyC,GAAG,QAAQ,CAAC,CAAC;QAC5E,CAAC;IACL,CAAC;CACJ,CAAA;AAtDY,8CAAiB;AAEP;IADlB,IAAA,kBAAM,EAAC,0CAAkB,CAAC;sCACY,0CAAkB;6DAAC;AAGvC;IADlB,IAAA,kBAAM,EAAC,uCAAiB,CAAC;sCACY,uCAAiB;4DAAC;AAGrC;IADlB,IAAA,kBAAM,EAAC,gBAAO,CAAC;IAAE,IAAA,iBAAK,EAAC,wBAAwB,CAAC;;iDACd;4BAR1B,iBAAiB;IAD7B,IAAA,sBAAU,GAAE;GACA,iBAAiB,CAsD7B"}
1
+ {"version":3,"file":"websocket-endpoint.js","sourceRoot":"","sources":["../../../src/node/messaging/websocket-endpoint.ts"],"names":[],"mappings":"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"}
@@ -14,10 +14,29 @@
14
14
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  ********************************************************************************/
16
16
  import { RequestConfiguration, RequestContext, RequestOptions, RequestService } from '@theia/request';
17
+ import { ContributionProvider, MaybePromise } from '../../common';
18
+ export declare const BackendRequestAllowedContribution: unique symbol;
19
+ export interface BackendRequestAllowedContribution {
20
+ /**
21
+ * Returns URL patterns that should be allowed through the backend request facade.
22
+ * Patterns are matched against request URLs.
23
+ *
24
+ * Supports:
25
+ * - Exact base URLs: `https://open-vsx.org` (allows any path under this origin)
26
+ * - Wildcard subdomains: `https://*.github.com` (allows any subdomain)
27
+ *
28
+ * Only `http:` and `https:` schemes are permitted.
29
+ */
30
+ getAllowedUrlPatterns(): MaybePromise<string[]>;
31
+ }
32
+ export declare function isUrlAllowed(url: string, allowedPatterns: string[]): boolean;
17
33
  export declare class BackendRequestFacade implements RequestService {
18
34
  protected readonly requestService: RequestService;
35
+ protected readonly allowedContributions?: ContributionProvider<BackendRequestAllowedContribution>;
36
+ protected cachedAllowedPatterns: string[] | undefined;
19
37
  configure(config: RequestConfiguration): Promise<void>;
20
38
  request(options: RequestOptions): Promise<RequestContext>;
21
39
  resolveProxy(url: string): Promise<string | undefined>;
40
+ protected getAllowedPatterns(): Promise<string[]>;
22
41
  }
23
42
  //# sourceMappingURL=backend-request-facade.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"backend-request-facade.d.ts","sourceRoot":"","sources":["../../../src/node/request/backend-request-facade.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;kFAckF;AAGlF,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEtG,qBACa,oBAAqB,YAAW,cAAc;IAGvD,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IAElD,SAAS,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhD,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;IAK/D,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;CAIzD"}
1
+ {"version":3,"file":"backend-request-facade.d.ts","sourceRoot":"","sources":["../../../src/node/request/backend-request-facade.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;kFAckF;AAGlF,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACtG,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAGlE,eAAO,MAAM,iCAAiC,eAA8C,CAAC;AAC7F,MAAM,WAAW,iCAAiC;IAC9C;;;;;;;;;OASG;IACH,qBAAqB,IAAI,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC;CACnD;AAID,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,OAAO,CAgB5E;AA4CD,qBACa,oBAAqB,YAAW,cAAc;IAGvD,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IAGlD,SAAS,CAAC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC,iCAAiC,CAAC,CAAC;IAElG,SAAS,CAAC,qBAAqB,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAEhD,SAAS,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAMtD,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;IAU/D,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;cAItC,kBAAkB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;CAc1D"}
@@ -15,27 +15,117 @@
15
15
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16
16
  ********************************************************************************/
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.BackendRequestFacade = void 0;
18
+ exports.BackendRequestFacade = exports.BackendRequestAllowedContribution = void 0;
19
+ exports.isUrlAllowed = isUrlAllowed;
19
20
  const tslib_1 = require("tslib");
20
21
  const inversify_1 = require("inversify");
21
22
  const request_1 = require("@theia/request");
23
+ const common_1 = require("../../common");
24
+ const backend_application_config_provider_1 = require("../backend-application-config-provider");
25
+ exports.BackendRequestAllowedContribution = Symbol('BackendRequestAllowedContribution');
26
+ const ALLOWED_SCHEMES = new Set(['http:', 'https:']);
27
+ function isUrlAllowed(url, allowedPatterns) {
28
+ let parsed;
29
+ try {
30
+ parsed = new URL(url);
31
+ }
32
+ catch {
33
+ return false;
34
+ }
35
+ if (!ALLOWED_SCHEMES.has(parsed.protocol)) {
36
+ return false;
37
+ }
38
+ for (const pattern of allowedPatterns) {
39
+ if (matchesPattern(parsed, pattern)) {
40
+ return true;
41
+ }
42
+ }
43
+ return false;
44
+ }
45
+ function matchesPattern(target, pattern) {
46
+ let patternUrl;
47
+ try {
48
+ patternUrl = new URL(pattern);
49
+ }
50
+ catch {
51
+ return false;
52
+ }
53
+ if (!ALLOWED_SCHEMES.has(patternUrl.protocol)) {
54
+ return false;
55
+ }
56
+ if (target.protocol !== patternUrl.protocol) {
57
+ return false;
58
+ }
59
+ const targetPort = getEffectivePort(target);
60
+ const patternPort = getEffectivePort(patternUrl);
61
+ if (targetPort !== patternPort) {
62
+ return false;
63
+ }
64
+ return matchesHost(target.hostname, patternUrl.hostname);
65
+ }
66
+ function getEffectivePort(url) {
67
+ if (url.port) {
68
+ return url.port;
69
+ }
70
+ if (url.protocol === 'https:') {
71
+ return '443';
72
+ }
73
+ if (url.protocol === 'http:') {
74
+ return '80';
75
+ }
76
+ return '';
77
+ }
78
+ function matchesHost(targetHost, patternHost) {
79
+ if (patternHost.startsWith('*.')) {
80
+ const suffix = patternHost.substring(1); // e.g. ".example.com"
81
+ return targetHost.endsWith(suffix) && targetHost.length > suffix.length;
82
+ }
83
+ return targetHost === patternHost;
84
+ }
22
85
  let BackendRequestFacade = class BackendRequestFacade {
23
- configure(config) {
24
- return this.requestService.configure(config);
86
+ async configure(config) {
87
+ if (backend_application_config_provider_1.BackendApplicationConfigProvider.get().configureProxyFromPreferences) {
88
+ return this.requestService.configure(config);
89
+ }
25
90
  }
26
91
  async request(options) {
92
+ const patterns = await this.getAllowedPatterns();
93
+ const url = options.url;
94
+ if (!url || !isUrlAllowed(url, patterns)) {
95
+ throw new Error(`Request to URL '${url}' is not allowed. The URL does not match any allowed pattern.`);
96
+ }
27
97
  const context = await this.requestService.request(options);
28
98
  return request_1.RequestContext.compress(context);
29
99
  }
30
100
  resolveProxy(url) {
31
101
  return this.requestService.resolveProxy(url);
32
102
  }
103
+ async getAllowedPatterns() {
104
+ if (this.cachedAllowedPatterns) {
105
+ return this.cachedAllowedPatterns;
106
+ }
107
+ const patterns = [];
108
+ if (this.allowedContributions) {
109
+ for (const contribution of this.allowedContributions.getContributions()) {
110
+ const contributed = await contribution.getAllowedUrlPatterns();
111
+ patterns.push(...contributed);
112
+ }
113
+ }
114
+ this.cachedAllowedPatterns = patterns;
115
+ return patterns;
116
+ }
33
117
  };
34
118
  exports.BackendRequestFacade = BackendRequestFacade;
35
119
  tslib_1.__decorate([
36
120
  (0, inversify_1.inject)(request_1.RequestService),
37
121
  tslib_1.__metadata("design:type", Object)
38
122
  ], BackendRequestFacade.prototype, "requestService", void 0);
123
+ tslib_1.__decorate([
124
+ (0, inversify_1.inject)(common_1.ContributionProvider),
125
+ (0, inversify_1.named)(exports.BackendRequestAllowedContribution),
126
+ (0, inversify_1.optional)(),
127
+ tslib_1.__metadata("design:type", Object)
128
+ ], BackendRequestFacade.prototype, "allowedContributions", void 0);
39
129
  exports.BackendRequestFacade = BackendRequestFacade = tslib_1.__decorate([
40
130
  (0, inversify_1.injectable)()
41
131
  ], BackendRequestFacade);
@@ -1 +1 @@
1
- {"version":3,"file":"backend-request-facade.js","sourceRoot":"","sources":["../../../src/node/request/backend-request-facade.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;kFAckF;;;;AAElF,yCAA+C;AAC/C,4CAAsG;AAG/F,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;IAK7B,SAAS,CAAC,MAA4B;QAClC,OAAO,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAuB;QACjC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC3D,OAAO,wBAAc,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC5C,CAAC;IAED,YAAY,CAAC,GAAW;QACpB,OAAO,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IACjD,CAAC;CAEJ,CAAA;AAlBY,oDAAoB;AAGV;IADlB,IAAA,kBAAM,EAAC,wBAAc,CAAC;;4DAC2B;+BAHzC,oBAAoB;IADhC,IAAA,sBAAU,GAAE;GACA,oBAAoB,CAkBhC"}
1
+ {"version":3,"file":"backend-request-facade.js","sourceRoot":"","sources":["../../../src/node/request/backend-request-facade.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;kFAckF;;;AAwBlF,oCAgBC;;AAtCD,yCAAgE;AAChE,4CAAsG;AACtG,yCAAkE;AAClE,gGAA0F;AAE7E,QAAA,iCAAiC,GAAG,MAAM,CAAC,mCAAmC,CAAC,CAAC;AAe7F,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;AAErD,SAAgB,YAAY,CAAC,GAAW,EAAE,eAAyB;IAC/D,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACD,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxC,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,KAAK,MAAM,OAAO,IAAI,eAAe,EAAE,CAAC;QACpC,IAAI,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;YAClC,OAAO,IAAI,CAAC;QAChB,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,SAAS,cAAc,CAAC,MAAW,EAAE,OAAe;IAChD,IAAI,UAAe,CAAC;IACpB,IAAI,CAAC;QACD,UAAU,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5C,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,KAAK,UAAU,CAAC,QAAQ,EAAE,CAAC;QAC1C,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,MAAM,UAAU,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,WAAW,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IACjD,IAAI,UAAU,KAAK,WAAW,EAAE,CAAC;QAC7B,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,OAAO,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;AAC7D,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAQ;IAC9B,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;QACX,OAAO,GAAG,CAAC,IAAI,CAAC;IACpB,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,OAAO,EAAE,CAAC;AACd,CAAC;AAED,SAAS,WAAW,CAAC,UAAkB,EAAE,WAAmB;IACxD,IAAI,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,sBAAsB;QAC/D,OAAO,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAC5E,CAAC;IACD,OAAO,UAAU,KAAK,WAAW,CAAC;AACtC,CAAC;AAGM,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;IAU7B,KAAK,CAAC,SAAS,CAAC,MAA4B;QACxC,IAAI,sEAAgC,CAAC,GAAG,EAAE,CAAC,6BAA6B,EAAE,CAAC;YACvE,OAAO,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACjD,CAAC;IACL,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAuB;QACjC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACjD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACxB,IAAI,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,mBAAmB,GAAG,+DAA+D,CAAC,CAAC;QAC3G,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC3D,OAAO,wBAAc,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC5C,CAAC;IAED,YAAY,CAAC,GAAW;QACpB,OAAO,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IACjD,CAAC;IAES,KAAK,CAAC,kBAAkB;QAC9B,IAAI,IAAI,CAAC,qBAAqB,EAAE,CAAC;YAC7B,OAAO,IAAI,CAAC,qBAAqB,CAAC;QACtC,CAAC;QACD,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC5B,KAAK,MAAM,YAAY,IAAI,IAAI,CAAC,oBAAoB,CAAC,gBAAgB,EAAE,EAAE,CAAC;gBACtE,MAAM,WAAW,GAAG,MAAM,YAAY,CAAC,qBAAqB,EAAE,CAAC;gBAC/D,QAAQ,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC;YAClC,CAAC;QACL,CAAC;QACD,IAAI,CAAC,qBAAqB,GAAG,QAAQ,CAAC;QACtC,OAAO,QAAQ,CAAC;IACpB,CAAC;CACJ,CAAA;AA5CY,oDAAoB;AAGV;IADlB,IAAA,kBAAM,EAAC,wBAAc,CAAC;;4DAC2B;AAG/B;IADlB,IAAA,kBAAM,EAAC,6BAAoB,CAAC;IAAE,IAAA,iBAAK,EAAC,yCAAiC,CAAC;IAAE,IAAA,oBAAQ,GAAE;;kEACe;+BANzF,oBAAoB;IADhC,IAAA,sBAAU,GAAE;GACA,oBAAoB,CA4ChC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=backend-request-facade.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend-request-facade.spec.d.ts","sourceRoot":"","sources":["../../../src/node/request/backend-request-facade.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+ // *****************************************************************************
3
+ // Copyright (C) 2026 EclipseSource GmbH and others.
4
+ //
5
+ // This program and the accompanying materials are made available under the
6
+ // terms of the Eclipse Public License v. 2.0 which is available at
7
+ // http://www.eclipse.org/legal/epl-2.0.
8
+ //
9
+ // This Source Code may also be made available under the following Secondary
10
+ // Licenses when the conditions for such availability set forth in the Eclipse
11
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
12
+ // with the GNU Classpath Exception which is available at
13
+ // https://www.gnu.org/software/classpath/license.html.
14
+ //
15
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16
+ // *****************************************************************************
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ const chai_1 = require("chai");
19
+ const sinon = require("sinon");
20
+ const backend_request_facade_1 = require("./backend-request-facade");
21
+ const backend_application_config_provider_1 = require("../backend-application-config-provider");
22
+ describe('isUrlAllowed', () => {
23
+ it('should allow a URL that matches an exact origin pattern', () => {
24
+ const patterns = ['https://open-vsx.org'];
25
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('https://open-vsx.org/api/extensions', patterns)).to.be.true;
26
+ });
27
+ it('should allow a URL with a path when pattern has no path', () => {
28
+ const patterns = ['https://example.com'];
29
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('https://example.com/some/deep/path?query=1', patterns)).to.be.true;
30
+ });
31
+ it('should allow a URL that exactly matches the origin', () => {
32
+ const patterns = ['https://example.com'];
33
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('https://example.com', patterns)).to.be.true;
34
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('https://example.com/', patterns)).to.be.true;
35
+ });
36
+ it('should reject a URL with a different scheme', () => {
37
+ const patterns = ['https://example.com'];
38
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('http://example.com/path', patterns)).to.be.false;
39
+ });
40
+ it('should reject a URL with a different host', () => {
41
+ const patterns = ['https://example.com'];
42
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('https://evil.com/path', patterns)).to.be.false;
43
+ });
44
+ it('should reject a URL with a different port', () => {
45
+ const patterns = ['https://example.com'];
46
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('https://example.com:8443/path', patterns)).to.be.false;
47
+ });
48
+ it('should allow a URL when port matches explicitly', () => {
49
+ const patterns = ['https://example.com:8443'];
50
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('https://example.com:8443/path', patterns)).to.be.true;
51
+ });
52
+ it('should treat default ports as equivalent', () => {
53
+ const patterns = ['https://example.com:443'];
54
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('https://example.com/path', patterns)).to.be.true;
55
+ const httpPatterns = ['http://example.com:80'];
56
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('http://example.com/path', httpPatterns)).to.be.true;
57
+ const implicitPatterns = ['http://example.com'];
58
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('http://example.com:80/path', implicitPatterns)).to.be.true;
59
+ });
60
+ it('should match wildcard subdomains', () => {
61
+ const patterns = ['https://*.example.com'];
62
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('https://foo.example.com/path', patterns)).to.be.true;
63
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('https://bar.baz.example.com/path', patterns)).to.be.true;
64
+ });
65
+ it('should not match the bare domain with a wildcard subdomain pattern', () => {
66
+ const patterns = ['https://*.example.com'];
67
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('https://example.com/path', patterns)).to.be.false;
68
+ });
69
+ it('should reject non-http(s) schemes', () => {
70
+ const patterns = ['file:///etc/passwd'];
71
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('file:///etc/passwd', patterns)).to.be.false;
72
+ });
73
+ it('should reject ftp scheme', () => {
74
+ const patterns = ['ftp://files.example.com'];
75
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('ftp://files.example.com/data', patterns)).to.be.false;
76
+ });
77
+ it('should reject a URL when target uses non-http(s) scheme even if patterns exist', () => {
78
+ const patterns = ['https://example.com'];
79
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('file:///etc/passwd', patterns)).to.be.false;
80
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('ftp://example.com/data', patterns)).to.be.false;
81
+ });
82
+ it('should reject all URLs when allowlist is empty', () => {
83
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('https://example.com', [])).to.be.false;
84
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('http://localhost:3000', [])).to.be.false;
85
+ });
86
+ it('should reject invalid URLs', () => {
87
+ const patterns = ['https://example.com'];
88
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('not a url', patterns)).to.be.false;
89
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('', patterns)).to.be.false;
90
+ });
91
+ it('should allow private IPs only when explicitly in the allowlist', () => {
92
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('http://127.0.0.1:8080/secret', [])).to.be.false;
93
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('http://127.0.0.1:8080/secret', ['https://example.com'])).to.be.false;
94
+ const patternsWithLoopback = ['http://127.0.0.1:8080'];
95
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('http://127.0.0.1:8080/secret', patternsWithLoopback)).to.be.true;
96
+ });
97
+ it('should reject cloud metadata endpoint by default', () => {
98
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('http://169.254.169.254/latest/meta-data/', [])).to.be.false;
99
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('http://169.254.169.254/latest/meta-data/', ['https://example.com'])).to.be.false;
100
+ });
101
+ it('should merge multiple patterns correctly', () => {
102
+ const patterns = [
103
+ 'https://open-vsx.org',
104
+ 'https://marketplace.example.com',
105
+ 'https://*.cdn.example.com'
106
+ ];
107
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('https://open-vsx.org/api/v2/extensions', patterns)).to.be.true;
108
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('https://marketplace.example.com/download', patterns)).to.be.true;
109
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('https://files.cdn.example.com/ext.vsix', patterns)).to.be.true;
110
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('https://evil.com/malware', patterns)).to.be.false;
111
+ });
112
+ it('should handle patterns with trailing slashes', () => {
113
+ const patterns = ['https://example.com/'];
114
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('https://example.com/path', patterns)).to.be.true;
115
+ });
116
+ it('should handle invalid patterns gracefully', () => {
117
+ const patterns = ['not a valid pattern', 'https://example.com'];
118
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('https://example.com/path', patterns)).to.be.true;
119
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('https://other.com/path', patterns)).to.be.false;
120
+ });
121
+ it('should prevent host spoofing via subdomain prefix', () => {
122
+ const patterns = ['https://example.com'];
123
+ (0, chai_1.expect)((0, backend_request_facade_1.isUrlAllowed)('https://example.com.evil.com/path', patterns)).to.be.false;
124
+ });
125
+ });
126
+ describe('BackendRequestFacade', () => {
127
+ describe('configure', () => {
128
+ let configProviderStub;
129
+ beforeEach(() => {
130
+ configProviderStub = sinon.stub(backend_application_config_provider_1.BackendApplicationConfigProvider, 'get');
131
+ });
132
+ afterEach(() => {
133
+ configProviderStub.restore();
134
+ });
135
+ it('should be a no-op when configureProxyFromPreferences is false', async () => {
136
+ configProviderStub.returns({
137
+ singleInstance: true,
138
+ frontendConnectionTimeout: 0,
139
+ configurationFolder: '.theia',
140
+ configureProxyFromPreferences: false
141
+ });
142
+ const facade = new backend_request_facade_1.BackendRequestFacade();
143
+ const configureStub = sinon.stub().resolves();
144
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
145
+ facade.requestService = {
146
+ configure: configureStub
147
+ };
148
+ await facade.configure({ proxyUrl: 'http://evil.com', strictSSL: false });
149
+ (0, chai_1.expect)(configureStub.called).to.be.false;
150
+ });
151
+ it('should pass through to the underlying request service when configureProxyFromPreferences is true', async () => {
152
+ configProviderStub.returns({
153
+ singleInstance: true,
154
+ frontendConnectionTimeout: 0,
155
+ configurationFolder: '.theia',
156
+ configureProxyFromPreferences: true
157
+ });
158
+ const facade = new backend_request_facade_1.BackendRequestFacade();
159
+ const configureStub = sinon.stub().resolves();
160
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
161
+ facade.requestService = {
162
+ configure: configureStub
163
+ };
164
+ const config = { proxyUrl: 'http://my-proxy.com:8080', strictSSL: true, proxyAuthorization: 'Bearer token' };
165
+ await facade.configure(config);
166
+ (0, chai_1.expect)(configureStub.calledOnce).to.be.true;
167
+ (0, chai_1.expect)(configureStub.firstCall.args[0]).to.deep.equal(config);
168
+ });
169
+ });
170
+ });
171
+ //# sourceMappingURL=backend-request-facade.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend-request-facade.spec.js","sourceRoot":"","sources":["../../../src/node/request/backend-request-facade.spec.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theia/core",
3
- "version": "1.73.0-next.43+39d328622",
3
+ "version": "1.73.0-next.52+637df8980",
4
4
  "description": "Theia is a cloud & desktop IDE framework implemented in TypeScript.",
5
5
  "main": "lib/common/index.js",
6
6
  "typings": "lib/common/index.d.ts",
@@ -17,8 +17,8 @@
17
17
  "@lumino/virtualdom": "^2.0.4",
18
18
  "@lumino/widgets": "2.7.5",
19
19
  "@parcel/watcher": "^2.5.6",
20
- "@theia/application-package": "1.73.0-next.43+39d328622",
21
- "@theia/request": "1.73.0-next.43+39d328622",
20
+ "@theia/application-package": "1.73.0-next.52+637df8980",
21
+ "@theia/request": "1.73.0-next.52+637df8980",
22
22
  "@types/body-parser": "^1.19.6",
23
23
  "@types/express": "^4.17.25",
24
24
  "@types/fs-extra": "^4.0.15",
@@ -230,5 +230,5 @@
230
230
  "nyc": {
231
231
  "extends": "../../configs/nyc.json"
232
232
  },
233
- "gitHead": "39d328622a0c2226daec3d331dfc18dd5c3eebde"
233
+ "gitHead": "637df89808957b3106f6de26237c250f6d599cdc"
234
234
  }
@@ -208,12 +208,7 @@ export class WebSocketConnectionSource implements ConnectionSource {
208
208
  reconnection: true,
209
209
  reconnectionDelay: 1000,
210
210
  reconnectionDelayMax: 10000,
211
- reconnectionAttempts: Infinity,
212
- extraHeaders: {
213
- // Socket.io strips the `origin` header
214
- // We need to provide our own for validation
215
- 'fix-origin': window.location.origin
216
- }
211
+ reconnectionAttempts: Infinity
217
212
  });
218
213
  }
219
214
 
@@ -0,0 +1,80 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2026 EclipseSource and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { enableJSDOM } from '../test/jsdom';
18
+
19
+ // The widget module transitively imports `@lumino/widgets`, which touches `document` at load time.
20
+ const disableJSDOM = enableJSDOM();
21
+
22
+ import { Container } from 'inversify';
23
+ import { expect } from 'chai';
24
+ import { ReactElement } from 'react';
25
+ import { CommandService } from '../../common';
26
+ import { LabelParser } from '../label-parser';
27
+ import { codicon } from '../widgets';
28
+ import { TreeViewWelcomeWidget } from './tree-view-welcome-widget';
29
+
30
+ disableJSDOM();
31
+
32
+ let labelParser: LabelParser;
33
+
34
+ before(() => {
35
+ const container = new Container();
36
+ container.bind(LabelParser).toSelf().inSingletonScope();
37
+ container.bind(CommandService).toDynamicValue(() => ({
38
+ executeCommand<T>(): Promise<T | undefined> {
39
+ return Promise.resolve(undefined);
40
+ }
41
+ })).inSingletonScope();
42
+ labelParser = container.get(LabelParser);
43
+ });
44
+
45
+ describe('TreeViewWelcomeWidget#renderLabelWithIcons', () => {
46
+
47
+ // Exercise the protected helper without standing up the full TreeWidget DI graph.
48
+ function render(label: string): ReactElement[] {
49
+ const widget = Object.create(TreeViewWelcomeWidget.prototype) as {
50
+ labelParser: LabelParser;
51
+ renderLabelWithIcons(label: string): ReactElement[];
52
+ };
53
+ widget.labelParser = labelParser;
54
+ return widget.renderLabelWithIcons(label);
55
+ }
56
+
57
+ it('renders a leading $(codicon) as a codicon span and keeps the trailing text', () => {
58
+ const nodes = render('$(robot) Launch AI Agent');
59
+ expect(nodes).to.have.lengthOf(2);
60
+ expect(nodes[0].props.className).to.equal(codicon('robot'));
61
+ expect(nodes[0].props.children).to.be.undefined;
62
+ expect(nodes[1].props.className).to.be.undefined;
63
+ expect(nodes[1].props.children).to.equal(' Launch AI Agent');
64
+ });
65
+
66
+ it('renders a plain label as a single text span with no codicon', () => {
67
+ const nodes = render('Open Documentation');
68
+ expect(nodes).to.have.lengthOf(1);
69
+ expect(nodes[0].props.className).to.be.undefined;
70
+ expect(nodes[0].props.children).to.equal('Open Documentation');
71
+ });
72
+
73
+ it('renders multiple codicons interleaved with text', () => {
74
+ const nodes = render('$(package) Import $(gear) Library');
75
+ const iconNodes = nodes.filter(n => typeof n.props.className === 'string' && n.props.className.includes('codicon-'));
76
+ expect(iconNodes).to.have.lengthOf(2);
77
+ expect(iconNodes[0].props.className).to.equal(codicon('package'));
78
+ expect(iconNodes[1].props.className).to.equal(codicon('gear'));
79
+ });
80
+ });