Installer not continuously signed
Please note that security bugs or issues should be reported to [email protected].
Describe the bug
At work we use Microsoft AppLocker and most apps in the user context are allowed by certificate. The pgadmin4-8.14-x64.exe admin installer is signed, but during the setup a tmp file is triggered which is no signed. Running the pgadmin4-8.14-x64.exe results in these logs:
pgadmin4-8.14-x64.exe was allowed to run.
%OSDRIVE%\USERS\MyUser\APPDATA\LOCAL\TEMP\2\IS-5LIUQ.TMP\PGADMIN4-8.14-X64.TMP was prevented from running.
Are more detailed log can be found in the details tab of the event:
+ System
- Provider
[ Name] Microsoft-Windows-AppLocker
[ Guid] {cbda4dbf-8d5d-4f69-9578-be14aa540d22}
EventID 8004
Version 0
Level 2
Task 0
Opcode 0
Keywords 0x8000000000000000
- TimeCreated
[ SystemTime] 2025-02-03T13:05:41.1525350Z
EventRecordID 3634
Correlation
- Execution
[ ProcessID] 7688
[ ThreadID] 8052
Channel Microsoft-Windows-AppLocker/EXE and DLL
Computer MyHost.Contoso.com
- Security
[ UserID] S-1-5-21-****
- UserData
- RuleAndFileData
PolicyNameLength 3
PolicyName EXE
RuleId {00000000-0000-0000-0000-000000000000}
RuleNameLength 1
RuleName -
RuleSddlLength 1
RuleSddl -
TargetUser S-1-5-21-****
TargetProcessId 11972
FilePathLength 78
FilePath %OSDRIVE%\USERS\MyUser\APPDATA\LOCAL\TEMP\2\IS-5LIUQ.TMP\PGADMIN4-8.14-X64.TMP
FileHashLength 32
FileHash 6EFEC37D80B39E5C3A74CD9A3364AB17C7E49B7C3F84EF8FA17CB421884FC3AD
FqbnLength 1
Fqbn -
TargetLogonId 0xbdf870a
FullFilePathLength 71
FullFilePath C:\Users\MyUser\AppData\Local\Temp\2\is-5LIUQ.tmp\pgadmin4-8.14-x64.tmp
As you can see, the Fqbn is empty.
To Reproduce
Steps to reproduce the behavior:
- Setup AppLocker
- Allow the used certificate for pgadmin4-8.14-x64.exe:
Get-AppLockerFileInformation .\pgadmin4-8.14-x64.exe | Format-List
RunspaceId : eba501a5-f09d-4946-8ccb-af34bbc368e3
Path : %OSDRIVE%\USERS\MyUser\DOWNLOADS\PGADMIN4-8.14-X64.EXE
Publisher : O=ENTERPRISEDB CORPORATION, S=MASSACHUSETTS, C=US\PGADMIN 4\,0.0.0.0
Hash : SHA256 0x5AD2561749ADA116D5CE93132800C70EE32E2A9BAA32433CFC66BDF3459B920D
AppX : False
Expected behavior
The the installer is continuously signed
Hi @dpage,
How do you think we can handle this case?
I have no idea. The internals of how the installer work are not managed by us, but by InnoSetup.
Hi @dpage, hi @adityatoshniwal,
at first thanks for even thinking about it. I googled what you said about using InnoSetup and I found following blog: https://blog.osarmor.com/340/innosetup-sign-installer-uninstaller/ which seems to describe the issue. I personally never used InnoSetup, I am more into MSI, but maybe you can check it?
@stephannn I checked our build process and it is already signing the installers as per the blog. You can check here https://github.com/pgadmin-org/pgadmin4/blob/master/Make.bat#L379
When I see it correctly the https://github.com/pgadmin-org/pgadmin4/blob/master/pkg/win32/installer.iss.in file is used for the setup creating process. On the other hand, https://github.com/pgadmin-org/pgadmin4/blob/master/Make.bat#L379 is just signing the final setup file. What maybe is missing is in the [setup] section the argument SignTool=sha256. On the blog is also says the signing step is done twice.
I have never really created a Inno setup by my own, but maybe I will find this week to do a test.
When I see it correctly the https://github.com/pgadmin-org/pgadmin4/blob/master/pkg/win32/installer.iss.in file is used for the setup creating process. On the other hand, https://github.com/pgadmin-org/pgadmin4/blob/master/Make.bat#L379 is just signing the final setup file. What maybe is missing is in the [setup] section the argument SignTool=sha256. On the blog is also says the signing step is done twice.
I have never really created a Inno setup by my own, but maybe I will find this week to do a test.
This is when you're using a UI tool to build the installer which requires SignTool key to tell what to run. sha256 is just a name for the command to run.
In pgAdmin, we're using command line as the builds are automated. You can check the build script to check for anything missing.
Hi, I rebuild the compiling process and it really makes a difference between signing during the compilation with inno setup and signing afterwards.
What I did for my testing was creating a cert at first:
$selfSignedRootCA = New-SelfSignedCertificate -DnsName [email protected] -notafter (Get-Date).AddMonths(6) -CertStoreLocation "Cert:\CurrentUser\My" -KeyExportPolicy Exportable -Type CodeSigningCert -KeySpec KeyExchange -KeyLength 2048 -KeyUsageProperty All -KeyAlgorithm 'RSA' -HashAlgorithm 'SHA256' -Provider 'Microsoft Enhanced RSA and AES Cryptographic Provider' -FriendlyName "Test-Cert" -KeyFriendlyName "TestCert" $CertPassword = ConvertTo-SecureString -String "123456" -Force -AsPlainText $selfSignedRootCA | Export-PfxCertificate -FilePath C:\tmp\mycert.pfx -Password $CertPassword
Then I used this cert as described in the article within inno setup. Setting up the signing tool and adding the cert name in the ISS file. The result is following.
The Exe:
[-](https://github.com/pgadmin-org/pgadmin4/issues/8420#) <UserData> [-](https://github.com/pgadmin-org/pgadmin4/issues/8420#) <RuleAndFileData xmlns="http://schemas.microsoft.com/schemas/event/Microsoft.Windows/1.0.0.0"> <PolicyNameLength>3</PolicyNameLength> <PolicyName>EXE</PolicyName> <RuleId>{5029b9f6-d04f-4e19-9d0a-fb0da3aa90e6}</RuleId> <RuleNameLength>38</RuleNameLength> <RuleName>PGADMIN 4, aus [email protected]</RuleName> <RuleSddlLength>111</RuleSddlLength> <RuleSddl>D:(XA;;FX;;;S-1-1-0;((Exists APPID://FQBN) && ((APPID://FQBN) >= ({"[email protected]\PGADMIN 4\*",0}))))</RuleSddl> <TargetUser>S-1-5-21-2531565672-1194778543-1457707523-171871</TargetUser> <TargetProcessId>6464</TargetProcessId> <FilePathLength>39</FilePathLength> <FilePath>%OSDRIVE%\TMP\OUTPUT\PGADMIN4-SETUP.EXE</FilePath> <FileHashLength>32</FileHashLength> <FileHash>46CC17AF8AA8F848581E64BAA82162AA530F3B3F1DB95A84E06AE6EF0B3C774B</FileHash> <FqbnLength>43</FqbnLength> <Fqbn>[email protected]\PGADMIN 4\\0.0.0.00</Fqbn> <TargetLogonId>0x91d5a</TargetLogonId> <FullFilePathLength>32</FullFilePathLength> <FullFilePath>C:\tmp\Output\pgadmin4-setup.exe</FullFilePath> </RuleAndFileData> </UserData>
and afterwards the tmp is getting executed:
[-](https://github.com/pgadmin-org/pgadmin4/issues/8420#) <UserData> [-](https://github.com/pgadmin-org/pgadmin4/issues/8420#) <RuleAndFileData xmlns="http://schemas.microsoft.com/schemas/event/Microsoft.Windows/1.0.0.0"> <PolicyNameLength>3</PolicyNameLength> <PolicyName>EXE</PolicyName> <RuleId>{5029b9f6-d04f-4e19-9d0a-fb0da3aa90e6}</RuleId> <RuleNameLength>38</RuleNameLength> <RuleName>PGADMIN 4, aus [email protected]</RuleName> <RuleSddlLength>111</RuleSddlLength> <RuleSddl>D:(XA;;FX;;;S-1-1-0;((Exists APPID://FQBN) && ((APPID://FQBN) >= ({"[email protected]\PGADMIN 4\*",0}))))</RuleSddl> <TargetUser>S-1-5-21-2531565672-1194778543-1457707523-171871</TargetUser> <TargetProcessId>3180</TargetProcessId> <FilePathLength>75</FilePathLength> <FilePath>%OSDRIVE%\USERS\G82179\APPDATA\LOCAL\TEMP\2\IS-5QAK9.TMP\PGADMIN4-SETUP.TMP</FilePath> <FileHashLength>32</FileHashLength> <FileHash>67CE20FE786E343EE42987E26CAC50774451F4EF505EA0BFF0CD06CF6D6CEFCC</FileHash> <FqbnLength>47</FqbnLength> <Fqbn>[email protected]\PGADMIN 4\\51.1052.0.00</Fqbn> <TargetLogonId>0x91d5a</TargetLogonId> <FullFilePathLength>68</FullFilePathLength> <FullFilePath>C:\Users\g82179\AppData\Local\Temp\2\is-5QAK9.tmp\pgadmin4-setup.tmp</FullFilePath> </RuleAndFileData> </UserData>
As you can see, both files, the pgadmin4-setup.exe and the pgadmin4-setup.tmp are correctly signed.
In case you just call afterward:
CALL "%PGADMIN_SIGNTOOL_DIR%\signtool.exe" sign /fd certHash /tr http://timestamp.digicert.com /td SHA256 "%DISTROOT%\%INSTALLERNAME%"
it will only sign the exe, but not the tmp file
Hi, I rebuild the compiling process and it really makes a difference between signing during the compilation with inno setup and signing afterwards.
Great! You can send the PR for changes and we can merge it. Like I said, we cannot use tool GUI for building the executable.
@adityatoshniwal , can you please try following command line:
"C:\Program Files (x86)\Inno Setup 6\ISCC.exe" "C:\tmp\installer.iss" "/Ssigntool=C:\tmp\signtool.exe sign /f C:\tmp\mycert2.pfx /tr http://timestamp.sectigo.com /td sha256 /fd sha256 /a /p 123456 $f"
or in your case
CALL "%PGADMIN_INNOTOOL_DIR%\ISCC.exe" "%WD%\pkg\win32\installer.iss" "/Ssigntool=%PGADMIN_SIGNTOOL_DIR%\signtool.exe sign /fd certHash /tr http://timestamp.digicert.com /td SHA256 "%DISTROOT%\%INSTALLERNAME%" $f" || EXIT /B 1
and in the ISS file add these two line:
SignTool=signtool
SignedUninstaller=yes
I hope the command line with the quotations is fine. Not sure about certHash
@adityatoshniwal , can you please try following command line:
"C:\Program Files (x86)\Inno Setup 6\ISCC.exe" "C:\tmp\installer.iss" "/Ssigntool=C:\tmp\signtool.exe sign /f C:\tmp\mycert2.pfx /tr http://timestamp.sectigo.com /td sha256 /fd sha256 /a /p 123456 $f"or in your case
CALL "%PGADMIN_INNOTOOL_DIR%\ISCC.exe" "%WD%\pkg\win32\installer.iss" "/Ssigntool=%PGADMIN_SIGNTOOL_DIR%\signtool.exe sign /fd certHash /tr http://timestamp.digicert.com /td SHA256 "%DISTROOT%\%INSTALLERNAME%" $f" || EXIT /B 1and in the ISS file add these two line:
SignTool=signtool SignedUninstaller=yesI hope the command line with the quotations is fine. Not sure about certHash
Based on this, I've created the PR on your behalf - https://github.com/pgadmin-org/pgadmin4/pull/8933
Edit: there is no need to set SignTool in .iss file because the command includes /Ssigntool
Hi @stephannn,
Can you confirm if the new singing is working by testing snapshot build - https://www.postgresql.org/ftp/pgadmin/pgadmin4/snapshots/?
Hi @adityatoshniwal , that looks very good, even the uninstaller works. The two events from the windows AppLocker when running the software:
1. Event
- <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
- <System>
<Provider Name="Microsoft-Windows-AppLocker" Guid="{cbda4dbf-8d5d-4f69-9578-be14aa540d22}" />
<EventID>8002</EventID>
<Version>0</Version>
<Level>4</Level>
<Task>0</Task>
<Opcode>0</Opcode>
<Keywords>0x8000000000000000</Keywords>
<TimeCreated SystemTime="2025-07-15T07:26:54.8932524Z" />
<EventRecordID>6089</EventRecordID>
<Correlation />
<Execution ProcessID="7600" ThreadID="11688" />
<Channel>Microsoft-Windows-AppLocker/EXE and DLL</Channel>
<Computer>PC1.contoso.org</Computer>
<Security UserID="S-1-5-21-2531565672-1194778543-1457707523-171871" />
</System>
- <UserData>
- <RuleAndFileData xmlns="http://schemas.microsoft.com/schemas/event/Microsoft.Windows/1.0.0.0">
<PolicyNameLength>3</PolicyNameLength>
<PolicyName>EXE</PolicyName>
<RuleId>{d0325022-3710-4383-b851-dc621a83b663}</RuleId>
<RuleNameLength>59</RuleNameLength>
<RuleName>Signed by O=ENTERPRISEDB CORPORATION, S=MASSACHUSETTS, C=US</RuleName>
<RuleSddlLength>129</RuleSddlLength>
<RuleSddl>D:(XA;;FX;;;S-1-1-0;((Exists APPID://FQBN) && ((APPID://FQBN) >= ({"O=ENTERPRISEDB CORPORATION, S=MASSACHUSETTS, C=US\*\*",0}))))</RuleSddl>
<TargetUser>S-1-5-21-2531565672-1194778543-1457707523-171871</TargetUser>
<TargetProcessId>7592</TargetProcessId>
<FilePathLength>57</FilePathLength>
<FilePath>%OSDRIVE%\USERS\TestUser\DOWNLOADS\PGADMIN4-9.5-X64 (1).EXE</FilePath>
<FileHashLength>32</FileHashLength>
<FileHash>BBCDB317727C2B4C46F52D9A0497CFD27B057B3433F0F7E2E64904A9E0E153D0</FileHash>
<FqbnLength>69</FqbnLength>
<Fqbn>O=ENTERPRISEDB CORPORATION, S=MASSACHUSETTS, C=US\PGADMIN 4\\0.0.0.00</Fqbn>
<TargetLogonId>0x76433</TargetLogonId>
<FullFilePathLength>50</FullFilePathLength>
<FullFilePath>C:\Users\TestUser\Downloads\pgadmin4-9.5-x64 (1).exe</FullFilePath>
</RuleAndFileData>
</UserData>
</Event>
2. Event
- <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
- <System>
<Provider Name="Microsoft-Windows-AppLocker" Guid="{cbda4dbf-8d5d-4f69-9578-be14aa540d22}" />
<EventID>8002</EventID>
<Version>0</Version>
<Level>4</Level>
<Task>0</Task>
<Opcode>0</Opcode>
<Keywords>0x8000000000000000</Keywords>
<TimeCreated SystemTime="2025-07-15T07:26:55.1653491Z" />
<EventRecordID>6090</EventRecordID>
<Correlation />
<Execution ProcessID="7592" ThreadID="1288" />
<Channel>Microsoft-Windows-AppLocker/EXE and DLL</Channel>
<Computer>PC1.contoso.org</Computer>
<Security UserID="S-1-5-21-2531565672-1194778543-1457707523-171871" />
</System>
- <UserData>
- <RuleAndFileData xmlns="http://schemas.microsoft.com/schemas/event/Microsoft.Windows/1.0.0.0">
<PolicyNameLength>3</PolicyNameLength>
<PolicyName>EXE</PolicyName>
<RuleId>{d0325022-3710-4383-b851-dc621a83b663}</RuleId>
<RuleNameLength>59</RuleNameLength>
<RuleName>Signed by O=ENTERPRISEDB CORPORATION, S=MASSACHUSETTS, C=US</RuleName>
<RuleSddlLength>129</RuleSddlLength>
<RuleSddl>D:(XA;;FX;;;S-1-1-0;((Exists APPID://FQBN) && ((APPID://FQBN) >= ({"O=ENTERPRISEDB CORPORATION, S=MASSACHUSETTS, C=US\*\*",0}))))</RuleSddl>
<TargetUser>S-1-5-21-2531565672-1194778543-1457707523-171871</TargetUser>
<TargetProcessId>7212</TargetProcessId>
<FilePathLength>81</FilePathLength>
<FilePath>%OSDRIVE%\USERS\TestUser\APPDATA\LOCAL\TEMP\2\IS-D0BKS.TMP\PGADMIN4-9.5-X64 (1).TMP</FilePath>
<FileHashLength>32</FileHashLength>
<FileHash>68F42F90092A7FCD659F9BB3E1DFEC352311967ACBD37A32E0B3FD14C635F49B</FileHash>
<FqbnLength>73</FqbnLength>
<Fqbn>O=ENTERPRISEDB CORPORATION, S=MASSACHUSETTS, C=US\PGADMIN 4\\51.1052.0.00</Fqbn>
<TargetLogonId>0x76433</TargetLogonId>
<FullFilePathLength>74</FullFilePathLength>
<FullFilePath>C:\Users\TestUser\AppData\Local\Temp\2\is-D0BKS.tmp\pgadmin4-9.5-x64 (1).tmp</FullFilePath>
</RuleAndFileData>
</UserData>
</Event>
I am sorry, I just noticed something more in the make.bat:
CALL "%PGADMIN_SIGNTOOL_DIR%\signtool.exe" sign /fd certHash /tr http://timestamp.digicert.com /td SHA256 "%BUILDROOT%\runtime\pgAdmin4.exe"
signs only the pgAdmin4.exe, but there are more executables like:
PG_DUMPALL.EXE , PG_DUMP.EXE, PG_RESTORE.EXE, PSQL.EXE that are not signed. Even some python files. Not sure if these are required, if the best would be a for loop, or just singly sign those 4 additional pgadmin files.
I must admit, I am also not using pgadmin because I am just a System Engineer ;)
@stephannn Thanks for your testing. These are log entries from ISCC installer build, so I think it should've already signed those files as well. May be the separate signing will not be needed. Are you getting any error?
Compressing: C:\jenkins\workspace\pgadmin4-windows-x64-qa\pkg\win32\..\..\win-build\runtime\libpq.dll
Compressing: C:\jenkins\workspace\pgadmin4-windows-x64-qa\pkg\win32\..\..\win-build\runtime\libssl-3-x64.dll
Compressing: C:\jenkins\workspace\pgadmin4-windows-x64-qa\pkg\win32\..\..\win-build\runtime\libzstd.dll
Compressing: C:\jenkins\workspace\pgadmin4-windows-x64-qa\pkg\win32\..\..\win-build\runtime\LICENSE
Compressing: C:\jenkins\workspace\pgadmin4-windows-x64-qa\pkg\win32\..\..\win-build\runtime\LICENSES.chromium.html
Compressing: C:\jenkins\workspace\pgadmin4-windows-x64-qa\pkg\win32\..\..\win-build\runtime\pgAdmin4.exe
Compressing: C:\jenkins\workspace\pgadmin4-windows-x64-qa\pkg\win32\..\..\win-build\runtime\pg_dump.exe
Compressing: C:\jenkins\workspace\pgadmin4-windows-x64-qa\pkg\win32\..\..\win-build\runtime\pg_dumpall.exe
Edit: I just searched and no it doesn't do it recursively.
@adityatoshniwal , I see what you mean. Unfortunately adding the signing parameter to the ISS only signs the installer (and uninstaller), but it does not includes the application Exe files. If I am not mistaken, something similar to this should be added to the make.bat:
CALL "%PGADMIN_SIGNTOOL_DIR%\signtool.exe" sign /fd certHash /tr http://timestamp.digicert.com /td SHA256 "%BUILDROOT%\runtime\PG_DUMPALL.exe"
CALL "%PGADMIN_SIGNTOOL_DIR%\signtool.exe" sign /fd certHash /tr http://timestamp.digicert.com /td SHA256 "%BUILDROOT%\runtime\PG_DUMP.exe"
CALL "%PGADMIN_SIGNTOOL_DIR%\signtool.exe" sign /fd certHash /tr http://timestamp.digicert.com /td SHA256 "%BUILDROOT%\runtime\PG_RESTORE.exe"
CALL "%PGADMIN_SIGNTOOL_DIR%\signtool.exe" sign /fd certHash /tr http://timestamp.digicert.com /td SHA256 "%BUILDROOT%\runtime\PSQL.exe"
to the additional pgAdmin4. On a Windows system you can easily double check it by right click -> properties. On Linux I am not really sure.
hi @stephannn,
The files are copied as is from PostgreSQL installer. I don't think they need to be separately signed. I believe they're signed from source.
@adityatoshniwal , to be honest, I am not sure. From our developers, who use the app, I did not hear any complain about it and they use it with the certificate allowing and everything else is blocked. I just noticed it that after I run pgAdmin4.exe that in the AppLocker the other exes got blocked without separately calling them. I would say, unless someone else says differently we can leave it as it is? If later someone else or I notice anything wrong we can still re open the issue. Thanks a lot for your support
@stephannn Sounds good. Feel free to reopen in future. Thank you for working on it.