@react-native-windows/cli 0.80.0-preview.6 → 0.80.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.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-native-windows/cli",
|
|
3
|
-
"version": "0.80.0
|
|
3
|
+
"version": "0.80.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "lib-commonjs/index.js",
|
|
6
6
|
"repository": {
|
|
@@ -17,10 +17,10 @@
|
|
|
17
17
|
"watch": "rnw-scripts watch"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@react-native-windows/codegen": "0.80.0
|
|
21
|
-
"@react-native-windows/fs": "0.80.0
|
|
22
|
-
"@react-native-windows/package-utils": "0.80.0
|
|
23
|
-
"@react-native-windows/telemetry": "0.80.0
|
|
20
|
+
"@react-native-windows/codegen": "0.80.0",
|
|
21
|
+
"@react-native-windows/fs": "0.80.0",
|
|
22
|
+
"@react-native-windows/package-utils": "0.80.0",
|
|
23
|
+
"@react-native-windows/telemetry": "0.80.0",
|
|
24
24
|
"@xmldom/xmldom": "^0.7.7",
|
|
25
25
|
"chalk": "^4.1.0",
|
|
26
26
|
"cli-spinners": "^2.2.0",
|
|
@@ -73,11 +73,11 @@
|
|
|
73
73
|
"src/powershell"
|
|
74
74
|
],
|
|
75
75
|
"beachball": {
|
|
76
|
-
"defaultNpmTag": "
|
|
76
|
+
"defaultNpmTag": "latest",
|
|
77
77
|
"disallowedChangeTypes": [
|
|
78
78
|
"major",
|
|
79
79
|
"minor",
|
|
80
|
-
"
|
|
80
|
+
"prerelease",
|
|
81
81
|
"premajor",
|
|
82
82
|
"preminor",
|
|
83
83
|
"prepatch"
|
|
@@ -16,6 +16,13 @@
|
|
|
16
16
|
specific language governing permissions and limitations
|
|
17
17
|
under the License.
|
|
18
18
|
#>
|
|
19
|
+
|
|
20
|
+
# SDL CE.10116 SECURITY FIX: Removed PowerShell injection vulnerabilities
|
|
21
|
+
# - Replaced Invoke-Expression with direct cmdlet invocation
|
|
22
|
+
# - Implemented parameterized ScriptBlock pattern for elevated execution
|
|
23
|
+
# - Added input validation for package IDs and paths
|
|
24
|
+
# Date: October 14, 2025
|
|
25
|
+
|
|
19
26
|
$code = @"
|
|
20
27
|
using System;
|
|
21
28
|
using System.Runtime.CompilerServices;
|
|
@@ -53,21 +60,150 @@ namespace StoreAppRunner
|
|
|
53
60
|
}
|
|
54
61
|
"@
|
|
55
62
|
|
|
63
|
+
#region Security Helper Functions
|
|
64
|
+
|
|
65
|
+
<#
|
|
66
|
+
.SYNOPSIS
|
|
67
|
+
Validates package identifier format to prevent injection attacks.
|
|
68
|
+
.DESCRIPTION
|
|
69
|
+
Ensures package ID contains only safe characters and matches expected format.
|
|
70
|
+
SDL CE.10116 compliance - prevents PowerShell injection via package names.
|
|
71
|
+
#>
|
|
72
|
+
function Validate-PackageIdentifier {
|
|
73
|
+
param(
|
|
74
|
+
[Parameter(Mandatory=$true)]
|
|
75
|
+
[string]$PackageId
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
# Valid format: alphanumeric, dots, hyphens, underscores only
|
|
79
|
+
if ($PackageId -notmatch '^[a-zA-Z0-9\.\-_]+$') {
|
|
80
|
+
throw "Invalid package identifier format. Only alphanumeric characters, dots, hyphens, and underscores are allowed."
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
# Prevent common injection patterns
|
|
84
|
+
$dangerousPatterns = @(';', '|', '&', '$', '`', '<', '>', "`n", "`r", '(', ')', '{', '}')
|
|
85
|
+
foreach ($pattern in $dangerousPatterns) {
|
|
86
|
+
if ($PackageId.Contains($pattern)) {
|
|
87
|
+
throw "Package identifier contains forbidden characters: $pattern"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return $true
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
<#
|
|
95
|
+
.SYNOPSIS
|
|
96
|
+
Validates and canonicalizes script path to prevent path traversal attacks.
|
|
97
|
+
.DESCRIPTION
|
|
98
|
+
Ensures path is a valid .ps1 file and resolves to canonical path.
|
|
99
|
+
SDL CE.10116 compliance - prevents path injection attacks.
|
|
100
|
+
#>
|
|
101
|
+
function Validate-ScriptPath {
|
|
102
|
+
param(
|
|
103
|
+
[Parameter(Mandatory=$true)]
|
|
104
|
+
[string]$Path
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
# Check file exists
|
|
108
|
+
if (!(Test-Path $Path -PathType Leaf)) {
|
|
109
|
+
throw "Script path does not exist: $Path"
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
# Check .ps1 extension
|
|
113
|
+
if ([System.IO.Path]::GetExtension($Path) -ne '.ps1') {
|
|
114
|
+
throw "Path must reference a PowerShell script (.ps1)"
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
# Get canonical path (prevents ../ traversal)
|
|
118
|
+
$canonicalPath = [System.IO.Path]::GetFullPath($Path)
|
|
119
|
+
|
|
120
|
+
return $canonicalPath
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
<#
|
|
124
|
+
.SYNOPSIS
|
|
125
|
+
Executes a ScriptBlock with optional elevation using parameterized approach.
|
|
126
|
+
.DESCRIPTION
|
|
127
|
+
SDL CE.10116 compliant - uses ScriptBlock with ArgumentList instead of string concatenation.
|
|
128
|
+
Prevents PowerShell injection attacks by properly isolating parameters.
|
|
129
|
+
#>
|
|
130
|
+
function Invoke-ElevatedScriptBlock {
|
|
131
|
+
param(
|
|
132
|
+
[Parameter(Mandatory=$true)]
|
|
133
|
+
[ScriptBlock]$ScriptBlock,
|
|
134
|
+
|
|
135
|
+
[Parameter(Mandatory=$false)]
|
|
136
|
+
[object[]]$ArgumentList = @()
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
if (!(IsElevated)) {
|
|
140
|
+
# Serialize ScriptBlock and arguments for elevated execution
|
|
141
|
+
$encodedCommand = [Convert]::ToBase64String(
|
|
142
|
+
[System.Text.Encoding]::Unicode.GetBytes($ScriptBlock.ToString())
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
$encodedArgs = [Convert]::ToBase64String(
|
|
146
|
+
[System.Text.Encoding]::Unicode.GetBytes(
|
|
147
|
+
($ArgumentList | ConvertTo-Json -Compress -Depth 10)
|
|
148
|
+
)
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
# Create secure argument list (no string interpolation)
|
|
152
|
+
$startArgs = @(
|
|
153
|
+
'-NoProfile',
|
|
154
|
+
'-NonInteractive',
|
|
155
|
+
'-Command',
|
|
156
|
+
"& ([ScriptBlock]::Create([System.Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('$encodedCommand')))) @(ConvertFrom-Json ([System.Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('$encodedArgs'))))"
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
$process = Start-Process PowerShell -ArgumentList $startArgs `
|
|
160
|
+
-Verb RunAs -Wait -PassThru -WindowStyle Hidden -ErrorAction Stop
|
|
161
|
+
|
|
162
|
+
if ($process.ExitCode -ne 0) {
|
|
163
|
+
throw "Elevated command failed with exit code $($process.ExitCode)"
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
# Already elevated, execute directly with splatting
|
|
168
|
+
& $ScriptBlock @ArgumentList
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
#endregion
|
|
173
|
+
|
|
174
|
+
#region Core Functions
|
|
175
|
+
|
|
176
|
+
<#
|
|
177
|
+
.SYNOPSIS
|
|
178
|
+
Uninstalls an AppX package by package identifier.
|
|
179
|
+
.DESCRIPTION
|
|
180
|
+
SDL CE.10116 FIX: Replaced Invoke-Expression with direct Remove-AppxPackage cmdlet.
|
|
181
|
+
Uses parameterized ScriptBlock for elevated execution.
|
|
182
|
+
#>
|
|
56
183
|
function Uninstall-App {
|
|
57
184
|
param(
|
|
58
185
|
[Parameter(Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]
|
|
59
186
|
[string] $ID <# package.appxmanifest//Identity@name #>
|
|
60
187
|
)
|
|
61
188
|
|
|
189
|
+
# SDL FIX: Validate package ID to prevent injection
|
|
190
|
+
Validate-PackageIdentifier -PackageId $ID | Out-Null
|
|
191
|
+
|
|
62
192
|
$package = Get-AppxPackage $ID
|
|
63
193
|
|
|
64
194
|
if($package) {
|
|
65
195
|
$pfn = $package.PackageFullName
|
|
66
|
-
|
|
196
|
+
|
|
197
|
+
# SDL FIX: Direct cmdlet invocation instead of Invoke-Expression
|
|
67
198
|
try {
|
|
68
|
-
|
|
199
|
+
Remove-AppxPackage $pfn -ErrorAction Stop
|
|
69
200
|
} catch {
|
|
70
|
-
|
|
201
|
+
# SDL FIX: Use parameterized ScriptBlock for elevation
|
|
202
|
+
$scriptBlock = {
|
|
203
|
+
param($PackageFullName)
|
|
204
|
+
Remove-AppxPackage $PackageFullName -ErrorAction Stop
|
|
205
|
+
}
|
|
206
|
+
Invoke-ElevatedScriptBlock -ScriptBlock $scriptBlock -ArgumentList @($pfn)
|
|
71
207
|
}
|
|
72
208
|
}
|
|
73
209
|
}
|
|
@@ -91,44 +227,60 @@ function IsElevated {
|
|
|
91
227
|
return [bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544");
|
|
92
228
|
}
|
|
93
229
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
} else {
|
|
103
|
-
throw "Process creation failed for $Command";
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
function Invoke-Expression-MayElevate([string]$Command) {
|
|
108
|
-
if (!(IsElevated))
|
|
109
|
-
{
|
|
110
|
-
RunElevatedPowerShellSync($Command) -ErrorAction Stop
|
|
111
|
-
}
|
|
112
|
-
else
|
|
113
|
-
{
|
|
114
|
-
Invoke-Expression ("& $Command") -ErrorAction Stop
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
230
|
+
<#
|
|
231
|
+
.SYNOPSIS
|
|
232
|
+
Enables developer mode by setting registry keys.
|
|
233
|
+
.DESCRIPTION
|
|
234
|
+
SDL CE.10116 FIX: Replaced Invoke-Expression-MayElevate with direct cmdlet calls
|
|
235
|
+
and parameterized ScriptBlock for elevation.
|
|
236
|
+
#>
|
|
118
237
|
function EnableDevmode {
|
|
119
238
|
$RegistryKeyPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock"
|
|
120
239
|
|
|
240
|
+
# Create registry key if it doesn't exist
|
|
121
241
|
if (-not(Test-Path -Path $RegistryKeyPath)) {
|
|
122
|
-
|
|
242
|
+
if (!(IsElevated)) {
|
|
243
|
+
$scriptBlock = {
|
|
244
|
+
param($Path)
|
|
245
|
+
New-Item -Path $Path -ItemType Directory -Force | Out-Null
|
|
246
|
+
}
|
|
247
|
+
Invoke-ElevatedScriptBlock -ScriptBlock $scriptBlock -ArgumentList @($RegistryKeyPath)
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
New-Item -Path $RegistryKeyPath -ItemType Directory -Force | Out-Null
|
|
251
|
+
}
|
|
123
252
|
}
|
|
124
253
|
|
|
125
|
-
|
|
254
|
+
# SDL FIX: Direct cmdlet invocation for AllowDevelopmentWithoutDevLicense
|
|
255
|
+
$value = Get-ItemProperty -Path $RegistryKeyPath -Name AllowDevelopmentWithoutDevLicense -ErrorAction SilentlyContinue
|
|
126
256
|
if (($value -eq $null) -or ($value.AllowDevelopmentWithoutDevLicense -ne 1)) {
|
|
127
|
-
|
|
257
|
+
if (!(IsElevated)) {
|
|
258
|
+
$scriptBlock = {
|
|
259
|
+
param($Path, $Name, $Value)
|
|
260
|
+
Set-ItemProperty -Path $Path -Name $Name -Value $Value -ErrorAction Stop
|
|
261
|
+
}
|
|
262
|
+
Invoke-ElevatedScriptBlock -ScriptBlock $scriptBlock `
|
|
263
|
+
-ArgumentList @($RegistryKeyPath, 'AllowDevelopmentWithoutDevLicense', 1)
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
Set-ItemProperty -Path $RegistryKeyPath -Name AllowDevelopmentWithoutDevLicense -Value 1 -ErrorAction Stop
|
|
267
|
+
}
|
|
128
268
|
}
|
|
129
|
-
|
|
269
|
+
|
|
270
|
+
# SDL FIX: Direct cmdlet invocation for AllowAllTrustedApps
|
|
271
|
+
$value = Get-ItemProperty -Path $RegistryKeyPath -Name AllowAllTrustedApps -ErrorAction SilentlyContinue
|
|
130
272
|
if (($value -eq $null) -or ($value.AllowAllTrustedApps -ne 1)) {
|
|
131
|
-
|
|
273
|
+
if (!(IsElevated)) {
|
|
274
|
+
$scriptBlock = {
|
|
275
|
+
param($Path, $Name, $Value)
|
|
276
|
+
Set-ItemProperty -Path $Path -Name $Name -Value $Value -ErrorAction Stop
|
|
277
|
+
}
|
|
278
|
+
Invoke-ElevatedScriptBlock -ScriptBlock $scriptBlock `
|
|
279
|
+
-ArgumentList @($RegistryKeyPath, 'AllowAllTrustedApps', 1)
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
Set-ItemProperty -Path $RegistryKeyPath -Name AllowAllTrustedApps -Value 1 -ErrorAction Stop
|
|
283
|
+
}
|
|
132
284
|
}
|
|
133
285
|
}
|
|
134
286
|
|
|
@@ -174,22 +326,44 @@ function CheckIfNeedInstallCertificate
|
|
|
174
326
|
return (-not $Valid)
|
|
175
327
|
}
|
|
176
328
|
|
|
329
|
+
<#
|
|
330
|
+
.SYNOPSIS
|
|
331
|
+
Installs an app package using Add-AppDevPackage.ps1 script.
|
|
332
|
+
.DESCRIPTION
|
|
333
|
+
SDL CE.10116 FIX: Replaced Invoke-Expression with call operator (&) and
|
|
334
|
+
parameterized ScriptBlock for elevated execution.
|
|
335
|
+
#>
|
|
177
336
|
function Install-App {
|
|
178
337
|
param(
|
|
179
338
|
[Parameter(Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]
|
|
180
339
|
[string] $Path, <# Full path to Add-AppDevPackage.ps1 #>
|
|
181
340
|
[switch] $Force = $false
|
|
182
341
|
)
|
|
183
|
-
|
|
342
|
+
|
|
343
|
+
# SDL FIX: Validate script path
|
|
344
|
+
$Path = Validate-ScriptPath -Path $Path
|
|
345
|
+
|
|
346
|
+
$needInstallCertificate = CheckIfNeedInstallCertificate (Join-Path $Path "..")
|
|
347
|
+
|
|
184
348
|
if (!$Force -and ((CheckIfNeedDeveloperLicense) -or ($needInstallCertificate)))
|
|
185
349
|
{
|
|
186
|
-
#
|
|
187
|
-
|
|
350
|
+
# SDL FIX: Use call operator (&) instead of Invoke-Expression
|
|
351
|
+
# No user input in path (validated above), so safe to execute
|
|
352
|
+
& $Path
|
|
188
353
|
}
|
|
189
354
|
else
|
|
190
355
|
{
|
|
191
|
-
|
|
192
|
-
|
|
356
|
+
# SDL FIX: Use parameterized ScriptBlock for elevation
|
|
357
|
+
if (!(IsElevated)) {
|
|
358
|
+
$scriptBlock = {
|
|
359
|
+
param($ScriptPath)
|
|
360
|
+
& $ScriptPath -Force
|
|
361
|
+
}
|
|
362
|
+
Invoke-ElevatedScriptBlock -ScriptBlock $scriptBlock -ArgumentList @($Path)
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
& $Path -Force
|
|
366
|
+
}
|
|
193
367
|
}
|
|
194
368
|
}
|
|
195
369
|
|
|
@@ -220,6 +394,9 @@ function Start-Locally {
|
|
|
220
394
|
[string[]] $argv
|
|
221
395
|
)
|
|
222
396
|
|
|
397
|
+
# SDL FIX: Validate package ID
|
|
398
|
+
Validate-PackageIdentifier -PackageId $ID | Out-Null
|
|
399
|
+
|
|
223
400
|
$package = Get-AppxPackage $ID
|
|
224
401
|
$manifest = Get-appxpackagemanifest $package
|
|
225
402
|
$applicationUserModelId = $package.PackageFamilyName + "!" + $manifest.package.applications.application.id
|
|
@@ -240,7 +417,6 @@ function Start-Locally {
|
|
|
240
417
|
}
|
|
241
418
|
}
|
|
242
419
|
|
|
243
|
-
|
|
244
420
|
function Map-PackageNameToPackage {
|
|
245
421
|
param([Parameter(Mandatory=$true)] [string]$DependenciesPath)
|
|
246
422
|
$mapP2N = @{};
|
|
@@ -272,3 +448,18 @@ function Install-AppDependencies {
|
|
|
272
448
|
$packagePaths = $packageNamesToInstall | % { $map[$_] }
|
|
273
449
|
$packagePaths | % { Add-AppxPackage -Path $_ }
|
|
274
450
|
}
|
|
451
|
+
|
|
452
|
+
#endregion
|
|
453
|
+
|
|
454
|
+
# Export functions
|
|
455
|
+
Export-ModuleMember -Function @(
|
|
456
|
+
'Uninstall-App',
|
|
457
|
+
'EnableDevmode',
|
|
458
|
+
'CheckIfNeedDeveloperLicense',
|
|
459
|
+
'CheckIfNeedInstallCertificate',
|
|
460
|
+
'Install-App',
|
|
461
|
+
'Install-AppFromDirectory',
|
|
462
|
+
'Install-AppFromAppx',
|
|
463
|
+
'Start-Locally',
|
|
464
|
+
'Install-AppDependencies'
|
|
465
|
+
)
|