mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-10-20 11:02:35 +00:00
Merged via /merge-batch (2026-10-19). Board validation on the current base together with #17138: npm run lint 0, typecheck core + open-sse 0, check:docs-all 0, file-size, test-masking, changelog-integrity, env-doc-sync, complexity, cognitive, provider-consistency 0; 187 affected unit files 2093 pass with only the 3 base-red #15306 i18n state tests failing. CI reds are inherited (i18n state tests, Docs Sync drift, Gate / Quality, E2E 3/9 mobile sidebar fail on unrelated PRs too).
This commit is contained in:
parent
03be754e95
commit
aae8749eed
3 changed files with 19 additions and 3 deletions
1
changelog.d/fixes/16327-m365-substrate-cloud-host.md
Normal file
1
changelog.d/fixes/16327-m365-substrate-cloud-host.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
- Accept the exact Microsoft 365 Copilot ChatHub host `substrate.svc.cloud.microsoft` when importing or pasting credentials, preserving the host through validation and execution while rejecting untrusted hosts and malformed URLs (#16327).
|
||||
|
|
@ -7,7 +7,7 @@ export interface M365CredentialParts {
|
|||
|
||||
const CHATHUB_PATH = "/m365Copilot/Chathub/";
|
||||
const TRUSTED_HOST =
|
||||
/^(?:[a-z0-9-]+\.)*(?:m365\.cloud\.microsoft|copilot\.microsoft\.com|substrate\.office\.com)$/i;
|
||||
/^(?:(?:[a-z0-9-]+\.)*(?:m365\.cloud\.microsoft|copilot\.microsoft\.com|substrate\.office\.com)|substrate\.svc\.cloud\.microsoft)$/i;
|
||||
|
||||
export type M365ChatHubUrlResult =
|
||||
| { credential: Required<M365CredentialParts> }
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import assert from "node:assert/strict";
|
||||
import { describe, it } from "node:test";
|
||||
import { validateCopilotM365WebProvider } from "../../src/lib/providers/validation/webProvidersB.ts";
|
||||
import { extractM365CredentialFromHar } from "../../src/shared/utils/m365HarImport.ts";
|
||||
import {
|
||||
resolveConnectionParams,
|
||||
|
|
@ -18,12 +19,15 @@ describe("M365 HAR host compatibility (#16327)", () => {
|
|||
"eu.m365.cloud.microsoft",
|
||||
"copilot.microsoft.com",
|
||||
"substrate.office.com",
|
||||
"substrate.svc.cloud.microsoft",
|
||||
"SUBSTRATE.SVC.CLOUD.MICROSOFT:443",
|
||||
"M365.CLOUD.MICROSOFT:443",
|
||||
]) {
|
||||
it(`preserves ${host} from HAR through execution`, () => {
|
||||
it(`preserves ${host} from HAR through validation and execution`, async () => {
|
||||
const imported = extractM365CredentialFromHar(har(url(host)));
|
||||
assert.equal(imported.ok, true);
|
||||
if (!imported.ok) return;
|
||||
assert.equal((await validateCopilotM365WebProvider({ apiKey: imported.apiKey })).valid, true);
|
||||
const params = resolveConnectionParams({ apiKey: imported.apiKey });
|
||||
assert.ok(!("error" in params));
|
||||
assert.equal(params.host, host.toLowerCase().replace(":443", ""));
|
||||
|
|
@ -59,6 +63,16 @@ describe("M365 HAR host compatibility (#16327)", () => {
|
|||
for (const unsafe of [
|
||||
url("m365.cloud.microsoft.attacker.invalid"),
|
||||
url("attacker.invalid"),
|
||||
url("substrate.svc.cloud.microsoft.attacker.invalid"),
|
||||
url("sub.substrate.svc.cloud.microsoft"),
|
||||
url("other.svc.cloud.microsoft"),
|
||||
url("user@substrate.svc.cloud.microsoft"),
|
||||
url("substrate.svc.cloud.microsoft:8443"),
|
||||
url("substrate.svc.cloud.microsoft").replace("wss:", "ws:"),
|
||||
url("substrate.svc.cloud.microsoft").replace("wss:", "https:"),
|
||||
url("substrate.svc.cloud.microsoft").replace("Chathub", "StreamHub"),
|
||||
url("substrate.svc.cloud.microsoft").replace(path, "user@tenant/extra"),
|
||||
url("substrate.svc.cloud.microsoft").replace(path, "%ZZ"),
|
||||
url("m365.cloud.microsoft:8443"),
|
||||
url("user@m365.cloud.microsoft"),
|
||||
url("m365.cloud.microsoft").replace("wss:", "ws:"),
|
||||
|
|
@ -66,9 +80,10 @@ describe("M365 HAR host compatibility (#16327)", () => {
|
|||
url("substrate.office.com").replace(path, "user@tenant%3Bhost=attacker.invalid"),
|
||||
url("substrate.office.com").replace(path, "user@tenant%3Faccess_token=other"),
|
||||
]) {
|
||||
it(`rejects unsafe HAR URL ${unsafe.replace(token, "REDACTED")}`, () => {
|
||||
it(`rejects unsafe HAR URL ${unsafe.replace(token, "REDACTED")}`, async () => {
|
||||
const imported = extractM365CredentialFromHar(har(unsafe));
|
||||
assert.equal(imported.ok, false);
|
||||
assert.equal((await validateCopilotM365WebProvider({ apiKey: unsafe })).valid, false);
|
||||
const params = resolveConnectionParams({ apiKey: unsafe });
|
||||
assert.ok("error" in params);
|
||||
if ("error" in params) assert.ok(!params.error.includes(token));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue