Skip to content

Align package broker requests with the broker's request validation - #5467

Open
Benoît Cortier (CBenoit) wants to merge 18 commits into
mainfrom
cbenoit-package-broker-request-alignment
Open

Benoît Cortier (CBenoit) wants to merge 18 commits into
mainfrom
cbenoit-package-broker-request-alignment

Conversation

@CBenoit

@CBenoit Benoît Cortier (CBenoit) commented Oct 2, 2026 •

Copy link
Copy Markdown
Member
  • I have read the contributing guidelines, and I agree with the Code of Conduct.
  • Have you checked that there aren't other open pull requests for the same changes?
  • Have you tested that the committed code can be executed without errors?
  • Have you confirmed that this issue is caused by UniGetUI itself, and not by the package manager or the package involved?
    If the same issue can be reproduced outside UniGetUI with the relevant package manager or with the package itself, please report it there first. UniGetUI should only be used to track issues that are specific to UniGetUI's behavior or integration.

Aligns the Devolutions Agent package broker integration with the broker's request validation, and makes broker outcomes understandable to the user.

Send resolved package versions to the package broker (BrokerRequestBuilder)

  • The broker evaluates version conditions against the version in the request, so UniGetUI now sends the version it already knows:
    • the version the user selected;
    • otherwise the listed version, for an install;
    • otherwise the target version, for an update.
  • No version is sent:
    • for uninstalls;
    • for Scoop and vcpkg;
    • for pre-release installs;
    • for managers without broker version rules;
    • when the known version would not be accepted for that manager.
  • A version saved for installs never blocks an update or an uninstall.
  • Fields the broker refuses for a role or a manager are left out:
    • pre-release, hash-check skip and architecture for uninstalls;
    • architecture for Scoop updates;
    • the source URL for managers that identify their source by name;
    • blank custom parameters.
  • Scope and architecture are sent when chosen.
  • The PowerShell -AllowClobber retry is not sent, because the broker accepts no PowerShell parameter. The command conflict is reported instead.
  • "Update all" already creates one operation per package.

Validate package broker request fields (BrokerRequestValidator, new)

  • Mirrors the broker's rules, with localized explanations:
    • API-wide identifier, version and custom-parameter bounds;
    • command-line safety guards;
    • per-manager identifier rules: Chocolatey NuGet ids, Scoop single names, PowerShell names without wildcards, npm/Bun registry names, crates, pip distributions;
    • per-manager version allowlists, including ranges and canonical SemVer for Bun;
    • source names;
    • characters refused by batch-script managers;
    • install location as a plain local drive path;
    • Scoop custom parameters, and managers that accept no custom parameters;
    • per-manager option support: scope, architecture, pre-release, interactive, hash check, install location, uninstall-previous;
    • elevation-dependent rules: per-user managers, and pre/post commands on elevated or machine-scope operations.
  • The broker stays the authority. A request it would reject is not sent, and the failure lists every problem.
  • The installation options dialog previews the same problems live: it dry-runs the request builder after applying the manager's elevation requirements. Changes are announced through the shared accessibility live region.

WinGet custom installer arguments

  • The dialog warns when --override/--custom, or any custom argument on an elevated operation, goes through the Devolutions Agent. These arguments reach an installer running with administrator rights, and the organization's policy may block them.

Explain package broker policy decisions (BrokerFailureDescriber, new)

  • Specific messages for:
    • policy denial, with rule id and reason;
    • validation failures, with the broker's message and details;
    • paused (no valid policy) versus busy (after the client's retries);
    • Forbidden, keeping the broker's reason (for example policy validity);
    • administrator required;
    • request too large, unsupported option, timeout, invalid response.
  • The capabilities request is made up front. If the broker refuses this client (401/403, for example an unsigned build), the operation explains why and raises BrokerUnavailable, which now carries the specific title.
  • In the policy editor, a save refused because an elevated administrator is required, or because the client is not authorized, gets a specific message.

The pipe transport, server verification and retry handling are unchanged. New strings were added to lang_en.json only.

Validation (from src/):

  • dotnet test UniGetUI.PackageEngine.Tests/UniGetUI.PackageEngine.Tests.csproj /p:Platform=x64 --filter "FullyQualifiedName~Broker|FullyQualifiedName~PackageOperationsTests": passed (448 for the Windows target, 436 for net10.0).
  • dotnet test UniGetUI.PackageEngine.Tests/UniGetUI.PackageEngine.Tests.csproj /p:Platform=x64 (full): passed for net10.0. On the Windows target, only PowerShellOperationLauncherTests.TheScopeRetryMarkersSurviveTheLauncher failed; it also fails on main in my environment.
  • dotnet test UniGetUI.Tests/UniGetUI.Tests.csproj /p:Platform=x64: passed (553).
  • dotnet format whitespace and dotnet format style UniGetUI.Windows.slnx --no-restore --verify-no-changes on the changed files: passed.
  • pwsh ./scripts/translation/Verify-Translations.ps1: passed.

Not tested: end to end against a running Devolutions Agent with the updated broker, and the dialog notices in the running app.

Send the resolved package version to the package broker: the version the
user selected, else the listed version for installs and the target version
for updates, omitting versions the broker does not accept for the manager
and never sending one for uninstalls or for managers that pin their own.

Validate package broker request fields before sending them (install
location, versions, package identifiers, source names, custom parameters,
architecture) and explain each problem in the operation failure and in the
installation options dialog.

Warn in the installation options dialog when WinGet custom installer
arguments go through the Devolutions Agent.

Explain package broker policy decisions and errors: show the denying rule
and reason, validation messages, paused and busy states, and authorization
failures, including when the broker refuses the capabilities request and
when a policy change requires an elevated administrator.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Version handling and live option validation still diverge from the requests ultimately sent to the broker.

Review effort: Balanced
Findings: 3 Medium severity

Open (3)
What changed in this PR

Aligns broker requests with stricter validation and improves user-facing broker failure reporting.

Changes:

  • Adds broker request validation and resolved-version handling.
  • Provides detailed policy, authorization, and transport errors.
  • Adds live broker warnings to installation options.
File Description
PolicyEditorStructuredInputGuardTests.cs Tests authorization messages.
PackageOperationsTests.cs Tests broker operation failures and versions.
BrokerRequestBuilderTests.cs Tests request validation rules.
BrokerFailureDescriberTests.cs Tests failure descriptions.
PackageOperations.cs Integrates capability probing and detailed failures.
BrokerRequestValidator.cs Implements broker-compatible validation.
BrokerRequestBuilder.cs Resolves versions and validates requests.
BrokerFailureDescriber.cs Produces localized failure explanations.
InstallOptionsControl.axaml Displays broker notices.
PolicyEditorDialogViewModel.cs Clarifies policy authorization failures.
InstallOptionsViewModel.cs Computes live broker warnings.
lang_en.json Adds localized English strings.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/UniGetUI.Avalonia/ViewModels/DialogPages/InstallOptionsViewModel.cs Outdated
Comment thread src/UniGetUI.PackageEngine.AgentBroker/BrokerRequestBuilder.cs
Comment thread src/UniGetUI.PackageEngine.AgentBroker/BrokerRequestValidator.cs
…eration

Share the brokered install location resolver with the installation options dialog, validate versions of managers with broker version rules only against those rules, and bound Bun version length.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Pre-release updates can omit known versions, and several broker warnings or authorization messages can be stale or misleading.

Review effort: Balanced
Findings: None

Resolved since last review (3)
Previously missed (4)

In code that hasn't changed since last review

Medium severity Prevent stale asynchronous refresh results from overwriting current state

src/​UniGetUI.Avalonia/​ViewModels/​DialogPages/​InstallOptionsViewModel.cs:552

These live results can be overwritten by an older refresh. Every edit starts a fire-and-forget RefreshCommandPreviewAsync, and each call performs multiple asynchronous loads; if a previous call completes after a later one, it assigns validation text for stale options and may leave the dialog showing or hiding the wrong broker warning. Add a monotonically increasing refresh generation or cancellation token and only publish results from the latest invocation.

Medium severity Include metadata-driven elevation in custom argument warnings

src/​UniGetUI.Avalonia/​ViewModels/​DialogPages/​InstallOptionsViewModel.cs:581

This warning only treats the checkbox value as elevation, but the broker path also elevates when WinGet metadata sets package.OverridenOptions.RunAsAdministrator in ApplyElevationRequirements (PackageOperations.cs:392-400, WinGetPkgOperationHelper.cs:217-275). Because command preview applies that metadata before this method runs, an installer that automatically requires elevation can still receive arbitrary custom arguments without the promised warning. Match the same elevation predicate used by the operation.

Medium severity Restrict pre-release suppression to install operations

src/​UniGetUI.PackageEngine.AgentBroker/​BrokerRequestBuilder.cs:189

Pre-release suppression currently applies to updates as well as installs. InstallOptions.PreRelease can remain enabled on an update, so this returns null instead of sending the known NewVersionString, contrary to the intended exception for pre-release installs only. Restrict this branch to OperationType.Install.

Medium severity Preserve authorization failure details in broker error dialogs

src/​UniGetUI.PackageEngine.Operations/​PackageOperations.cs:565

The new authorization failure is raised through BrokerUnavailable, whose only production subscriber still opens SimpleErrorDialog with the hard-coded title “Agent broker unavailable” (AvaloniaBootstrapper.cs:140-150). For a 401/403 the agent is available but rejecting this client, so the immediate user-facing dialog loses the specific authorization title computed above and remains misleading. Carry the full failure description (or otherwise pass its title) through this notification path.

Publish only the latest options-dialog broker check, use the operation's elevation predicate for the WinGet custom arguments warning, keep the target version for pre-release updates, and pass the specific failure title to the broker notification dialog.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@CBenoit

Copy link
Copy Markdown
Member Author

Addressed the four 'previously missed' review notes in 1e2b9af: (1) the options dialog publishes only the latest broker check (refresh generation); (2) the WinGet custom-arguments warning uses the operation's elevation predicate (package requirement or checkbox, respecting ProhibitElevation); (3) the pre-release exception now only applies to installs, so updates keep their target version; (4) BrokerUnavailable now carries the full title and message, so a refused client shows the authorization title instead of 'Agent broker unavailable'.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Source mapping, PowerShell parameters, and paused-broker responses remain inconsistent with the broker contract.

Review effort: Balanced
Findings: None

Previously missed (3)

In code that hasn't changed since last review

Medium severity Map structured BrokerPaused responses to 409 instead of busy 503

src/​UniGetUI.PackageEngine.AgentBroker/​BrokerFailureDescriber.cs:82

BrokerPaused is mapped to HTTP 503 by the broker server, including the “active policy is unavailable” path. Because this branch also accepts ErrorCode.BrokerPaused, a real paused response is always described as “busy” and the BrokerPaused switch case below is unreachable; the 409 test does not match the wire contract. Reserve this branch for an unstructured 503 so structured paused responses get the paused explanation.

Medium severity Validate or strip source URLs before broker submission

src/​UniGetUI.PackageEngine.AgentBroker/​BrokerRequestValidator.cs:56

This validates only the source name, but BrokerRequestBuilder still forwards package.Source.Url. The broker rejects non-null source URLs for Chocolatey, npm, pip, PowerShell, and PowerShell 7, while UniGetUI's default sources for all five managers have URLs, so normal requests for these managers still pass this preflight and are then rejected by the broker. Build a name-only RequestSource for those managers or mirror the broker's URL rules before submission.

Medium severity Validate PowerShell custom and broker-added parameters

src/​UniGetUI.PackageEngine.AgentBroker/​BrokerRequestValidator.cs:80

PowerShell custom parameters still bypass this preflight even though the broker's PowerShell command builder rejects every non-empty custom parameter. This also affects the automatic -AllowClobber retry because BrokerRequestBuilder appends it after Validate returns, so that retry is sent and rejected. Align the PowerShell parameter mapping with the broker and ensure broker-added parameters are validated too.

Omit the source URL for managers that identify sources by name, validate the custom parameters that are actually sent (including the PowerShell AllowClobber retry) and refuse them for managers that accept none, and tell a busy broker apart from a paused one.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…r-request-alignment

# Conflicts:
#	src/UniGetUI.PackageEngine.AgentBroker/BrokerRequestBuilder.cs
#	src/UniGetUI.PackageEngine.Tests/BrokerRequestBuilderTests.cs
@CBenoit

Copy link
Copy Markdown
Member Author

Addressed the three 'previously missed' notes in 75688c3: (1) a structured BrokerPaused response is described as paused unless its message reports the busy state, and only an unstructured 503 is treated as busy; tests now use the 503 wire status. (2) The source URL is omitted for managers that identify their source by name (Chocolatey, PowerShell, PowerShell 7, npm, Bun, Cargo, .NET Tool, pip, vcpkg). This also covers the pip change from #5466, merged from main. (3) The custom parameters that are actually sent, including the AllowClobber retry, are validated, and they are refused with an explanation for managers whose broker command builder accepts none.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The asynchronous broker notices do not use the established accessibility announcement service, and validator documentation conflicts with its behavior.

Review effort: Balanced
Findings: 1 Medium severity · 1 Low severity

Open (2)

Comment thread src/UniGetUI.PackageEngine.AgentBroker/BrokerRequestValidator.cs
Route changed broker validation problems (assertive) and custom-argument warnings (polite) through AccessibilityAnnouncementService, and describe the managers that refuse custom parameters as an explicit list.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Request validation still permits broker-rejected identifiers, parameters, and Bun versions, while irrelevant saved versions can block updates or uninstalls.

Review effort: Balanced
Findings: None

Resolved since last review (2)
Previously missed (4)

In code that hasn't changed since last review

Medium severity Version validation incorrectly blocks update and uninstall

src/​UniGetUI.PackageEngine.AgentBroker/​BrokerRequestBuilder.cs:190

ResolveVersion omits versions for updates and uninstalls, but Build still validates options.Version before calling it. A saved install-only value such as /latest therefore prevents an uninstall/update even though that value would not be sent. Gate both earlier version guards on role == Install, or validate only the resolved version.

Medium severity Missing universal PackageIdentifier validation

src/​UniGetUI.PackageEngine.AgentBroker/​BrokerRequestValidator.cs:246

This manager-specific switch omits the broker API's universal PackageIdentifier constraints. For example, a WinGet identifier longer than 256 characters passes IsOptionSafeIdentifier and this method, but the broker rejects it while deserializing the request; non-ASCII identifiers have the same gap for several managers. Apply the API-wide length/ASCII allowlist before the manager-specific rules so these requests fail locally with the promised explanation.

Medium severity Missing custom-parameter length validation

src/​UniGetUI.PackageEngine.AgentBroker/​BrokerRequestValidator.cs:321

The broker's custom-parameter type requires each value to contain 1–512 characters, but this validation only checks manager-specific content. A WinGet or Scoop argument longer than 512 characters therefore passes locally and is sent, only to be rejected during broker deserialization. Enforce the shared bounds before the manager-specific checks (and either omit or reject empty entries).

Medium severity SemVer validation accepts broker-invalid versions

src/​UniGetUI.PackageEngine.AgentBroker/​BrokerRequestValidator.cs:514

This regex is looser than the broker's SemVer parser: it accepts numeric prerelease identifiers with leading zeroes (for example 1.2.3-01) and arbitrarily large numeric components, both of which the broker rejects. As a result, Bun requests advertised as valid locally still fail remotely. Use SemVer validation with the same canonical numeric rules and bounds as the broker.

Check package identifiers, custom parameters and versions against the API-wide length and character rules, use canonical SemVer rules for Bun, drop empty custom parameters, and ignore a saved install version for updates and uninstalls.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@CBenoit

Copy link
Copy Markdown
Member Author

Addressed the four 'previously missed' notes in b26f7c3: (1) the saved version is only checked, and only sent, for installs, so a stale value can no longer block an update or an uninstall; (2) package identifiers are checked against the broker API's universal 256-byte length and ASCII character set before the manager-specific rules; (3) custom parameters are bounded to 512 bytes, and empty entries are dropped from the request; (4) Bun versions follow canonical SemVer: no leading zeros in numeric pre-release identifiers, and release components must fit 64 bits.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Whitespace-only custom parameters can bypass local rejection and still be sent to the broker.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)

Comment thread src/UniGetUI.PackageEngine.AgentBroker/BrokerRequestBuilder.cs Outdated
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@CBenoit
Benoît Cortier (CBenoit) requested a balanced review from Copilot October 2, 2026 16:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Live validation can publish stale results, and PowerShell’s hidden AllowClobber retry produces a deterministic misleading failure.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)
Resolved since last review (2)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Avoid unsupported AllowClobber retry validation failure

src/​UniGetUI.PackageEngine.AgentBroker/​BrokerRequestBuilder.cs:54

This validation turns PowerShell's automatic CommandAlreadyAvailable recovery into a deterministic second failure. PowerShellPkgOperationHelper.GetResult sets the internal PowerShell_AllowClobber flag and returns AutoRetry; the next broker attempt appends -AllowClobber above, then fails here because PowerShell rejects all custom parameters. The resulting message tells users to remove an argument that is not present in their installation options. Brokered execution should suppress this unsupported retry or surface the original command-conflict failure directly.

Medium severity Align UTF-8 byte limit enforcement with error message

src/​UniGetUI.PackageEngine.AgentBroker/​BrokerRequestValidator.cs:442

The limit is enforced in UTF-8 bytes but reported as characters. For example, a 300-character CJK argument exceeds 512 bytes and produces the false claim that it is longer than 512 characters. Either compare parameter.Length if the broker limit is character-based, or change the localized message to say UTF-8 bytes.

Comment thread src/UniGetUI.Avalonia/ViewModels/DialogPages/InstallOptionsViewModel.cs Outdated
The broker accepts no PowerShell custom parameter, so the AllowClobber retry is no longer sent: the operation explains the command conflict instead. The options dialog orders whole refreshes (command preview included), and length limits are reported in bytes, as the broker counts them.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@CBenoit

Copy link
Copy Markdown
Member Author

Addressed the two 'previously missed' notes in 1377556. (1) The PowerShell AllowClobber retry is no longer sent through the broker: when that retry comes up, the operation reports the command conflict and explains that -AllowClobber can't be used through the Devolutions Agent. (2) Length limits are now reported in bytes, matching how the broker counts them.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

The live dialog validation does not apply manager-derived elevation requirements, so it can show broker-rejected WinGet options as acceptable.

Review effort: Balanced
Findings: None

Resolved since last review (1)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Apply elevation requirements before dialog preview validation

src/​UniGetUI.Avalonia/​ViewModels/​DialogPages/​InstallOptionsViewModel.cs:566

The dialog validates before applying the manager-specific elevation requirements that the real broker path applies at PackageOperations.cs:402-410. For a WinGet package whose installer metadata forces elevation, FindProblems therefore misses elevated pre/post-command rejection, and the later custom-argument warning also sees runsElevated == false; the operation then rejects options the dialog showed as acceptable. Apply the same elevation-requirement step before running the preview validation (without blocking the UI thread).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@CBenoit

Copy link
Copy Markdown
Member Author

Addressed the 'previously missed' note about elevation in 72852d0. The live dialog check now calls the manager's ApplyElevationRequirements off the UI thread before running FindProblems, as the brokered operation does. A WinGet installer that must run elevated is therefore checked, and warned about, as elevated.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Broker tests depend on ambient elevation settings, and blank inherited arguments can produce a false warning.

Review effort: Balanced
Findings: None

Previously missed (2)

In code that hasn't changed since last review

Medium severity Warning counts whitespace-only parameters as elevated arguments

src/​UniGetUI.Avalonia/​ViewModels/​DialogPages/​InstallOptionsViewModel.cs:619

The broker builder drops whitespace-only custom parameters, but this warning counts them and tells the user they will be passed to WinGet. Inherited or deserialized options containing only blank entries therefore show a false elevated-arguments warning. Use the same IsNullOrWhiteSpace filter as the request builder.

Medium severity Test depends on unisolated ProhibitElevation setting

src/​UniGetUI.PackageEngine.Tests/​BrokerRequestBuilderTests.cs:805

This assertion depends on the developer/runner setting ProhibitElevation being false. RequestsElevation deliberately ignores RunAsAdministrator when that setting is enabled (BrokerRequestValidator.cs:176-178), and this test class does not isolate or override the settings store, so Build succeeds instead of throwing under that valid configuration. Run this class with the isolated-settings fixture or explicitly scope ProhibitElevation to false for the test.

This issue also appears on line 811 of the same file.

… tests

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@CBenoit

Copy link
Copy Markdown
Member Author

Addressed the two 'previously missed' notes in 50d8e6f: (1) the elevated WinGet custom-arguments warning ignores blank arguments, using the same IsNullOrWhiteSpace filter as the request builder; (2) the elevation-dependent builder tests now set ProhibitElevation to false for their duration and restore it afterwards, so they don't depend on the machine's settings.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Several manager-, operation-, and source-specific broker rules are not mirrored correctly by the new validator.

Review effort: Balanced
Findings: None

Previously missed (4)

In code that hasn't changed since last review

Medium severity Validate pre-release support by manager and operation role

src/​UniGetUI.PackageEngine.AgentBroker/​BrokerRequestValidator.cs:117

PreRelease is never validated by manager or role. Npm exposes pre-release selection in UniGetUI, but the broker rejects every npm request with PreRelease=true; similarly, several managers reject it on uninstall. Because the dialog keeps this saved selection when switching profiles, these requests show no live issue and are still sent to be rejected. Add manager/role validation for this flag or clear it when unsupported.

Medium severity Validate architecture by manager and operation role

src/​UniGetUI.PackageEngine.AgentBroker/​BrokerRequestValidator.cs:126

The architecture check only rejects arm32, but it misses manager/operation restrictions. For example, UniGetUI enables x86/x64/arm64 for Scoop updates, while the broker accepts Scoop architecture only for installs. Such an update passes FindProblems and the client's manager-level capability check, then is rejected by the execute endpoint. Validate architecture against both manager and role (or omit it when that role cannot use it).

Medium severity Validate machine scope against manager restrictions

src/​UniGetUI.PackageEngine.AgentBroker/​BrokerRequestValidator.cs:139

Machine scope is not covered by the manager restrictions here. Npm and Scoop both expose custom scopes in UniGetUI, so selecting the global scope maps to Scope.Machine, but the broker supports only Scope.User for those managers. The live validator therefore reports no problem; execution later fails capability validation instead of listing the invalid field. Mirror the broker's per-manager scope restrictions here.

Medium severity Validate original PowerShell source name without trimming

src/​UniGetUI.PackageEngine.AgentBroker/​BrokerRequestValidator.cs:404

Trimming PowerShell source names before validation creates a false negative. The original sourceName is serialized unchanged, while the broker explicitly rejects any source name with leading or trailing whitespace before policy evaluation. For example, " PSGallery" passes this check and is then rejected remotely. Validate the original spelling instead of its trimmed copy.

Report options the broker's command builder refuses for the manager (machine or user scope, architecture, pre-release, interactive, hash-check skip, install location, uninstall-previous, Cargo actions), stop sending pre-release, hash-check skip and architecture where the role ignores them, and check source names as sent.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@CBenoit

Copy link
Copy Markdown
Member Author

Addressed the four 'previously missed' notes in e8fc724. The validator now mirrors the broker's per-manager option rules for the values that are actually sent: machine or user scope, architecture (Scoop on install only; never on uninstall), pre-release, interactive, hash-check skip, install location, uninstall-previous, and Cargo's close-apps and pre/post actions. Pre-release, hash-check skip and architecture are no longer sent for uninstalls, matching the local path. PowerShell source names are checked as sent, without trimming.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Live validation omits Cargo close-app entries, allowing an operation to fail without the promised advance warning.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

It duplicates security-sensitive external broker rules and lacks end-to-end validation against the updated Agent.

Review effort: Balanced
Findings: None

Resolved since last review (1)

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

PowerShell architecture and install-location constraints remain inconsistent with the broker’s advertised capabilities.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)

Comment on lines +204 to +205
bool packageManagerPicksTheBuild = manager is ManagerName.Npm or ManagerName.Bun or ManagerName.Cargo
or ManagerName.Pip or ManagerName.Vcpkg;

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants