@tellescope/sdk 1.255.19 → 1.256.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.
Files changed (82) hide show
  1. package/lib/cjs/tests/api_tests/custom_dashboards.test.d.ts.map +1 -1
  2. package/lib/cjs/tests/api_tests/custom_dashboards.test.js +99 -8
  3. package/lib/cjs/tests/api_tests/custom_dashboards.test.js.map +1 -1
  4. package/lib/cjs/tests/api_tests/default_summary_journey.test.d.ts.map +1 -0
  5. package/lib/cjs/tests/api_tests/default_summary_journey.test.js.map +1 -0
  6. package/lib/cjs/tests/api_tests/file_download_unicode_names.test.d.ts +6 -0
  7. package/lib/cjs/tests/api_tests/file_download_unicode_names.test.d.ts.map +1 -0
  8. package/lib/cjs/tests/api_tests/file_download_unicode_names.test.js +278 -0
  9. package/lib/cjs/tests/api_tests/file_download_unicode_names.test.js.map +1 -0
  10. package/lib/cjs/tests/api_tests/openloop_webhooks.test.d.ts.map +1 -1
  11. package/lib/cjs/tests/api_tests/openloop_webhooks.test.js +212 -33
  12. package/lib/cjs/tests/api_tests/openloop_webhooks.test.js.map +1 -1
  13. package/lib/cjs/tests/api_tests/phone_calls_cold_transfer.test.d.ts.map +1 -1
  14. package/lib/cjs/tests/api_tests/phone_calls_cold_transfer.test.js +85 -9
  15. package/lib/cjs/tests/api_tests/phone_calls_cold_transfer.test.js.map +1 -1
  16. package/lib/cjs/tests/api_tests/security/F-0013-sanitize-user-html-with-iframes.test.d.ts +2 -0
  17. package/lib/cjs/tests/api_tests/security/F-0013-sanitize-user-html-with-iframes.test.d.ts.map +1 -0
  18. package/lib/cjs/tests/api_tests/security/F-0013-sanitize-user-html-with-iframes.test.js +242 -0
  19. package/lib/cjs/tests/api_tests/security/F-0013-sanitize-user-html-with-iframes.test.js.map +1 -0
  20. package/lib/cjs/tests/api_tests/security/F-0015-webhook-outbound-ssrf.test.d.ts +29 -0
  21. package/lib/cjs/tests/api_tests/security/F-0015-webhook-outbound-ssrf.test.d.ts.map +1 -0
  22. package/lib/cjs/tests/api_tests/security/F-0015-webhook-outbound-ssrf.test.js +443 -0
  23. package/lib/cjs/tests/api_tests/security/F-0015-webhook-outbound-ssrf.test.js.map +1 -0
  24. package/lib/cjs/tests/api_tests/security/F-0025-proxy-image-unauth-ssrf.test.d.ts +35 -0
  25. package/lib/cjs/tests/api_tests/security/F-0025-proxy-image-unauth-ssrf.test.d.ts.map +1 -0
  26. package/lib/cjs/tests/api_tests/security/F-0025-proxy-image-unauth-ssrf.test.js +231 -0
  27. package/lib/cjs/tests/api_tests/security/F-0025-proxy-image-unauth-ssrf.test.js.map +1 -0
  28. package/lib/cjs/tests/api_tests/security/F-0166-allowed-paths-wildcard-bypass.test.d.ts.map +1 -1
  29. package/lib/cjs/tests/api_tests/security/F-0166-allowed-paths-wildcard-bypass.test.js +524 -294
  30. package/lib/cjs/tests/api_tests/security/F-0166-allowed-paths-wildcard-bypass.test.js.map +1 -1
  31. package/lib/cjs/tests/tests.d.ts.map +1 -1
  32. package/lib/cjs/tests/tests.js +431 -230
  33. package/lib/cjs/tests/tests.js.map +1 -1
  34. package/lib/esm/enduser.d.ts +0 -1
  35. package/lib/esm/enduser.d.ts.map +1 -1
  36. package/lib/esm/sdk.d.ts +2 -3
  37. package/lib/esm/sdk.d.ts.map +1 -1
  38. package/lib/esm/session.d.ts +0 -1
  39. package/lib/esm/session.d.ts.map +1 -1
  40. package/lib/esm/tests/api_tests/custom_dashboards.test.d.ts.map +1 -1
  41. package/lib/esm/tests/api_tests/custom_dashboards.test.js +99 -8
  42. package/lib/esm/tests/api_tests/custom_dashboards.test.js.map +1 -1
  43. package/lib/esm/tests/api_tests/default_summary_journey.test.d.ts.map +1 -0
  44. package/lib/esm/tests/api_tests/default_summary_journey.test.js.map +1 -0
  45. package/lib/esm/tests/api_tests/file_download_unicode_names.test.d.ts +6 -0
  46. package/lib/esm/tests/api_tests/file_download_unicode_names.test.d.ts.map +1 -0
  47. package/lib/esm/tests/api_tests/file_download_unicode_names.test.js +248 -0
  48. package/lib/esm/tests/api_tests/file_download_unicode_names.test.js.map +1 -0
  49. package/lib/esm/tests/api_tests/openloop_webhooks.test.d.ts.map +1 -1
  50. package/lib/esm/tests/api_tests/openloop_webhooks.test.js +213 -34
  51. package/lib/esm/tests/api_tests/openloop_webhooks.test.js.map +1 -1
  52. package/lib/esm/tests/api_tests/phone_calls_cold_transfer.test.d.ts.map +1 -1
  53. package/lib/esm/tests/api_tests/phone_calls_cold_transfer.test.js +85 -9
  54. package/lib/esm/tests/api_tests/phone_calls_cold_transfer.test.js.map +1 -1
  55. package/lib/esm/tests/api_tests/security/F-0013-sanitize-user-html-with-iframes.test.d.ts +2 -0
  56. package/lib/esm/tests/api_tests/security/F-0013-sanitize-user-html-with-iframes.test.d.ts.map +1 -0
  57. package/lib/esm/tests/api_tests/security/F-0013-sanitize-user-html-with-iframes.test.js +238 -0
  58. package/lib/esm/tests/api_tests/security/F-0013-sanitize-user-html-with-iframes.test.js.map +1 -0
  59. package/lib/esm/tests/api_tests/security/F-0015-webhook-outbound-ssrf.test.d.ts +29 -0
  60. package/lib/esm/tests/api_tests/security/F-0015-webhook-outbound-ssrf.test.d.ts.map +1 -0
  61. package/lib/esm/tests/api_tests/security/F-0015-webhook-outbound-ssrf.test.js +436 -0
  62. package/lib/esm/tests/api_tests/security/F-0015-webhook-outbound-ssrf.test.js.map +1 -0
  63. package/lib/esm/tests/api_tests/security/F-0025-proxy-image-unauth-ssrf.test.d.ts +35 -0
  64. package/lib/esm/tests/api_tests/security/F-0025-proxy-image-unauth-ssrf.test.d.ts.map +1 -0
  65. package/lib/esm/tests/api_tests/security/F-0025-proxy-image-unauth-ssrf.test.js +224 -0
  66. package/lib/esm/tests/api_tests/security/F-0025-proxy-image-unauth-ssrf.test.js.map +1 -0
  67. package/lib/esm/tests/api_tests/security/F-0166-allowed-paths-wildcard-bypass.test.d.ts.map +1 -1
  68. package/lib/esm/tests/api_tests/security/F-0166-allowed-paths-wildcard-bypass.test.js +524 -294
  69. package/lib/esm/tests/api_tests/security/F-0166-allowed-paths-wildcard-bypass.test.js.map +1 -1
  70. package/lib/esm/tests/tests.d.ts.map +1 -1
  71. package/lib/esm/tests/tests.js +431 -230
  72. package/lib/esm/tests/tests.js.map +1 -1
  73. package/lib/tsconfig.tsbuildinfo +1 -1
  74. package/package.json +10 -10
  75. package/src/tests/api_tests/custom_dashboards.test.ts +92 -0
  76. package/src/tests/api_tests/file_download_unicode_names.test.ts +223 -0
  77. package/src/tests/api_tests/openloop_webhooks.test.ts +138 -0
  78. package/src/tests/api_tests/phone_calls_cold_transfer.test.ts +54 -0
  79. package/src/tests/api_tests/security/F-0013-sanitize-user-html-with-iframes.test.ts +215 -0
  80. package/src/tests/api_tests/security/F-0166-allowed-paths-wildcard-bypass.test.ts +215 -0
  81. package/src/tests/tests.ts +212 -1
  82. package/test_generated.pdf +0 -0
@@ -1,4 +1,15 @@
1
1
  "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
2
13
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
14
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
15
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -49,15 +60,17 @@ exports.phone_calls_cold_transfer_tests = void 0;
49
60
  require('source-map-support').install();
50
61
  var sdk_1 = require("../../sdk");
51
62
  var testing_1 = require("@tellescope/testing");
63
+ var constants_1 = require("@tellescope/constants");
52
64
  var setup_1 = require("../setup");
53
65
  var host = process.env.API_URL || 'http://localhost:8080';
54
66
  var NONEXISTENT_MONGO_ID = '60398b1131a295e64f084fff';
67
+ var RAND = function () { return Math.random().toString(36).slice(2, 10); };
55
68
  // Validation-path tests for the cold transfer endpoint. All assertions below hit
56
69
  // validations that run before any Twilio access, so no Twilio config is needed.
57
70
  var phone_calls_cold_transfer_tests = function (_a) {
58
71
  var sdk = _a.sdk, sdkNonAdmin = _a.sdkNonAdmin;
59
72
  return __awaiter(void 0, void 0, void 0, function () {
60
- var enduser, targetUsers, inboundCall_1, outboundCall_1, disabledTargetUser_1;
73
+ var enduser, targetUsers, createdRoleIds, inboundCall_1, outboundCall_1, disabledTargetUser_1, mkRoleUser, sdkUpdateDefault_1, sdkReadDefault_1;
61
74
  return __generator(this, function (_b) {
62
75
  switch (_b.label) {
63
76
  case 0:
@@ -66,9 +79,10 @@ var phone_calls_cold_transfer_tests = function (_a) {
66
79
  case 1:
67
80
  enduser = _b.sent();
68
81
  targetUsers = [];
82
+ createdRoleIds = [];
69
83
  _b.label = 2;
70
84
  case 2:
71
- _b.trys.push([2, , 12, 14]);
85
+ _b.trys.push([2, , 17, 19]);
72
86
  return [4 /*yield*/, sdk.api.phone_calls.createOne({
73
87
  enduserId: enduser.id,
74
88
  inbound: true,
@@ -127,22 +141,84 @@ var phone_calls_cold_transfer_tests = function (_a) {
127
141
  _b.sent();
128
142
  // non-admin either can't see the call (Call not found) or is stopped by a later
129
143
  // validation (target has incoming calls disabled) — errors on every path
130
- return [4 /*yield*/, (0, testing_1.async_test)("cold_transfer: non-admin cannot transfer an inaccessible call", function () { return sdkNonAdmin.api.phone_calls.cold_transfer({ callSid: inboundCall_1.externalId, targetUserId: disabledTargetUser_1.id }); }, testing_1.handleAnyError)];
144
+ return [4 /*yield*/, (0, testing_1.async_test)("cold_transfer: non-admin cannot transfer an inaccessible call", function () { return sdkNonAdmin.api.phone_calls.cold_transfer({ callSid: inboundCall_1.externalId, targetUserId: disabledTargetUser_1.id }); }, testing_1.handleAnyError)
145
+ // ── target-user lookup must be gated by users READ access, not the endpoint's update access ──
146
+ // PROVIDER_PERMISSIONS already models the reported bug: users read='All', update='Default'.
147
+ // phone_calls gets FULL_ACCESS so the call itself is visible under update-level filtering.
148
+ ];
131
149
  case 11:
132
150
  // non-admin either can't see the call (Call not found) or is stopped by a later
133
151
  // validation (target has incoming calls disabled) — errors on every path
134
152
  _b.sent();
135
- return [3 /*break*/, 14];
136
- case 12:
153
+ mkRoleUser = function (permissions) { return __awaiter(void 0, void 0, void 0, function () {
154
+ var role, rbap, user, _a, authToken, sessionUser, session;
155
+ return __generator(this, function (_b) {
156
+ switch (_b.label) {
157
+ case 0:
158
+ role = "cold-transfer-".concat(RAND());
159
+ return [4 /*yield*/, sdk.api.role_based_access_permissions.createOne({ role: role, permissions: permissions })];
160
+ case 1:
161
+ rbap = _b.sent();
162
+ createdRoleIds.push(rbap.id);
163
+ return [4 /*yield*/, sdk.api.users.createOne({
164
+ email: "cold.transfer.".concat(RAND(), "@tellescope.example"),
165
+ fname: 'Cold', lname: 'TransferRole',
166
+ notificationEmailsDisabled: true, verifiedEmail: true,
167
+ roles: [role],
168
+ })];
169
+ case 2:
170
+ user = _b.sent();
171
+ targetUsers.push(user);
172
+ return [4 /*yield*/, sdk.api.users.generate_auth_token({ id: user.id })];
173
+ case 3:
174
+ _a = _b.sent(), authToken = _a.authToken, sessionUser = _a.user;
175
+ session = new sdk_1.Session({ host: host });
176
+ session.setAuthToken(authToken);
177
+ session.setUserInfo(sessionUser);
178
+ return [2 /*return*/, session];
179
+ }
180
+ });
181
+ }); };
182
+ return [4 /*yield*/, mkRoleUser(__assign(__assign({}, constants_1.PROVIDER_PERMISSIONS), { phone_calls: constants_1.FULL_ACCESS }))];
183
+ case 12:
184
+ sdkUpdateDefault_1 = _b.sent();
185
+ return [4 /*yield*/, mkRoleUser(__assign(__assign({}, constants_1.PROVIDER_PERMISSIONS), { phone_calls: constants_1.FULL_ACCESS, users: { create: null, read: 'Default', update: 'Default', delete: null } }))
186
+ // regression: previously failed with "Target user not found" because the lookup was
187
+ // filtered by users update='Default' (self-only); getting past it to the
188
+ // incoming-calls-disabled validation proves the lookup now uses read access
189
+ ];
190
+ case 13:
191
+ sdkReadDefault_1 = _b.sent();
192
+ // regression: previously failed with "Target user not found" because the lookup was
193
+ // filtered by users update='Default' (self-only); getting past it to the
194
+ // incoming-calls-disabled validation proves the lookup now uses read access
195
+ return [4 /*yield*/, (0, testing_1.async_test)("cold_transfer: users update=Default no longer blocks the target lookup", function () { return sdkUpdateDefault_1.api.phone_calls.cold_transfer({ callSid: inboundCall_1.externalId, targetUserId: disabledTargetUser_1.id }); }, { shouldError: true, onError: function (e) { return e.message === "Target user has incoming calls disabled"; } })
196
+ // guard: the lookup is read-filtered (not org-wide) — users read='Default' still can't see the target
197
+ ];
198
+ case 14:
199
+ // regression: previously failed with "Target user not found" because the lookup was
200
+ // filtered by users update='Default' (self-only); getting past it to the
201
+ // incoming-calls-disabled validation proves the lookup now uses read access
202
+ _b.sent();
203
+ // guard: the lookup is read-filtered (not org-wide) — users read='Default' still can't see the target
204
+ return [4 /*yield*/, (0, testing_1.async_test)("cold_transfer: users read=Default still hides the target user", function () { return sdkReadDefault_1.api.phone_calls.cold_transfer({ callSid: inboundCall_1.externalId, targetUserId: disabledTargetUser_1.id }); }, { shouldError: true, onError: function (e) { return e.message === "Target user not found"; } })];
205
+ case 15:
206
+ // guard: the lookup is read-filtered (not org-wide) — users read='Default' still can't see the target
207
+ _b.sent();
208
+ return [4 /*yield*/, (0, testing_1.async_test)("cold_transfer: nonexistent target still rejected for restricted role", function () { return sdkUpdateDefault_1.api.phone_calls.cold_transfer({ callSid: inboundCall_1.externalId, targetUserId: NONEXISTENT_MONGO_ID }); }, { shouldError: true, onError: function (e) { return e.message === "Target user not found"; } })];
209
+ case 16:
210
+ _b.sent();
211
+ return [3 /*break*/, 19];
212
+ case 17:
137
213
  // deleting the enduser cascades deletion of its phone_calls records
138
- return [4 /*yield*/, Promise.all(__spreadArray([
214
+ return [4 /*yield*/, Promise.all(__spreadArray(__spreadArray([
139
215
  sdk.api.endusers.deleteOne(enduser.id)
140
- ], targetUsers.map(function (u) { return sdk.api.users.deleteOne(u.id); }), true)).catch(console.error)];
141
- case 13:
216
+ ], targetUsers.map(function (u) { return sdk.api.users.deleteOne(u.id); }), true), createdRoleIds.map(function (id) { return sdk.api.role_based_access_permissions.deleteOne(id); }), true)).catch(console.error)];
217
+ case 18:
142
218
  // deleting the enduser cascades deletion of its phone_calls records
143
219
  _b.sent();
144
220
  return [7 /*endfinally*/];
145
- case 14: return [2 /*return*/];
221
+ case 19: return [2 /*return*/];
146
222
  }
147
223
  });
148
224
  });
@@ -1 +1 @@
1
- {"version":3,"file":"phone_calls_cold_transfer.test.js","sourceRoot":"","sources":["../../../../src/tests/api_tests/phone_calls_cold_transfer.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"phone_calls_cold_transfer.test.js","sourceRoot":"","sources":["../../../../src/tests/api_tests/phone_calls_cold_transfer.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const sanitize_user_html_with_iframes_tests: () => Promise<void>;
2
+ //# sourceMappingURL=F-0013-sanitize-user-html-with-iframes.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"F-0013-sanitize-user-html-with-iframes.test.d.ts","sourceRoot":"","sources":["../../../../../src/tests/api_tests/security/F-0013-sanitize-user-html-with-iframes.test.ts"],"names":[],"mappings":"AA+CA,eAAO,MAAM,qCAAqC,qBAiKjD,CAAA"}
@@ -0,0 +1,242 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.sanitize_user_html_with_iframes_tests = void 0;
40
+ var utilities_1 = require("@tellescope/utilities");
41
+ // Companion to F-0013-sanitize-user-html.test.ts (pattern 06 — XSS via dangerouslySetInnerHTML).
42
+ //
43
+ // sanitize_user_html_with_iframes is the variant used by the live form's field description, so
44
+ // admins can embed video / scheduling widgets. It permits <iframe> and NOTHING else beyond what
45
+ // sanitize_user_html allows. This asserts:
46
+ // 1. permitting iframe did not reopen any of the F-0013 vectors (the full payload list is re-run)
47
+ // 2. only absolute https iframes survive — relative, protocol-relative, http, javascript:, data:
48
+ // and srcdoc frames are dropped, along with their fallback content
49
+ // 3. the restrictive sandbox is forced, but an author-supplied sandbox is honored
50
+ // 4. sanitize_user_html itself still strips iframes (the boundary between the two functions)
51
+ //
52
+ // Pure-function test — no Session needed. Runs as part of the main suite and standalone:
53
+ // ./build_cjs.sh && cd packages/public/sdk && node -r dotenv/config lib/cjs/tests/api_tests/security/F-0013-sanitize-user-html-with-iframes.test.js
54
+ var fail = function (msg) { throw new Error(msg); };
55
+ // Same as has_no_executable_vector in the F-0013 test, minus the '<iframe' clause (iframes are
56
+ // expected in this function's output). Everything else must still be neutralized.
57
+ var has_no_executable_vector_allowing_iframe = function (out) {
58
+ var o = out.toLowerCase();
59
+ var withoutValues = o.replace(/"[^"]*"/g, '""').replace(/'[^']*'/g, "''");
60
+ return !/\son[a-z]+\s*=/.test(withoutValues) // no live on*= event-handler attribute
61
+ && !o.includes('javascript:')
62
+ && !o.includes('vbscript:')
63
+ && !o.includes('<script')
64
+ && !o.includes('<svg')
65
+ && !o.includes('<math')
66
+ && !o.includes('<object')
67
+ && !o.includes('<embed')
68
+ && !o.includes('<form')
69
+ && !o.includes('<noscript')
70
+ && !o.includes('<template')
71
+ && !o.includes('srcdoc'); // an inline document is arbitrary markup
72
+ };
73
+ // Tokens that must NEVER appear in the forced default. allow-top-navigation is the important one:
74
+ // it is what stops a hostile embed from redirecting the patient's form page to a phishing site.
75
+ var FORBIDDEN_SANDBOX_TOKENS = [
76
+ 'allow-top-navigation',
77
+ 'allow-downloads',
78
+ 'allow-modals',
79
+ 'allow-pointer-lock',
80
+ 'allow-orientation-lock',
81
+ ];
82
+ var sanitize_user_html_with_iframes_tests = function () { return __awaiter(void 0, void 0, void 0, function () {
83
+ var xssPayloads, _i, xssPayloads_1, _a, name_1, payload, out, badSrcs, _b, badSrcs_1, _c, name_2, src, out, fallback, srcdoc, handlers, yt, _d, FORBIDDEN_SANDBOX_TOKENS_1, token, authorSandbox, emptySandbox, noref, allowAttr, heading, table, list, link, img, dataimg, fmt, shared, adminTemplate, templated, endToEnd;
84
+ return __generator(this, function (_e) {
85
+ console.log("Running sanitize_user_html_with_iframes XSS regression tests");
86
+ xssPayloads = [
87
+ ['img onerror', "<img src=x onerror=\"alert(document.domain)\">"],
88
+ ['svg onload', "<svg onload=\"alert(1)\"></svg>"],
89
+ ['svg animate onbegin', "<svg><animate onbegin=\"alert(1)\" attributeName=\"x\" dur=\"1s\"></svg>"],
90
+ ['details ontoggle', "<details open ontoggle=\"alert(1)\"></details>"],
91
+ ['input onfocus autofocus', "<input autofocus onfocus=\"alert(1)\">"],
92
+ ['body onpageshow', "<body onpageshow=\"alert(1)\">"],
93
+ ['a javascript scheme', "<a href=\"javascript:alert(1)\">x</a>"],
94
+ ['a javascript entity-encoded', "<a href=\"jav&#x09;ascript:alert(1)\">x</a>"],
95
+ ['script tag', "<script>alert(1)</script>"],
96
+ ['onerror newline before =', "<img src=x onerror\n=\"alert(1)\">"],
97
+ ['onerror mixed case', "<IMG SRC=x OnErRoR=\"alert(1)\">"],
98
+ ['marquee onstart', "<marquee onstart=\"alert(1)\">x</marquee>"],
99
+ ['mathml mglyph style mxss', "<math><mtext><table><mglyph><style><!--</style><img src=x onerror=alert(1)>"],
100
+ ['svg foreignObject', "<svg><foreignObject><img src=x onerror=alert(1)></foreignObject></svg>"],
101
+ ['noscript context confusion', "<noscript><p title=\"</noscript><img src=x onerror=alert(1)>\">"],
102
+ ['template content', "<template><img src=x onerror=alert(1)></template>"],
103
+ ['comment confusion', "<!--><img src=x onerror=alert(1)>-->"],
104
+ ['cdata confusion', "<![CDATA[<img src=x onerror=alert(1)>]]>"],
105
+ ['markup inside attr value', "<img src=\"x\" alt=\"<script>alert(1)</script>\">"],
106
+ ['vbscript scheme', "<a href=\"vbscript:msgbox(1)\">x</a>"],
107
+ ['data text/html href', "<a href=\"data:text/html,<script>alert(1)</script>\">x</a>"],
108
+ ['javascript decimal entity', "<a href=\"&#74;avascript:alert(1)\">x</a>"],
109
+ ['javascript newline entity', "<a href=\"jav&#x0A;ascript:alert(1)\">x</a>"],
110
+ ];
111
+ for (_i = 0, xssPayloads_1 = xssPayloads; _i < xssPayloads_1.length; _i++) {
112
+ _a = xssPayloads_1[_i], name_1 = _a[0], payload = _a[1];
113
+ out = (0, utilities_1.sanitize_user_html_with_iframes)(payload);
114
+ if (!has_no_executable_vector_allowing_iframe(out))
115
+ fail("XSS not neutralized [".concat(name_1, "] -> ").concat(out));
116
+ }
117
+ badSrcs = [
118
+ ['javascript scheme', "javascript:alert(1)"],
119
+ ['data text/html', "data:text/html,<script>alert(1)</script>"],
120
+ ['http (not https)', "http://evil.example"],
121
+ // sanitize-html does NOT reject protocol-relative iframe srcs on its own when
122
+ // allowProtocolRelative is set — this is the self-origin framing vector and the reason the
123
+ // sanitizer does its own absolute-https check.
124
+ ['protocol-relative', "//app.tellescope.com/"],
125
+ ['root-relative', "/portal/settings"],
126
+ ['bare relative', "settings"],
127
+ ['whitespace-obfuscated', " https:/\\/\\evil"],
128
+ ['tab-entity javascript', "jav&#x09;ascript:alert(1)"],
129
+ ['scheme-only', "https://"],
130
+ ['empty', ""],
131
+ ];
132
+ for (_b = 0, badSrcs_1 = badSrcs; _b < badSrcs_1.length; _b++) {
133
+ _c = badSrcs_1[_b], name_2 = _c[0], src = _c[1];
134
+ out = (0, utilities_1.sanitize_user_html_with_iframes)("<iframe src=\"".concat(src, "\"></iframe>"));
135
+ if (out.toLowerCase().includes('<iframe'))
136
+ fail("bad iframe src survived [".concat(name_2, "] -> ").concat(out));
137
+ }
138
+ fallback = (0, utilities_1.sanitize_user_html_with_iframes)("<iframe src=\"/x\">FALLBACK-TEXT</iframe>");
139
+ if (fallback.includes('FALLBACK-TEXT'))
140
+ fail("dropped iframe leaked its fallback text: ".concat(fallback));
141
+ if (fallback.toLowerCase().includes('<iframe'))
142
+ fail("dropped iframe survived: ".concat(fallback));
143
+ srcdoc = (0, utilities_1.sanitize_user_html_with_iframes)("<iframe src=\"https://ok.example\" srcdoc=\"<img src=x onerror=alert(1)>\"></iframe>");
144
+ if (srcdoc.toLowerCase().includes('srcdoc'))
145
+ fail("srcdoc not stripped: ".concat(srcdoc));
146
+ if (!srcdoc.toLowerCase().includes('<iframe'))
147
+ fail("valid iframe dropped alongside srcdoc: ".concat(srcdoc));
148
+ handlers = (0, utilities_1.sanitize_user_html_with_iframes)("<iframe src=\"https://ok.example\" onload=\"alert(1)\" id=\"x\" name=\"getElementById\"></iframe>");
149
+ if (!handlers.toLowerCase().includes('<iframe'))
150
+ fail("valid iframe dropped: ".concat(handlers));
151
+ if (/\son[a-z]+\s*=/.test(handlers.toLowerCase()))
152
+ fail("iframe event handler survived: ".concat(handlers));
153
+ if (/\b(id|name)\s*=/.test(handlers))
154
+ fail("iframe id/name not stripped (DOM clobbering): ".concat(handlers));
155
+ yt = (0, utilities_1.sanitize_user_html_with_iframes)("<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/abc\" frameBorder=\"0\"></iframe>");
156
+ if (!yt.includes('src="https://www.youtube.com/embed/abc"'))
157
+ fail("youtube embed src stripped: ".concat(yt));
158
+ if (!(yt.includes('width="560"') && yt.includes('height="315"')))
159
+ fail("iframe dimensions stripped: ".concat(yt));
160
+ if (!yt.toLowerCase().includes('frameborder'))
161
+ fail("frameborder stripped: ".concat(yt));
162
+ // forced containment
163
+ if (!yt.includes("sandbox=\"".concat(utilities_1.DEFAULT_IFRAME_SANDBOX, "\"")))
164
+ fail("sandbox not forced: ".concat(yt));
165
+ if (!yt.toLowerCase().includes('referrerpolicy='))
166
+ fail("referrerpolicy not set: ".concat(yt));
167
+ for (_d = 0, FORBIDDEN_SANDBOX_TOKENS_1 = FORBIDDEN_SANDBOX_TOKENS; _d < FORBIDDEN_SANDBOX_TOKENS_1.length; _d++) {
168
+ token = FORBIDDEN_SANDBOX_TOKENS_1[_d];
169
+ if (utilities_1.DEFAULT_IFRAME_SANDBOX.includes(token))
170
+ fail("forced sandbox must not grant ".concat(token, ": ").concat(utilities_1.DEFAULT_IFRAME_SANDBOX));
171
+ }
172
+ // allow-same-origin IS granted — required for real embeds (a Loom embed renders blank without it)
173
+ // and harmless because the src is guaranteed cross-origin by the check asserted above.
174
+ if (!utilities_1.DEFAULT_IFRAME_SANDBOX.includes('allow-same-origin'))
175
+ fail("forced sandbox must grant allow-same-origin so real embeds render: ".concat(utilities_1.DEFAULT_IFRAME_SANDBOX));
176
+ authorSandbox = (0, utilities_1.sanitize_user_html_with_iframes)("<iframe src=\"https://ok.example\" sandbox=\"allow-scripts\"></iframe>");
177
+ if (!authorSandbox.includes('sandbox="allow-scripts"'))
178
+ fail("author sandbox not honored: ".concat(authorSandbox));
179
+ emptySandbox = (0, utilities_1.sanitize_user_html_with_iframes)("<iframe src=\"https://ok.example\" sandbox=\"\"></iframe>");
180
+ if (emptySandbox.includes('allow-'))
181
+ fail("empty sandbox was replaced with the permissive default: ".concat(emptySandbox));
182
+ if (!/\ssandbox(\s|>)/.test(emptySandbox))
183
+ fail("empty sandbox attribute lost entirely: ".concat(emptySandbox));
184
+ noref = (0, utilities_1.sanitize_user_html_with_iframes)("<iframe src=\"https://ok.example\" referrerpolicy=\"no-referrer\"></iframe>");
185
+ if (!noref.includes('referrerpolicy="no-referrer"'))
186
+ fail("author referrerpolicy not honored: ".concat(noref));
187
+ allowAttr = (0, utilities_1.sanitize_user_html_with_iframes)("<iframe src=\"https://ok.example\" allow=\"autoplay; encrypted-media\" allowfullscreen></iframe>");
188
+ if (!allowAttr.includes('allow="autoplay; encrypted-media"'))
189
+ fail("allow attribute stripped: ".concat(allowAttr));
190
+ heading = (0, utilities_1.sanitize_user_html_with_iframes)("<h1>Welcome</h1><h3 style=\"color:#333\">Sub</h3>");
191
+ if (!(heading.includes('<h1>') && heading.includes('<h3') && heading.toLowerCase().includes('color')))
192
+ fail("headings/style stripped: ".concat(heading));
193
+ table = (0, utilities_1.sanitize_user_html_with_iframes)("<table><thead><tr><th>H</th></tr></thead><tbody><tr><td style=\"padding:4px\" colspan=\"2\">cell</td></tr></tbody></table>");
194
+ if (!(table.includes('<table') && table.includes('<td') && table.includes('colspan')))
195
+ fail("table stripped: ".concat(table));
196
+ list = (0, utilities_1.sanitize_user_html_with_iframes)("<ul><li>a</li></ul><ol start=\"3\"><li>c</li></ol>");
197
+ if (!(list.includes('<ul') && list.includes('<li') && list.includes('<ol')))
198
+ fail("list stripped: ".concat(list));
199
+ link = (0, utilities_1.sanitize_user_html_with_iframes)("<a href=\"https://example.com\">link</a>");
200
+ if (!link.includes('href="https://example.com"'))
201
+ fail("safe link stripped: ".concat(link));
202
+ if (!link.toLowerCase().includes('noopener'))
203
+ fail("external link not hardened: ".concat(link));
204
+ img = (0, utilities_1.sanitize_user_html_with_iframes)("<img src=\"https://cdn.example.com/a.png\" alt=\"pic\" width=\"200\">");
205
+ if (!(img.includes('src="https://cdn.example.com/a.png"') && img.includes('alt="pic"')))
206
+ fail("image stripped: ".concat(img));
207
+ dataimg = (0, utilities_1.sanitize_user_html_with_iframes)("<img src=\"data:image/png;base64,iVBORw0KGgo=\">");
208
+ if (!dataimg.includes('data:image/png'))
209
+ fail("data: image stripped: ".concat(dataimg));
210
+ fmt = (0, utilities_1.sanitize_user_html_with_iframes)("<p><strong>b</strong> <em>i</em> <span style=\"font-size:14px\">s</span></p><blockquote>q</blockquote>");
211
+ if (!(fmt.includes('<strong>') && fmt.includes('<span') && fmt.toLowerCase().includes('font-size')))
212
+ fail("formatting stripped: ".concat(fmt));
213
+ shared = (0, utilities_1.sanitize_user_html)("<iframe src=\"https://www.youtube.com/embed/abc\"></iframe>");
214
+ if (shared.toLowerCase().includes('<iframe'))
215
+ fail("sanitize_user_html must still strip iframes: ".concat(shared));
216
+ adminTemplate = "<p>Hi {{enduser.fname}}, watch this:</p><iframe src=\"https://www.youtube.com/embed/abc\"></iframe>";
217
+ templated = (0, utilities_1.replace_form_field_template_values)(adminTemplate, {
218
+ enduser: { fname: "<iframe src=\"https://evil.example/phish\"></iframe>" },
219
+ responses: [],
220
+ escapeNewlinesAsHTMLBreaks: true,
221
+ escapeHTMLValues: true,
222
+ });
223
+ endToEnd = (0, utilities_1.sanitize_user_html_with_iframes)(templated);
224
+ if (!endToEnd.includes('src="https://www.youtube.com/embed/abc"'))
225
+ fail("admin's own iframe did not survive: ".concat(endToEnd));
226
+ // The patient's markup must survive only as inert escaped text — so 'evil.example' may still
227
+ // appear as visible characters, but there must be exactly one LIVE frame (the admin's).
228
+ if (!endToEnd.includes('&lt;iframe'))
229
+ fail("patient markup not escaped to inert text: ".concat(endToEnd));
230
+ if ((endToEnd.toLowerCase().match(/<iframe/g) || []).length !== 1)
231
+ fail("patient-injected iframe became a live frame: ".concat(endToEnd));
232
+ console.log("✅ sanitize_user_html_with_iframes XSS regression tests passed");
233
+ return [2 /*return*/];
234
+ });
235
+ }); };
236
+ exports.sanitize_user_html_with_iframes_tests = sanitize_user_html_with_iframes_tests;
237
+ if (require.main === module) {
238
+ (0, exports.sanitize_user_html_with_iframes_tests)()
239
+ .then(function () { console.log("✅ suite completed"); process.exit(0); })
240
+ .catch(function (err) { console.error("❌ suite failed:", err); process.exit(1); });
241
+ }
242
+ //# sourceMappingURL=F-0013-sanitize-user-html-with-iframes.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"F-0013-sanitize-user-html-with-iframes.test.js","sourceRoot":"","sources":["../../../../../src/tests/api_tests/security/F-0013-sanitize-user-html-with-iframes.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { Session } from "../../../sdk";
2
+ /**
3
+ * Regression tests for F-0015
4
+ * (security-audit/findings/F-0015-webhook-outbound-ssrf.md).
5
+ *
6
+ * Outbound webhooks request customer-configured URLs that are validated only for SYNTAX
7
+ * (urlValidator -> validator.isURL, which happily accepts http://10.0.0.1/). Four call sites are
8
+ * affected: api/modules/webhooks.ts:145, :214, :270, and the five-method block at api/v1/api.ts:9723.
9
+ *
10
+ * Two properties make this worse than a blind SSRF:
11
+ * - A non-2xx response body is stored in log.response, and webhook_logs is surfaced to customers for
12
+ * debugging — so an internal endpoint's error body is readable by the tenant that configured it.
13
+ * - The automation send-webhook action builds its URL at runtime through five nested template
14
+ * replacers over action.info.url, so patient-controlled field values can reach the destination.
15
+ *
16
+ * And critically: axios@0.30.2 follows redirects by default (maxRedirects: 5). A pre-flight check on
17
+ * the configured URL is therefore NOT sufficient — a receiver can simply 302 to an internal address
18
+ * after validation has already passed. T4 exists to prove exactly that, which is why the fix has to
19
+ * validate at connect time (a guarded agent) rather than as a string check.
20
+ *
21
+ * Each test below asserts ABSENCE ("the sentinel was never contacted"), which passes trivially if the
22
+ * request never happened at all — a missing allowlist entry, a webhook that never fired, a broken
23
+ * subscription. So each is paired with a positive control that proves the attempt really was made.
24
+ */
25
+ export declare const webhook_outbound_ssrf_tests: ({ sdk }: {
26
+ sdk: Session;
27
+ sdkNonAdmin: Session;
28
+ }) => Promise<void>;
29
+ //# sourceMappingURL=F-0015-webhook-outbound-ssrf.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"F-0015-webhook-outbound-ssrf.test.d.ts","sourceRoot":"","sources":["../../../../../src/tests/api_tests/security/F-0015-webhook-outbound-ssrf.test.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAyEtC;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,2BAA2B;SAA2B,OAAO;iBAAe,OAAO;mBA0K/F,CAAA"}