@theia/core 1.73.0-next.40 → 1.73.0-next.51

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 (84) hide show
  1. package/README.md +1 -1
  2. package/lib/browser/catalog.json +23 -6
  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/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.js +2 -2
  7. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.js.map +1 -1
  8. package/lib/browser/tree/tree-view-welcome-widget.d.ts +1 -0
  9. package/lib/browser/tree/tree-view-welcome-widget.d.ts.map +1 -1
  10. package/lib/browser/tree/tree-view-welcome-widget.js +8 -6
  11. package/lib/browser/tree/tree-view-welcome-widget.js.map +1 -1
  12. package/lib/browser/tree/tree-view-welcome-widget.spec.d.ts +2 -0
  13. package/lib/browser/tree/tree-view-welcome-widget.spec.d.ts.map +1 -0
  14. package/lib/browser/tree/tree-view-welcome-widget.spec.js +68 -0
  15. package/lib/browser/tree/tree-view-welcome-widget.spec.js.map +1 -0
  16. package/lib/electron-node/hosting/electron-ws-origin-validator.d.ts.map +1 -1
  17. package/lib/electron-node/hosting/electron-ws-origin-validator.js +5 -2
  18. package/lib/electron-node/hosting/electron-ws-origin-validator.js.map +1 -1
  19. package/lib/electron-node/hosting/electron-ws-origin-validator.spec.d.ts +2 -0
  20. package/lib/electron-node/hosting/electron-ws-origin-validator.spec.d.ts.map +1 -0
  21. package/lib/electron-node/hosting/electron-ws-origin-validator.spec.js +59 -0
  22. package/lib/electron-node/hosting/electron-ws-origin-validator.spec.js.map +1 -0
  23. package/lib/node/backend-application-module.d.ts.map +1 -1
  24. package/lib/node/backend-application-module.js +2 -0
  25. package/lib/node/backend-application-module.js.map +1 -1
  26. package/lib/node/backend-application.d.ts +9 -0
  27. package/lib/node/backend-application.d.ts.map +1 -1
  28. package/lib/node/backend-application.js +23 -1
  29. package/lib/node/backend-application.js.map +1 -1
  30. package/lib/node/backend-application.spec.js +1 -0
  31. package/lib/node/backend-application.spec.js.map +1 -1
  32. package/lib/node/hosting/backend-hosting-module.d.ts.map +1 -1
  33. package/lib/node/hosting/backend-hosting-module.js +7 -0
  34. package/lib/node/hosting/backend-hosting-module.js.map +1 -1
  35. package/lib/node/hosting/browser-connection-token.d.ts +46 -0
  36. package/lib/node/hosting/browser-connection-token.d.ts.map +1 -0
  37. package/lib/node/hosting/browser-connection-token.js +120 -0
  38. package/lib/node/hosting/browser-connection-token.js.map +1 -0
  39. package/lib/node/hosting/browser-connection-token.spec.d.ts +2 -0
  40. package/lib/node/hosting/browser-connection-token.spec.d.ts.map +1 -0
  41. package/lib/node/hosting/browser-connection-token.spec.js +128 -0
  42. package/lib/node/hosting/browser-connection-token.spec.js.map +1 -0
  43. package/lib/node/hosting/ws-origin-validator.d.ts.map +1 -1
  44. package/lib/node/hosting/ws-origin-validator.js +21 -4
  45. package/lib/node/hosting/ws-origin-validator.js.map +1 -1
  46. package/lib/node/hosting/ws-origin-validator.spec.d.ts +2 -0
  47. package/lib/node/hosting/ws-origin-validator.spec.d.ts.map +1 -0
  48. package/lib/node/hosting/ws-origin-validator.spec.js +131 -0
  49. package/lib/node/hosting/ws-origin-validator.spec.js.map +1 -0
  50. package/lib/node/index.d.ts +1 -0
  51. package/lib/node/index.d.ts.map +1 -1
  52. package/lib/node/index.js +3 -1
  53. package/lib/node/index.js.map +1 -1
  54. package/lib/node/messaging/websocket-endpoint.d.ts +5 -0
  55. package/lib/node/messaging/websocket-endpoint.d.ts.map +1 -1
  56. package/lib/node/messaging/websocket-endpoint.js +14 -5
  57. package/lib/node/messaging/websocket-endpoint.js.map +1 -1
  58. package/lib/node/request/backend-request-facade.d.ts +19 -0
  59. package/lib/node/request/backend-request-facade.d.ts.map +1 -1
  60. package/lib/node/request/backend-request-facade.js +93 -3
  61. package/lib/node/request/backend-request-facade.js.map +1 -1
  62. package/lib/node/request/backend-request-facade.spec.d.ts +2 -0
  63. package/lib/node/request/backend-request-facade.spec.d.ts.map +1 -0
  64. package/lib/node/request/backend-request-facade.spec.js +171 -0
  65. package/lib/node/request/backend-request-facade.spec.js.map +1 -0
  66. package/package.json +5 -6
  67. package/src/browser/messaging/ws-connection-source.ts +1 -6
  68. package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.tsx +2 -2
  69. package/src/browser/tree/tree-view-welcome-widget.spec.ts +80 -0
  70. package/src/browser/tree/tree-view-welcome-widget.tsx +10 -11
  71. package/src/electron-node/hosting/electron-ws-origin-validator.spec.ts +69 -0
  72. package/src/electron-node/hosting/electron-ws-origin-validator.ts +5 -2
  73. package/src/node/backend-application-module.ts +4 -2
  74. package/src/node/backend-application.spec.ts +2 -0
  75. package/src/node/backend-application.ts +18 -0
  76. package/src/node/hosting/backend-hosting-module.ts +10 -0
  77. package/src/node/hosting/browser-connection-token.spec.ts +167 -0
  78. package/src/node/hosting/browser-connection-token.ts +126 -0
  79. package/src/node/hosting/ws-origin-validator.spec.ts +193 -0
  80. package/src/node/hosting/ws-origin-validator.ts +23 -4
  81. package/src/node/index.ts +1 -0
  82. package/src/node/messaging/websocket-endpoint.ts +17 -5
  83. package/src/node/request/backend-request-facade.spec.ts +203 -0
  84. package/src/node/request/backend-request-facade.ts +108 -3
@@ -14,8 +14,87 @@
14
14
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  ********************************************************************************/
16
16
 
17
- import { inject, injectable } from 'inversify';
17
+ import { inject, injectable, named, optional } from 'inversify';
18
18
  import { RequestConfiguration, RequestContext, RequestOptions, RequestService } from '@theia/request';
19
+ import { ContributionProvider, MaybePromise } from '../../common';
20
+ import { BackendApplicationConfigProvider } from '../backend-application-config-provider';
21
+
22
+ export const BackendRequestAllowedContribution = Symbol('BackendRequestAllowedContribution');
23
+ export interface BackendRequestAllowedContribution {
24
+ /**
25
+ * Returns URL patterns that should be allowed through the backend request facade.
26
+ * Patterns are matched against request URLs.
27
+ *
28
+ * Supports:
29
+ * - Exact base URLs: `https://open-vsx.org` (allows any path under this origin)
30
+ * - Wildcard subdomains: `https://*.github.com` (allows any subdomain)
31
+ *
32
+ * Only `http:` and `https:` schemes are permitted.
33
+ */
34
+ getAllowedUrlPatterns(): MaybePromise<string[]>;
35
+ }
36
+
37
+ const ALLOWED_SCHEMES = new Set(['http:', 'https:']);
38
+
39
+ export function isUrlAllowed(url: string, allowedPatterns: string[]): boolean {
40
+ let parsed: URL;
41
+ try {
42
+ parsed = new URL(url);
43
+ } catch {
44
+ return false;
45
+ }
46
+ if (!ALLOWED_SCHEMES.has(parsed.protocol)) {
47
+ return false;
48
+ }
49
+ for (const pattern of allowedPatterns) {
50
+ if (matchesPattern(parsed, pattern)) {
51
+ return true;
52
+ }
53
+ }
54
+ return false;
55
+ }
56
+
57
+ function matchesPattern(target: URL, pattern: string): boolean {
58
+ let patternUrl: URL;
59
+ try {
60
+ patternUrl = new URL(pattern);
61
+ } catch {
62
+ return false;
63
+ }
64
+ if (!ALLOWED_SCHEMES.has(patternUrl.protocol)) {
65
+ return false;
66
+ }
67
+ if (target.protocol !== patternUrl.protocol) {
68
+ return false;
69
+ }
70
+ const targetPort = getEffectivePort(target);
71
+ const patternPort = getEffectivePort(patternUrl);
72
+ if (targetPort !== patternPort) {
73
+ return false;
74
+ }
75
+ return matchesHost(target.hostname, patternUrl.hostname);
76
+ }
77
+
78
+ function getEffectivePort(url: URL): string {
79
+ if (url.port) {
80
+ return url.port;
81
+ }
82
+ if (url.protocol === 'https:') {
83
+ return '443';
84
+ }
85
+ if (url.protocol === 'http:') {
86
+ return '80';
87
+ }
88
+ return '';
89
+ }
90
+
91
+ function matchesHost(targetHost: string, patternHost: string): boolean {
92
+ if (patternHost.startsWith('*.')) {
93
+ const suffix = patternHost.substring(1); // e.g. ".example.com"
94
+ return targetHost.endsWith(suffix) && targetHost.length > suffix.length;
95
+ }
96
+ return targetHost === patternHost;
97
+ }
19
98
 
20
99
  @injectable()
21
100
  export class BackendRequestFacade implements RequestService {
@@ -23,11 +102,23 @@ export class BackendRequestFacade implements RequestService {
23
102
  @inject(RequestService)
24
103
  protected readonly requestService: RequestService;
25
104
 
26
- configure(config: RequestConfiguration): Promise<void> {
27
- return this.requestService.configure(config);
105
+ @inject(ContributionProvider) @named(BackendRequestAllowedContribution) @optional()
106
+ protected readonly allowedContributions?: ContributionProvider<BackendRequestAllowedContribution>;
107
+
108
+ protected cachedAllowedPatterns: string[] | undefined;
109
+
110
+ async configure(config: RequestConfiguration): Promise<void> {
111
+ if (BackendApplicationConfigProvider.get().configureProxyFromPreferences) {
112
+ return this.requestService.configure(config);
113
+ }
28
114
  }
29
115
 
30
116
  async request(options: RequestOptions): Promise<RequestContext> {
117
+ const patterns = await this.getAllowedPatterns();
118
+ const url = options.url;
119
+ if (!url || !isUrlAllowed(url, patterns)) {
120
+ throw new Error(`Request to URL '${url}' is not allowed. The URL does not match any allowed pattern.`);
121
+ }
31
122
  const context = await this.requestService.request(options);
32
123
  return RequestContext.compress(context);
33
124
  }
@@ -36,4 +127,18 @@ export class BackendRequestFacade implements RequestService {
36
127
  return this.requestService.resolveProxy(url);
37
128
  }
38
129
 
130
+ protected async getAllowedPatterns(): Promise<string[]> {
131
+ if (this.cachedAllowedPatterns) {
132
+ return this.cachedAllowedPatterns;
133
+ }
134
+ const patterns: string[] = [];
135
+ if (this.allowedContributions) {
136
+ for (const contribution of this.allowedContributions.getContributions()) {
137
+ const contributed = await contribution.getAllowedUrlPatterns();
138
+ patterns.push(...contributed);
139
+ }
140
+ }
141
+ this.cachedAllowedPatterns = patterns;
142
+ return patterns;
143
+ }
39
144
  }