feat(agent,agent-installer): add policy consent helper - #1982
Benoît Cortier (CBenoit) wants to merge 24 commits into
Conversation
|
Implementation notes:
Note Human-tuned, LLM-assisted content. |
There was a problem hiding this comment.
🟡 Changes recommended
Version parsing and cancellation handling can reject valid callers or return incorrect protocol outcomes.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adds an elevated Agent policy-consent helper that authenticates UniGetUI and the Agent broker before forwarding policy updates.
Changes:
- Adds the NativeAOT consent helper, protocol, authentication, and tests.
- Restricts broker policy writes to the installed helper.
- Packages, signs, registers, and tests the helper in CI.
File summaries
| File | Description |
|---|---|
package/AgentWindowsManaged/Resources/Includes.cs |
Shares helper discovery constants. |
package/AgentWindowsManaged/Program.cs |
Installs and registers the helper. |
package/AgentWindowsManaged/DevolutionsAgent.csproj |
Links the shared contract. |
package/AgentWindowsManaged.Tests/PackageBrokerInstallerTests.cs |
Tests registry discovery. |
package/AgentPolicyConsent/Protocol.cs |
Defines helper framing and validation. |
package/AgentPolicyConsent/Program.cs |
Implements the helper workflow. |
package/AgentPolicyConsent/PolicyConsentContract.cs |
Defines identity and signer constants. |
package/AgentPolicyConsent/PeerTrust.cs |
Authenticates UI and broker processes. |
package/AgentPolicyConsent/DevolutionsAgentPolicyConsent.csproj |
Configures the NativeAOT executable. |
package/AgentPolicyConsent/BrokerClient.cs |
Forwards policy updates to the broker. |
package/AgentPolicyConsent/app.manifest |
Requires administrator elevation. |
package/AgentPolicyConsent.Tests/ProtocolTests.cs |
Tests protocol and trust behavior. |
package/AgentPolicyConsent.Tests/DevolutionsAgentPolicyConsent.Tests.csproj |
Configures helper tests. |
crates/now-package-broker/src/server/mod.rs |
Applies helper-specific write authentication. |
crates/now-package-broker/src/auth.rs |
Validates the installed helper identity. |
ci/package-agent-windows.ps1 |
Adds the helper to MSI packaging. |
.github/workflows/package.yml |
Signs and repackages the helper. |
.github/workflows/ci.yml |
Builds and tests the helper. |
Review details
- Files reviewed: 18/18 changed files
- Comments generated: 3
- Review effort level: Balanced
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
🔵 Needs a closer look
Helper credential validation does not conform to the canonical policy API character restrictions.
Review details
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
package/AgentPolicyConsent/Protocol.cs:71
- These fields are policy-store credentials, but
IsCredentialaccepts every printable ASCII character after the first one. The canonical policy API restricts store tokens and validation receipts to[A-Za-z0-9._~:-](now-librariesmanagement.rs,PolicyStoreToken/PolicyValidationReceipt), so values containing spaces, quotes, slashes, etc. pass this protocol boundary and are only rejected later by the broker. Apply the canonical character rule here (and to returned store tokens) so malformed helper requests fail as protocol errors rather than entering the privileged write path.
- Files reviewed: 18/18 changed files
- Comments generated: 0 new
- Review effort level: Balanced
There was a problem hiding this comment.
🔵 Needs a closer look
Security-critical native authentication, elevation, protocol, and multi-architecture packaging changes warrant final human review.
Review details
- Files reviewed: 18/18 changed files
- Comments generated: 0 new
- Review effort level: Balanced
3867fa3 to
3cce637
Compare
67a6419 to
a262d4b
Compare
a262d4b to
c5d59c2
Compare
c5d59c2 to
d2f50f3
Compare
d2f50f3 to
c1f0a22
Compare
Reject remote-provider parent images before retaining them for policy consent. Document every required local Agent package artifact argument. Issue: #1963 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Resolve the retained UniGetUI image path before trusting its local volume. Keep already-correct package inputs absolute while the MSI build changes directories. Issue: #1963 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Keep the bounded broker connection lifetime aligned with the consent helper's two-minute policy replacement exchange. Issue: #1963 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Keep ordinary pipe capture and requests bounded to 30 seconds. Allow the two-minute exchange only after the exact consent helper is authorized. Issue: #1963 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Keep unauthenticated and ordinary pipe connections at 30 seconds. Extend only a successfully authorized consent-helper policy write to the two-minute exchange limit. Issue: #1963 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Retire only verified protected probe remnants after an interrupted capability check, and require retained Agent ancestor handles to remain expected directories. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Use Unicode-aware literal matching for source names so a policy deny uses the same case semantics as PowerShell repository lookup. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Normalize source names before ordinal matching so policy evaluation uses the same canonical repository identity as PowerShell. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Reject source spellings containing default-ignorable characters before PowerShell can resolve them to a different policy identity. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Reject default-ignorable source spellings before policy evaluation and command construction can disagree. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Carry the ordinary pipe deadline through client capture and serving so unauthenticated clients cannot reserve a connection slot twice as long. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
824c40d to
f57e471
Compare
Reject noncanonical source spellings before policy matching so PowerShell repository trimming cannot bypass a source-specific rule. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
The critical SourceName matching issue remains unresolved for non-PowerShell package managers.
Get a fresh assessment by requesting another Copilot review.
Review details
- Files reviewed: 28/29 changed files
- Comments generated: 1
- Review effort level: Lite (auto)
Note
Copilot is running an experiment and ran this review at Lite.
Apply PowerShell source canonicalization only to PowerShell so other package managers retain their own source identity semantics. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🔵 Needs a closer look
A critical policy-validation mismatch remains, and the security-sensitive changes require human review.
Review details
- Files reviewed: 28/29 changed files
- Comments generated: 1
- Review effort level: Lite (auto)
Note
Copilot is running an experiment and ran this review at Lite.
Reject policy source spellings that cannot safely match package requests before they can create unusable source-specific rules. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Exercise ambiguous SourceNames with a valid PowerShell rule so the regression protects the shared policy-validation predicate. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🔵 Needs a closer look
A moderate 32-bit registry-view discovery gap remains unresolved, and the security-sensitive changes require human review.
Review details
Suppressed comments (1)
package/AgentWindowsManaged/Program.cs:495
- On a 64-bit Agent MSI this selects only the 64-bit HKLM view, but UniGetUI also publishes a
win-x86build and a 32-bit process reads HKLM\Software through the WOW6432Node view by default. Those supported UniGetUI installations therefore cannot discover the helper even though the comment says discovery follows the consumer's native view. Publish the discovery contract to both registry views on 64-bit systems (or explicitly constrain supported host architectures).
internal static bool Use64BitRegistryView(Platform? platform) =>
platform is Platform.x64 or Platform.arm64;
- Files reviewed: 29/30 changed files
- Comments generated: 0 new
- Review effort level: Lite (auto)
Note
Copilot is running an experiment and ran this review at Lite.
Publish consent-helper discovery and configured broker-pipe values to the 32-bit registry view so supported x86 consumers find the protected helper. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🔵 Needs a closer look
Update the validator version and receipt fixtures; the registry-view duplication remains a minor maintainability concern.
Review details
Suppressed comments (2)
crates/now-package-broker/src/policy_store/validation.rs:428
- This adds a new authoritative validation rejection while
VALIDATOR_VERSIONremainsnow-package-broker-policy-validator/10. That value is returned to clients and is part of the validation-receipt MAC, so consumers cannot distinguish this changed validation contract from version 10; increment the validator version and update the receipt/version fixtures together.
for (source_index, source_name) in rule.match_criteria.source_names.iter().enumerate() {
if !evaluator::source_name_is_unambiguous(source_name.as_ref()) {
findings.push(rule_finding(
rule,
PolicyFindingSeverity::Error,
package/AgentWindowsManaged/Program.cs:505
- The WOW6432Node values duplicate the seven native-view definitions above. Because both views implement the same discovery contract, a future field added to one block can silently make 32-bit UniGetUI installations undiscoverable; define the field list once and project it to the requested registry view, with a parity assertion.
internal static IEnumerable<RegValue> CreatePolicyConsentRegistryValuesFor32BitConsumers(
Platform? platform,
Version productVersion)
{
if (!Use64BitRegistryView(platform))
- Files reviewed: 29/30 changed files
- Comments generated: 0 new
- Review effort level: Lite (auto)
Note
Copilot is running an experiment and ran this review at Lite.
Adds an Agent-installed consent helper that lets supported UniGetUI installations request protected policy updates with explicit elevation consent.
The helper authenticates the running UniGetUI and Agent images, preserves policy validation and conflict semantics, and is installed and discovered through the Agent MSI for both default per-user and all-users UniGetUI deployments.
Issue: #1963