mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-28 01:21:36 +00:00
fix: enforce paired scope baselines on reconnect
This commit is contained in:
@@ -84,7 +84,7 @@ describe("talk-voice plugin", () => {
|
||||
text:
|
||||
"Talk voice status:\n" +
|
||||
"- provider: microsoft\n" +
|
||||
"- talk.voiceId: en-US-AvaNeural\n" +
|
||||
"- talk.providers.microsoft.voiceId: en-US-AvaNeural\n" +
|
||||
"- microsoft.apiKey: secret…",
|
||||
});
|
||||
});
|
||||
|
||||
@@ -408,6 +408,7 @@ describe("callGateway url resolution", () => {
|
||||
"operator.write",
|
||||
"operator.approvals",
|
||||
"operator.pairing",
|
||||
"operator.talk.secrets",
|
||||
],
|
||||
},
|
||||
])("scope selection: $label", async ({ call, expectedScopes }) => {
|
||||
|
||||
@@ -738,21 +738,20 @@ export function attachGatewayWsMessageHandler(params: {
|
||||
sharedAuthOk,
|
||||
authMethod,
|
||||
});
|
||||
const skipPairing =
|
||||
shouldSkipLocalBackendSelfPairing({
|
||||
connectParams,
|
||||
locality: pairingLocality,
|
||||
hasBrowserOriginHeader,
|
||||
sharedAuthOk,
|
||||
authMethod,
|
||||
}) ||
|
||||
shouldSkipControlUiPairing(
|
||||
controlUiAuthPolicy,
|
||||
role,
|
||||
trustedProxyAuthOk,
|
||||
resolvedAuth.mode,
|
||||
);
|
||||
if (device && devicePublicKey && !skipPairing) {
|
||||
const skipLocalBackendSelfPairing = shouldSkipLocalBackendSelfPairing({
|
||||
connectParams,
|
||||
locality: pairingLocality,
|
||||
hasBrowserOriginHeader,
|
||||
sharedAuthOk,
|
||||
authMethod,
|
||||
});
|
||||
const skipControlUiPairingForDevice = shouldSkipControlUiPairing(
|
||||
controlUiAuthPolicy,
|
||||
role,
|
||||
trustedProxyAuthOk,
|
||||
resolvedAuth.mode,
|
||||
);
|
||||
if (device && devicePublicKey) {
|
||||
const formatAuditList = (items: string[] | undefined): string => {
|
||||
if (!items || items.length === 0) {
|
||||
return "<none>";
|
||||
@@ -968,9 +967,15 @@ export function attachGatewayWsMessageHandler(params: {
|
||||
const paired = await getPairedDevice(device.id);
|
||||
const isPaired = paired?.publicKey === devicePublicKey;
|
||||
if (!isPaired) {
|
||||
const ok = await requirePairing("not-paired", paired);
|
||||
if (!ok) {
|
||||
return;
|
||||
if (!(skipLocalBackendSelfPairing || skipControlUiPairingForDevice)) {
|
||||
// Initial local backend/control-ui self-pairing can bypass the
|
||||
// pairing prompt, but only while the device is still unpaired.
|
||||
// Once a device is paired, reconnects must stay inside the
|
||||
// approved role/scope baseline below.
|
||||
const ok = await requirePairing("not-paired", paired);
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const claimedPlatform = connectParams.client.platform;
|
||||
@@ -1001,10 +1006,10 @@ export function attachGatewayWsMessageHandler(params: {
|
||||
}
|
||||
}
|
||||
const pairedRoles = listEffectivePairedDeviceRoles(paired);
|
||||
const pairedScopes = Array.isArray(paired.scopes)
|
||||
? paired.scopes
|
||||
: Array.isArray(paired.approvedScopes)
|
||||
? paired.approvedScopes
|
||||
const pairedScopes = Array.isArray(paired.approvedScopes)
|
||||
? paired.approvedScopes
|
||||
: Array.isArray(paired.scopes)
|
||||
? paired.scopes
|
||||
: [];
|
||||
const allowedRoles = new Set(pairedRoles);
|
||||
if (allowedRoles.size === 0) {
|
||||
|
||||
Reference in New Issue
Block a user