Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
31e20e5
feat(agent): add policy audit events
CBenoit Sep 8, 2026
27fe9ff
build(dgw,agent): embed policy event catalogs
CBenoit Sep 8, 2026
07081aa
test(dgw,agent): enforce event catalog parity
CBenoit Sep 8, 2026
8d964b1
fix(dgw,agent): harden policy audit validation
CBenoit Sep 9, 2026
3619f06
fix(agent): audit legacy policy rejection
CBenoit Sep 15, 2026
fddc080
fix(dgw,agent): compile localized event messages
CBenoit Sep 15, 2026
1b9c2f2
fix(dgw,agent,agent-installer): retain canonical audits
CBenoit Sep 17, 2026
5d94bfc
fix(agent): sanitize audit text controls
CBenoit Sep 18, 2026
b1ed7fe
refactor(agent): isolate policy audit event codes
CBenoit Sep 18, 2026
21a0fb4
test(agent): isolate audit recorders
CBenoit Sep 18, 2026
cd08d96
test(agent): scope audit fixtures locally
CBenoit Sep 18, 2026
2dc816a
refactor(agent): require policy write audits
CBenoit Sep 18, 2026
58e8ca0
refactor(agent): adopt shared warning contract
CBenoit Sep 19, 2026
48a7e2d
test(agent): cover policy management end to end
CBenoit Sep 8, 2026
87d5422
ci(agent): run policy E2E as both identities
CBenoit Sep 8, 2026
a3e3113
test(agent): separate policy client identity
CBenoit Sep 9, 2026
6ff4e4b
ci(agent): handle detached policy tester launch
CBenoit Sep 9, 2026
304f578
test(agent): use medium-integrity policy client
CBenoit Sep 9, 2026
421829f
ci(agent): stop policy server after launch failures
CBenoit Sep 9, 2026
6e4d41f
test(agent): exercise revised policy lifecycle
CBenoit Sep 15, 2026
8059127
fix(agent): restore NuGet test imports for SYSTEM
CBenoit Sep 15, 2026
c10b4bd
fix(agent): run installer tests as LocalSystem
CBenoit Sep 15, 2026
4b13e3f
fix(agent): authenticate installer E2E client
CBenoit Sep 15, 2026
4300382
test(agent): retain canonical policy E2E
CBenoit Sep 17, 2026
9f6744a
test(agent): cover final policy contract
CBenoit Sep 17, 2026
8c553f5
test(agent): cover policy review gaps
CBenoit Sep 17, 2026
5eb089e
fix(agent): accept advisory policy findings
CBenoit Sep 20, 2026
d1fe413
feat(agent,agent-installer): add policy consent helper
CBenoit Sep 9, 2026
089c76b
fix(agent): enforce signer revocation checks
CBenoit Sep 9, 2026
2ace003
fix(agent): bind broker trust to running image
CBenoit Sep 10, 2026
7160af7
fix(agent,agent-installer): correct helper packaging
CBenoit Sep 10, 2026
04371ab
fix(agent): validate policy credentials
CBenoit Sep 10, 2026
a17351d
fix(agent,agent-installer): require current UI signer
CBenoit Sep 17, 2026
85ca006
fix(agent,agent-installer): discover broker pipe
CBenoit Sep 17, 2026
95cce81
docs(agent-installer): add helper package step
CBenoit Sep 17, 2026
2c2354c
fix(agent): require local consent parent
CBenoit Sep 17, 2026
c81c1b9
fix(agent): resolve retained consent paths
CBenoit Sep 17, 2026
db757ad
fix(agent): align policy pipe deadline
CBenoit Sep 17, 2026
6466a19
fix(agent): limit consent pipe timeout
CBenoit Sep 17, 2026
0fadc51
fix(agent): extend authorized policy writes
CBenoit Sep 17, 2026
db8482d
fix(agent): recover interrupted policy probes
CBenoit Sep 17, 2026
e31c8ed
fix(agent): match Unicode policy sources
CBenoit Sep 17, 2026
11b4733
fix(agent): normalize policy source names
CBenoit Sep 17, 2026
cc47854
fix(agent): reject ambiguous policy sources
CBenoit Sep 17, 2026
e8f56e6
fix(agent): validate package source identity
CBenoit Sep 17, 2026
a92258d
fix(agent): bound pipe connections from accept
CBenoit Sep 17, 2026
25155a5
fix(agent): reject padded policy sources
CBenoit Sep 17, 2026
3ac7208
fix(agent): preserve manager source identity
CBenoit Sep 17, 2026
ee9613e
fix(agent): validate policy source spelling
CBenoit Sep 17, 2026
0a279f2
test(agent): cover policy source spelling guard
CBenoit Sep 17, 2026
bed8690
fix(agent,agent-installer): publish helper discovery in both views
CBenoit Sep 18, 2026
c13d2a1
fix(agent): align helper policy contract
CBenoit Sep 20, 2026
70bd15e
refactor(agent-installer): deduplicate helper registry values
CBenoit Sep 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 125 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -354,8 +354,6 @@ jobs:
$VSINSTALLDIR = $(vswhere.exe -latest -requires Microsoft.VisualStudio.Component.VC.Llvm.Clang -property installationPath)
Write-Output "LIBCLANG_PATH=$VSINSTALLDIR\VC\Tools\Llvm\x64\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append

# Install Visual Studio Developer PowerShell Module for cmdlets such as Enter-VsDevShell
Install-Module VsDevShell -Force
shell: pwsh

- name: Configure Windows (arm) runner
Expand Down Expand Up @@ -696,9 +694,6 @@ jobs:
# NASM is required by aws-lc-rs (used as rustls crypto backend)
choco install nasm

# Install Visual Studio Developer PowerShell Module for cmdlets such as Enter-VsDevShell
Install-Module VsDevShell -Force

# We need to add the NASM binary folder to the PATH manually.
Write-Output "$Env:ProgramFiles\NASM" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
shell: pwsh
Expand All @@ -707,9 +702,31 @@ jobs:
id: find_mc
if: ${{ matrix.os == 'windows' }}
run: |
Enter-VsDevShell
$path = (Get-Command -Type Application mc).Source | Split-Path -Parent
$sdkRoots = @(
$Env:WindowsSdkDir
(Get-ItemPropertyValue -Path "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" -Name KitsRoot10 -ErrorAction SilentlyContinue)
"${Env:ProgramFiles(x86)}\Windows Kits\10"
) | Where-Object { $_ } | Select-Object -Unique
$candidates = @()
if ($Env:WindowsSdkVerBinPath) {
$candidates += Join-Path $Env:WindowsSdkVerBinPath "mc.exe"
$candidates += Join-Path $Env:WindowsSdkVerBinPath "x64\mc.exe"
}
foreach ($root in $sdkRoots) {
$bin = Join-Path $root "bin"
$candidates += Join-Path $bin "x64\mc.exe"
$candidates += Get-ChildItem -LiteralPath $bin -Directory -ErrorAction SilentlyContinue |
Where-Object Name -Match '^\d+\.\d+\.\d+\.\d+$' |
Sort-Object { [version]$_.Name } -Descending |
ForEach-Object { Join-Path $_.FullName "x64\mc.exe" }
}
$mc = $candidates | Where-Object { Test-Path -LiteralPath $_ -PathType Leaf } | Select-Object -First 1
if (-Not $mc) {
throw "mc.exe was not found in the installed Windows SDK"
}
$path = Split-Path -Parent $mc
Write-Output "windows_sdk_ver_bin_path=$path" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
Write-Output $path | Out-File -FilePath $env:GITHUB_PATH -Append -Encoding utf8
shell: pwsh

- name: Build
Expand Down Expand Up @@ -870,6 +887,9 @@ jobs:
$DAgentSessionExecutable = Join-Path $TargetOutputPath "DevolutionsSession.exe"
echo "dagent-session-executable=$DAgentSessionExecutable" >> $Env:GITHUB_OUTPUT

$DAgentPolicyConsentHelper = Join-Path $TargetOutputPath "DevolutionsAgentPolicyConsent.exe"
echo "dagent-policy-consent-helper=$DAgentPolicyConsentHelper" >> $Env:GITHUB_OUTPUT

$DAgentUpdaterExecutable = Join-Path $TargetOutputPath "DevolutionsAgentUpdater.exe"
echo "dagent-updater-executable=$DAgentUpdaterExecutable" >> $Env:GITHUB_OUTPUT
}
Expand Down Expand Up @@ -975,6 +995,37 @@ jobs:
if: ${{ matrix.os == 'windows' }}
uses: microsoft/setup-msbuild@v3

- name: Find mc.exe
id: find_mc
if: ${{ matrix.os == 'windows' }}
run: |
$sdkRoots = @(
$Env:WindowsSdkDir
(Get-ItemPropertyValue -Path "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" -Name KitsRoot10 -ErrorAction SilentlyContinue)
"${Env:ProgramFiles(x86)}\Windows Kits\10"
) | Where-Object { $_ } | Select-Object -Unique
$candidates = @()
if ($Env:WindowsSdkVerBinPath) {
$candidates += Join-Path $Env:WindowsSdkVerBinPath "mc.exe"
$candidates += Join-Path $Env:WindowsSdkVerBinPath "x64\mc.exe"
}
foreach ($root in $sdkRoots) {
$bin = Join-Path $root "bin"
$candidates += Join-Path $bin "x64\mc.exe"
$candidates += Get-ChildItem -LiteralPath $bin -Directory -ErrorAction SilentlyContinue |
Where-Object Name -Match '^\d+\.\d+\.\d+\.\d+$' |
Sort-Object { [version]$_.Name } -Descending |
ForEach-Object { Join-Path $_.FullName "x64\mc.exe" }
}
$mc = $candidates | Where-Object { Test-Path -LiteralPath $_ -PathType Leaf } | Select-Object -First 1
if (-Not $mc) {
throw "mc.exe was not found in the installed Windows SDK"
}
$path = Split-Path -Parent $mc
Write-Output "windows_sdk_ver_bin_path=$path" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
Write-Output $path | Out-File -FilePath $env:GITHUB_PATH -Append -Encoding utf8
shell: pwsh

- name: Build
run: |
if ($Env:RUNNER_OS -eq "Windows") {
Expand All @@ -985,6 +1036,7 @@ jobs:
$Env:DAGENT_TUN2SOCKS_EXE = "${{ steps.tun2socks.outputs.tun2socks-executable-path }}"
$Env:DAGENT_WINTUN_DLL = "${{ steps.tun2socks.outputs.wintun-library-path }}"
$Env:DAGENT_MULTI_PWSH_EXECUTABLE = "${{ steps.multi-pwsh.outputs.executable-path }}"
$Env:WindowsSdkVerBinPath = '${{ steps.find_mc.outputs.windows_sdk_ver_bin_path }}'
}

if ($Env:RUNNER_OS -eq "Linux") {
Expand All @@ -1003,6 +1055,28 @@ jobs:
DAGENT_EXECUTABLE: ${{ steps.load-variables.outputs.dagent-executable }}
TARGET_OUTPUT_PATH: ${{ steps.load-variables.outputs.target-output-path }}

- name: Build NativeAOT policy consent helper
if: ${{ matrix.os == 'windows' }}
run: |
$Rid = "win-${{ matrix.arch }}"
$Output = Split-Path -Parent '${{ steps.load-variables.outputs.dagent-policy-consent-helper }}'
dotnet publish package/AgentPolicyConsent/DevolutionsAgentPolicyConsent.csproj `
--configuration Release `
--runtime $Rid `
--output $Output `
-p:Version=${{ needs.preflight.outputs.version }}
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}
$Helper = '${{ steps.load-variables.outputs.dagent-policy-consent-helper }}'
if (-Not (Test-Path -LiteralPath $Helper -PathType Leaf)) {
throw "NativeAOT policy consent helper was not produced"
}
if ((Get-Item -LiteralPath $Helper).Length -gt 8MB) {
throw "NativeAOT policy consent helper exceeds 8 MiB"
}
shell: pwsh

- name: Package
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }}
run: |
Expand All @@ -1016,6 +1090,7 @@ jobs:
$Env:DAGENT_PEDM_SHELL_EXT_DLL = "${{ steps.load-variables.outputs.dagent-pedm-shell-ext-dll }}"
$Env:DAGENT_PEDM_SHELL_EXT_MSIX = "${{ steps.load-variables.outputs.dagent-pedm-shell-ext-msix }}"
$Env:DAGENT_SESSION_EXECUTABLE = "${{ steps.load-variables.outputs.dagent-session-executable }}"
$Env:DAGENT_POLICY_CONSENT_HELPER = "${{ steps.load-variables.outputs.dagent-policy-consent-helper }}"
$Env:DAGENT_TUN2SOCKS_EXE = "${{ steps.tun2socks.outputs.tun2socks-executable-path }}"
$Env:DAGENT_WINTUN_DLL = "${{ steps.tun2socks.outputs.wintun-library-path }}"
$Env:DAGENT_MULTI_PWSH_EXECUTABLE = "${{ steps.multi-pwsh.outputs.executable-path }}"
Expand Down Expand Up @@ -1122,6 +1197,25 @@ jobs:
run: dotnet test utils/dotnet/GatewayUtils.sln
shell: pwsh

agent-installer-event-log-tests:
name: Agent installer Event Log lifecycle tests
runs-on: windows-2022
needs: [preflight]

steps:
- name: Checkout ${{ github.repository }}
uses: actions/checkout@v6
with:
ref: ${{ needs.preflight.outputs.ref }}

- name: Tests
run: dotnet test package/AgentWindowsManaged.Tests/DevolutionsAgent.Installer.Tests.csproj
shell: pwsh

- name: Policy consent helper tests
run: dotnet test package/AgentPolicyConsent.Tests/DevolutionsAgentPolicyConsent.Tests.csproj -c Release
shell: pwsh


winapi-sanitizer-tests:
name: Windows API sanitizer tests
Expand Down Expand Up @@ -1283,12 +1377,14 @@ jobs:
name: Agent policy end-to-end test
runs-on: windows-2022
needs: [preflight]
env:
AGENT_POLICY_TEST_SHA: ${{ inputs.ref || github.event.pull_request.head.sha || needs.preflight.outputs.ref }}

steps:
- name: Checkout ${{ github.repository }}
uses: actions/checkout@v6
with:
ref: ${{ needs.preflight.outputs.ref }}
ref: ${{ env.AGENT_POLICY_TEST_SHA }}

- name: Setup Rust cache
uses: ./.github/actions/setup-rust-cache
Expand All @@ -1311,8 +1407,13 @@ jobs:
Add-Content -Path $env:GITHUB_PATH -Value $toolsDir

- name: Build Agent policy test executables
id: build-policy-executables
shell: pwsh
run: |
$actualCommit = git rev-parse HEAD
if ($LASTEXITCODE -ne 0 -or $actualCommit -ne $env:AGENT_POLICY_TEST_SHA) {
throw "Agent policy tests must build the requested commit $env:AGENT_POLICY_TEST_SHA, got $actualCommit"
}
cargo build --locked -p devolutions-agent --features dev-skip-broker-signature
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
Expand All @@ -1322,7 +1423,18 @@ jobs:
exit $LASTEXITCODE
}

- name: Run Agent policy tester as standard user
shell: pwsh
run: |
./crates/agent-policy-tester/run-unelevated.ps1
$exitCode = $LASTEXITCODE
Get-Content -Path ./crates/agent-policy-tester/agent-policy-tester-unelevated.out
if ($exitCode -ne 0) {
exit $exitCode
}

- name: Run Agent policy tester as LocalSystem
if: ${{ !cancelled() && steps.build-policy-executables.outcome == 'success' }}
shell: pwsh
run: |
$scriptPath = Resolve-Path -Path "./crates/agent-policy-tester/run-as-system.ps1"
Expand All @@ -1333,6 +1445,10 @@ jobs:
exit $exitCode
}

- name: Run policy route authorization tests
shell: pwsh
run: cargo test --locked -p now-package-broker --features dev-skip-broker-signature

- name: Show sccache stats
if: ${{ needs.preflight.outputs.sccache == 'true' && !cancelled() }}
shell: pwsh
Expand Down Expand Up @@ -1366,7 +1482,7 @@ jobs:
success:
name: Success
if: ${{ always() }}
needs: [tests, agent-tunnel-e2e, agent-policy-e2e, lints, check-dependencies, jetsocat-lipo, devolutions-gateway-powershell, devolutions-gateway, devolutions-gateway-merge, devolutions-pedm-desktop, devolutions-agent, devolutions-agent-merge, devolutions-pedm-client, dotnet-utils-tests, winapi-sanitizer-tests, winapi-miri, pedm-simulator, secure-memory-verifier]
needs: [tests, agent-tunnel-e2e, agent-policy-e2e, lints, check-dependencies, jetsocat-lipo, devolutions-gateway-powershell, devolutions-gateway, devolutions-gateway-merge, devolutions-pedm-desktop, devolutions-agent, devolutions-agent-merge, devolutions-pedm-client, dotnet-utils-tests, agent-installer-event-log-tests, winapi-sanitizer-tests, winapi-miri, pedm-simulator, secure-memory-verifier]
runs-on: ubuntu-latest

steps:
Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ jobs:
run: |
$IncludePattern = @(switch ('${{ matrix.project }}') {
'devolutions-gateway' { @('DevolutionsGateway.exe') }
'devolutions-agent' { @('DevolutionsAgent.exe', 'DevolutionsAgentUpdater.exe', 'DevolutionsPedmShellExt.dll', 'DevolutionsPedmShellExt.msix', 'DevolutionsDesktopAgent.exe') }
'devolutions-agent' { @('DevolutionsAgent.exe', 'DevolutionsAgentUpdater.exe', 'DevolutionsAgentPolicyConsent.exe', 'DevolutionsPedmShellExt.dll', 'DevolutionsPedmShellExt.msix', 'DevolutionsDesktopAgent.exe') }
'jetsocat' { @('jetsocat.exe', 'jetsocat') }
})
$ExcludePattern = "*.pdb"
Expand Down Expand Up @@ -495,6 +495,7 @@ jobs:
$Env:DAGENT_PEDM_SHELL_EXT_DLL = Get-ChildItem -Path $ArchRoot -Filter 'DevolutionsPedmShellExt.dll' -File | Select-Object -First 1
$Env:DAGENT_PEDM_SHELL_EXT_MSIX = Get-ChildItem -Path $ArchRoot -Filter 'DevolutionsPedmShellExt.msix' -File | Select-Object -First 1
$Env:DAGENT_SESSION_EXECUTABLE = Get-ChildItem -Path $ArchRoot -Filter 'DevolutionsSession.exe' -File | Select-Object -First 1
$Env:DAGENT_POLICY_CONSENT_HELPER = Get-ChildItem -Path $ArchRoot -Filter 'DevolutionsAgentPolicyConsent.exe' -File | Select-Object -First 1
$Env:DAGENT_TUN2SOCKS_EXE = Join-Path $ArchRoot 'tun2socks.exe'
$Env:DAGENT_WINTUN_DLL = Join-Path $ArchRoot 'wintun.dll'
$MultiPwshDirectory = Join-Path $Env:RUNNER_TEMP 'multi-pwsh' 'windows' $Arch
Expand All @@ -508,6 +509,7 @@ jobs:
Write-Host "DAGENT_PEDM_SHELL_EXT_DLL = ${Env:DAGENT_PEDM_SHELL_EXT_DLL}"
Write-Host "DAGENT_PEDM_SHELL_EXT_MSIX = ${Env:DAGENT_PEDM_SHELL_EXT_MSIX}"
Write-Host "DAGENT_SESSION_EXECUTABLE = ${Env:DAGENT_SESSION_EXECUTABLE}"
Write-Host "DAGENT_POLICY_CONSENT_HELPER = ${Env:DAGENT_POLICY_CONSENT_HELPER}"
Write-Host "DAGENT_TUN2SOCKS_EXE = ${Env:DAGENT_TUN2SOCKS_EXE}"
Write-Host "DAGENT_WINTUN_DLL = ${Env:DAGENT_WINTUN_DLL}"
Write-Host "DAGENT_MULTI_PWSH_EXECUTABLE = ${Env:DAGENT_MULTI_PWSH_EXECUTABLE}"
Expand All @@ -534,7 +536,8 @@ jobs:
@((Join-Path $ArchRoot DesktopAgent),
(Get-ChildItem -Path $ArchRoot -Filter 'DevolutionsPedmShellExt.dll' | Select-Object -First 1),
(Get-ChildItem -Path $ArchRoot -Filter 'DevolutionsPedmShellExt.msix' | Select-Object -First 1),
(Get-ChildItem -Path $ArchRoot -Filter 'DevolutionsSession.exe' | Select-Object -First 1)) | ForEach-Object {
(Get-ChildItem -Path $ArchRoot -Filter 'DevolutionsSession.exe' | Select-Object -First 1),
(Get-ChildItem -Path $ArchRoot -Filter 'DevolutionsAgentPolicyConsent.exe' | Select-Object -First 1)) | ForEach-Object {
Remove-Item $_ -Recurse -ErrorAction SilentlyContinue | Out-Null
}
}
Expand Down
28 changes: 21 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading