Skip to content

Commit a448815

Browse files
author
Krzysztof Nowicki
committed
Add support for InTune Single-Sign-On
This add support for communicating with the Microsoft Authentication Broker over its DBus interface in order to retrieve an authentication cookie, that can be used to automatically login the user currently logged-in via InTune. This also adds support for MFA and Conditional Access, which allows use of Teams outside of corporate network in case the organization has chosen to only allow access from registered devices. Behind the scene this uses the same mechanism as Microsoft Edge on Linux: upon loading a website from login.microsoftonline.com the URL is passed to the authentication broker in order to prepare a token based on the PRT (Primary Refresh Token). The returned refresh token is passed to the server via the 'X-Ms-Refreshtokencredential' HTTP header. With this token in place the server will skip any interactive prompts and generate a proper OAuth authentication token. Since the PRT is tied to the device credentials, the resulting refresh token carries the MFA attribute, which causes it to be accepted even if the Conditional Access policy mandates strong, device-based authentication. Signed-off-by: Krzysztof Nowicki <[email protected]>
1 parent 221dafe commit a448815

File tree

6 files changed

+225
-5
lines changed

6 files changed

+225
-5
lines changed

app/config/README.md

+2
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ Here is the list of available arguments and its usage:
5757
| spellCheckerLanguages | Array of languages to use with Electron's spell checker | [] |
5858
| ssoBasicAuthUser | Login that will be sent for basic_auth SSO login. | string |
5959
| ssoBasicAuthPasswordCommand | Command to execute, grab stdout and use it as a password for basic_auth SSO login. | string |
60+
| ssoIntuneEnabled | Enable InTune Single-Sign-On | false
61+
| ssoIntuneAuthUser | User (e-mail) to be used for InTune SSO login. | string |
6062
| trayIconEnabled | Enable tray icon | true |
6163
| url | Microsoft Teams URL | string |
6264
| useMutationTitleLogic | Use MutationObserver to update counter from title | true |

app/config/index.js

+10
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,16 @@ function argv(configPath, appVersion) {
275275
describe: 'Command to execute to retrieve password for SSO basic auth.',
276276
type: 'string'
277277
},
278+
ssoInTuneEnabled: {
279+
default: false,
280+
describe: 'Enable Single-Sign-On using Microsoft InTune.',
281+
type: 'boolean'
282+
},
283+
ssoInTuneAuthUser: {
284+
default: '',
285+
describe: 'User (e-mail) to use for InTune SSO.',
286+
type: 'string'
287+
},
278288
trayIconEnabled: {
279289
default: true,
280290
describe: 'Enable tray icon',

app/intune/index.js

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
const dbus = require('@homebridge/dbus-native');
2+
const { LucidLog } = require('lucid-log');
3+
4+
var sessionBus = dbus.sessionBus();
5+
6+
var intuneAccount = null;
7+
8+
var brokerService = sessionBus.getService('com.microsoft.identity.broker1');
9+
10+
function processInTuneAccounts(logger, resp, ssoInTuneAuthUser) {
11+
response = JSON.parse(resp);
12+
if ('error' in response) {
13+
logger.warn('Failed to retrieve InTune account list: ' + response.error.context);
14+
return;
15+
};
16+
17+
if (ssoInTuneAuthUser == '') {
18+
intuneAccount = response.accounts[0];
19+
logger.debug('Using first available InTune account (' + intuneAccount.username + ')');
20+
} else {
21+
for (account in response.accounts) {
22+
if (account.username == ssoIntuneAuthUser) {
23+
intuneAccount = account;
24+
logger.debug('Found matching InTune account (' + intuneAccount.username + ')');
25+
break;
26+
}
27+
}
28+
if (intuneAccount == null) {
29+
logger.warn('Failed to find matching InTune account for ' + ssoIntuneAuthUser + '.');
30+
}
31+
}
32+
}
33+
34+
exports.initSso = function initIntuneSso(logger, ssoInTuneAuthUser) {
35+
logger.debug("Initializing InTune SSO");
36+
brokerService.getInterface(
37+
'/com/microsoft/identity/broker1',
38+
'com.microsoft.identity.Broker1', function(err, broker) {
39+
if (err) {
40+
logger.warn('Failed to find microsoft-identity-broker DBus interface');
41+
return;
42+
}
43+
broker.getAccounts('0.0', '', JSON.stringify({'clientId': '88200948-af09-45a1-9c03-53cdcc75c183', 'redirectUri':'urn:ietf:oob'}), function(err, resp) {
44+
if (err) {
45+
logger.warn('Failed to communicate with microsoft-identity-broker');
46+
return;
47+
}
48+
processInTuneAccounts(logger, resp, ssoInTuneAuthUser);
49+
});
50+
});
51+
}
52+
53+
exports.setupUrlFilter = function setupUrlFilter(filter) {
54+
filter.urls.push('https://login.microsoftonline.com/*');
55+
}
56+
57+
exports.isSsoUrl = function isSsoUrl(url) {
58+
return intuneAccount != null && url.startsWith('https://login.microsoftonline.com/');
59+
}
60+
61+
function processPrtResponse(logger, resp, detail) {
62+
response = JSON.parse(resp);
63+
if ('error' in response) {
64+
logger.warn('Failed to retrieve Intune SSO cookie: ' + response.error.context);
65+
} else {
66+
logger.debug('Adding SSO credential');
67+
detail.requestHeaders['X-Ms-Refreshtokencredential'] = response['cookieContent'];
68+
}
69+
}
70+
71+
exports.addSsoCookie = function addIntuneSsoCookie(logger, detail, callback) {
72+
logger.debug('Retrieving InTune SSO cookie');
73+
if (intuneAccount == null) {
74+
logger.info("InTune SSO not active");
75+
callback({
76+
requestHeaders: detail.requestHeaders
77+
});
78+
return;
79+
}
80+
brokerService.getInterface(
81+
'/com/microsoft/identity/broker1',
82+
'com.microsoft.identity.Broker1', function(err, broker) {
83+
broker.acquirePrtSsoCookie('0.0', '', JSON.stringify({'ssoUrl':detail.url, 'account':intuneAccount, 'authParameters':{'authority':'https://login.microsoftonline.com/common/'}}), function(err, resp) {
84+
processPrtResponse(logger, resp, detail);
85+
callback({
86+
requestHeaders: detail.requestHeaders
87+
});
88+
});
89+
});
90+
}
91+

app/mainAppWindow/index.js

+15-5
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const TrayIconChooser = require('../browser/tools/trayIconChooser');
1616
const { AppConfiguration } = require('../appConfiguration');
1717
const connMgr = require('../connectionManager');
1818
const fs = require('fs');
19+
const intune = require('../intune');
1920

2021
/**
2122
* @type {TrayIconChooser}
@@ -65,6 +66,10 @@ exports.onAppReady = async function onAppReady(configGroup) {
6566
levels: config.appLogLevels.split(',')
6667
});
6768

69+
if (config.ssoInTuneEnabled) {
70+
intune.initSso(logger, config.ssoInTuneAuthUser);
71+
}
72+
6873
window = await createWindow();
6974

7075
if (config.trayIconEnabled) {
@@ -323,12 +328,16 @@ function setImgSrcSecurityPolicy(policies) {
323328
* @param {Electron.BeforeSendResponse} callback
324329
*/
325330
function onBeforeSendHeadersHandler(detail, callback) {
326-
if (detail.url.startsWith(customBGServiceUrl.href)) {
327-
detail.requestHeaders['Access-Control-Allow-Origin'] = '*';
331+
if (intune.isSsoUrl(detail.url)) {
332+
intune.addSsoCookie(logger, detail, callback);
333+
} else {
334+
if (detail.url.startsWith(customBGServiceUrl.href)) {
335+
detail.requestHeaders['Access-Control-Allow-Origin'] = '*';
336+
}
337+
callback({
338+
requestHeaders: detail.requestHeaders
339+
});
328340
}
329-
callback({
330-
requestHeaders: detail.requestHeaders
331-
});
332341
}
333342

334343
/**
@@ -409,6 +418,7 @@ function addEventHandlers() {
409418

410419
function getWebRequestFilterFromURL() {
411420
const filter = customBGServiceUrl.protocol === 'http:' ? { urls: ['http://*/*'] } : { urls: ['https://*/*'] };
421+
intune.setupUrlFilter(filter);
412422
return filter;
413423
}
414424

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"release": "electron-builder"
4141
},
4242
"dependencies": {
43+
"@homebridge/dbus-native": "0.6.0",
4344
"@electron/remote": "^2.1.2",
4445
"electron-is-dev": "2.0.0",
4546
"electron-store": "8.2.0",

yarn.lock

+106
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,29 @@
119119
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.0.0.tgz#1a9e4b4c96d8c7886e0110ed310a0135144a1691"
120120
integrity sha512-RThY/MnKrhubF6+s1JflwUjPEsnCEmYCWwqa/aRISKWNXGZ9epUwft4bUMM35SdKF9xvBrLydAM1RDHd1Z//ZQ==
121121

122+
"@homebridge/[email protected]":
123+
version "0.6.0"
124+
resolved "https://registry.yarnpkg.com/@homebridge/dbus-native/-/dbus-native-0.6.0.tgz#25052dd03216b977298e4c9db19b7aeb1d2363f4"
125+
integrity sha512-xObqQeYHTXmt6wsfj10+krTo4xbzR9BgUfX2aQ+edDC9nc4ojfzLScfXCh3zluAm6UCowKw+AFfXn6WLWUOPkg==
126+
dependencies:
127+
"@homebridge/long" "^5.2.1"
128+
"@homebridge/put" "^0.0.8"
129+
event-stream "^4.0.1"
130+
hexy "^0.3.5"
131+
minimist "^1.2.6"
132+
safe-buffer "^5.1.2"
133+
xml2js "^0.6.2"
134+
135+
"@homebridge/long@^5.2.1":
136+
version "5.2.1"
137+
resolved "https://registry.yarnpkg.com/@homebridge/long/-/long-5.2.1.tgz#1c7568775b78e1a0fd75a7b3fa7a995f0388ab37"
138+
integrity sha512-i5Df8R63XNPCn+Nj1OgAoRdw9e+jHUQb3CNUbvJneI2iu3j4+OtzQj+5PA1Ce+747NR1SPqZSvyvD483dOT3AA==
139+
140+
"@homebridge/put@^0.0.8":
141+
version "0.0.8"
142+
resolved "https://registry.yarnpkg.com/@homebridge/put/-/put-0.0.8.tgz#4b8b99f2c4d58bc762718863699df2c5bc0b4b8a"
143+
integrity sha512-mwxLHHqKebOmOSU0tsPEWQSBHGApPhuaqtNpCe7U+AMdsduweANiu64E9SXXUtdpyTjsOpgSMLhD1+kbLHD2gA==
144+
122145
"@humanwhocodes/config-array@^0.12.3":
123146
version "0.12.3"
124147
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.12.3.tgz#a6216d90f81a30bedd1d4b5d799b47241f318072"
@@ -795,6 +818,11 @@ dotenv@^9.0.2:
795818
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-9.0.2.tgz#dacc20160935a37dea6364aa1bef819fb9b6ab05"
796819
integrity sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==
797820

821+
duplexer@^0.1.1, duplexer@~0.1.1:
822+
version "0.1.2"
823+
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
824+
integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==
825+
798826
eastasianwidth@^0.2.0:
799827
version "0.2.0"
800828
resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb"
@@ -1012,6 +1040,19 @@ esutils@^2.0.2:
10121040
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
10131041
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
10141042

1043+
event-stream@^4.0.1:
1044+
version "4.0.1"
1045+
resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-4.0.1.tgz#4092808ec995d0dd75ea4580c1df6a74db2cde65"
1046+
integrity sha512-qACXdu/9VHPBzcyhdOWR5/IahhGMf0roTeZJfzz077GwylcDd90yOHLouhmv7GJ5XzPi6ekaQWd8AvPP2nOvpA==
1047+
dependencies:
1048+
duplexer "^0.1.1"
1049+
from "^0.1.7"
1050+
map-stream "0.0.7"
1051+
pause-stream "^0.0.11"
1052+
split "^1.0.1"
1053+
stream-combiner "^0.2.2"
1054+
through "^2.3.8"
1055+
10151056
extract-zip@^2.0.1:
10161057
version "2.0.1"
10171058
resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a"
@@ -1116,6 +1157,11 @@ form-data@^4.0.0:
11161157
combined-stream "^1.0.8"
11171158
mime-types "^2.1.12"
11181159

1160+
from@^0.1.7:
1161+
version "0.1.7"
1162+
resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe"
1163+
integrity sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==
1164+
11191165
fs-extra@^10.0.0, fs-extra@^10.1.0:
11201166
version "10.1.0"
11211167
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf"
@@ -1302,6 +1348,11 @@ hasown@^2.0.0:
13021348
dependencies:
13031349
function-bind "^1.1.2"
13041350

1351+
hexy@^0.3.5:
1352+
version "0.3.5"
1353+
resolved "https://registry.yarnpkg.com/hexy/-/hexy-0.3.5.tgz#adcd5ee47d66aca3581d771743a509a5176e45f9"
1354+
integrity sha512-UCP7TIZPXz5kxYJnNOym+9xaenxCLor/JyhKieo8y8/bJWunGh9xbhy3YrgYJUQ87WwfXGm05X330DszOfINZw==
1355+
13051356
hosted-git-info@^4.1.0:
13061357
version "4.1.0"
13071358
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224"
@@ -1585,6 +1636,11 @@ lucid-log@^0.0.3:
15851636
dependencies:
15861637
chalk "^4.1.2"
15871638

1639+
1640+
version "0.0.7"
1641+
resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.0.7.tgz#8a1f07896d82b10926bd3744a2420009f88974a8"
1642+
integrity sha512-C0X0KQmGm3N2ftbTGBhSyuydQ+vV1LC3f3zPvT3RXHXNZrvfPZcoXp/N5DOa8vedX/rTMm2CjTtivFg2STJMRQ==
1643+
15881644
matcher@^3.0.0:
15891645
version "3.0.0"
15901646
resolved "https://registry.yarnpkg.com/matcher/-/matcher-3.0.0.tgz#bd9060f4c5b70aa8041ccc6f80368760994f30ca"
@@ -1821,6 +1877,13 @@ path-scurry@^1.10.2:
18211877
lru-cache "^10.2.0"
18221878
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
18231879

1880+
pause-stream@^0.0.11:
1881+
version "0.0.11"
1882+
resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445"
1883+
integrity sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==
1884+
dependencies:
1885+
through "~2.3"
1886+
18241887
pend@~1.2.0:
18251888
version "1.2.0"
18261889
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
@@ -1951,6 +2014,11 @@ run-parallel@^1.1.9:
19512014
dependencies:
19522015
queue-microtask "^1.2.2"
19532016

2017+
safe-buffer@^5.1.2:
2018+
version "5.2.1"
2019+
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
2020+
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
2021+
19542022
"safer-buffer@>= 2.1.2 < 3.0.0":
19552023
version "2.1.2"
19562024
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
@@ -1963,6 +2031,11 @@ sanitize-filename@^1.6.3:
19632031
dependencies:
19642032
truncate-utf8-bytes "^1.0.0"
19652033

2034+
sax@>=0.6.0:
2035+
version "1.4.1"
2036+
resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f"
2037+
integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==
2038+
19662039
sax@^1.2.4:
19672040
version "1.3.0"
19682041
resolved "https://registry.yarnpkg.com/sax/-/sax-1.3.0.tgz#a5dbe77db3be05c9d1ee7785dbd3ea9de51593d0"
@@ -2043,6 +2116,13 @@ source-map@^0.6.0:
20432116
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
20442117
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
20452118

2119+
split@^1.0.1:
2120+
version "1.0.1"
2121+
resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9"
2122+
integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==
2123+
dependencies:
2124+
through "2"
2125+
20462126
sprintf-js@^1.1.2:
20472127
version "1.1.3"
20482128
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a"
@@ -2053,6 +2133,14 @@ stat-mode@^1.0.0:
20532133
resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-1.0.0.tgz#68b55cb61ea639ff57136f36b216a291800d1465"
20542134
integrity sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==
20552135

2136+
stream-combiner@^0.2.2:
2137+
version "0.2.2"
2138+
resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.2.2.tgz#aec8cbac177b56b6f4fa479ced8c1912cee52858"
2139+
integrity sha512-6yHMqgLYDzQDcAkL+tjJDC5nSNuNIx0vZtRZeiPh7Saef7VHX9H5Ijn9l2VIol2zaNYlYEX6KyuT/237A58qEQ==
2140+
dependencies:
2141+
duplexer "~0.1.1"
2142+
through "~2.3.4"
2143+
20562144
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
20572145
version "4.2.3"
20582146
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
@@ -2129,6 +2217,11 @@ text-table@^0.2.0:
21292217
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
21302218
integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==
21312219

2220+
through@2, through@^2.3.8, through@~2.3, through@~2.3.4:
2221+
version "2.3.8"
2222+
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
2223+
integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==
2224+
21322225
tmp-promise@^3.0.2:
21332226
version "3.0.3"
21342227
resolved "https://registry.yarnpkg.com/tmp-promise/-/tmp-promise-3.0.3.tgz#60a1a1cc98c988674fcbfd23b6e3367bdeac4ce7"
@@ -2241,11 +2334,24 @@ wrappy@1:
22412334
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
22422335
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
22432336

2337+
xml2js@^0.6.2:
2338+
version "0.6.2"
2339+
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499"
2340+
integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==
2341+
dependencies:
2342+
sax ">=0.6.0"
2343+
xmlbuilder "~11.0.0"
2344+
22442345
xmlbuilder@>=11.0.1, xmlbuilder@^15.1.1:
22452346
version "15.1.1"
22462347
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-15.1.1.tgz#9dcdce49eea66d8d10b42cae94a79c3c8d0c2ec5"
22472348
integrity sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==
22482349

2350+
xmlbuilder@~11.0.0:
2351+
version "11.0.1"
2352+
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3"
2353+
integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==
2354+
22492355
y18n@^5.0.5:
22502356
version "5.0.8"
22512357
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"

0 commit comments

Comments
 (0)