Security Overview
This document provides full security documentation for the App Store for Intune, including all Azure resources created, permissions granted, and security configurations. It is intended to assist security teams with reviews and compliance requirements.
Table of contents
Section titled βTable of contentsβ- Azure resources created
- Identity and access management
- Microsoft Entra ID app registration
- Managed identity configuration
- Network security
- Data protection
- Authentication flow
- Authorization model
- Audit logging
- Security checklist
- Package verification
Azure resources created
Section titled βAzure resources createdβThe ARM template deploys the following resources:
| Resource Type | Name Pattern | Purpose |
|---|---|---|
| App Service Plan | asp-apprequest-{env} | Hosts the web application |
| App Service | apprequest-{env}-{unique} | ASP.NET Core API + React SPA |
| Azure Key Vault | kv-appreq-{unique} | Secure secret storage |
| SQL Server | sql-apprequest-{env}-{unique} | Database server |
| SQL Database | AppRequestPortal | Application data storage |
| Storage Account | stappreq{unique} | Queue + blob storage for packaging |
| Application Insights | ai-apprequest-{env} | Application monitoring |
| Log Analytics Workspace | la-apprequest-{env} | Centralized logging |
| Azure Bot | bot-apprequest-{env}-{unique} | Teams proactive messaging (optional) |
| Bot Teams Channel | {bot}/MsTeamsChannel | Enables Teams communication (optional) |
Resource configuration details
Section titled βResource configuration detailsβApp Service
Section titled βApp Serviceβ- Runtime: .NET 8.0 on Linux
- TLS Version: Minimum TLS 1.2 enforced
- HTTPS Only: Enabled (HTTP redirects to HTTPS)
- FTPS State: Disabled (no FTP access)
- Client Affinity: Disabled (stateless application)
- Always On: Enabled (prevents cold starts)
SQL Server
Section titled βSQL Serverβ- TLS Version: Minimum TLS 1.2
- Firewall: Only Azure services allowed (0.0.0.0-0.0.0.0)
- Authentication: SQL authentication (username/password)
Azure Bot (optional)
Section titled βAzure Bot (optional)β- SKU: F0 (Free)
- Location: Global
- App Type: UserAssignedMSI
- Microsoft App ID: the client ID of the botβs own user-assigned managed identity (
Bot:UamiClientId), created by the deploy template when the Teams bot is enabled - Messaging Endpoint:
https://{app-url}/api/messages - Channels: Microsoft Teams only
- Authentication: Bot Framework handles its own authentication via
ConfigurationBotFrameworkAuthentication, using that managed identity
Bot Framework Authentication Model:
- As of v1.30.0 the Azure Bot resource uses a dedicated user-assigned managed identity. It does not use the portal app registration, and there is no client secret in this path.
- That identity holds no Microsoft Graph or Intune permissions. It authenticates to Bot Framework and nothing else. Expanding the group behind a notification is done by the App Serviceβs system-assigned managed identity, like every other Graph call.
- Proactive messages are sent via
BotAdapter.ContinueConversationAsyncorCreateConversationAsync, authenticated with the same managed identity - No additional Microsoft Graph API permissions are required for Teams bot notifications. Bot Framework handles its own auth channel.
Data stored:
BotConversationReferencestable stores per-user conversation references for proactive messaging- Contains: User ID (Microsoft Entra ID object ID), Conversation ID, Service URL, serialized ConversationReference JSON
- Conversation references are encrypted/signed by Bot Framework and tied to the bot credentials that created them
- If bot credentials change, existing conversation references become invalid and must be cleared
Identity and access management
Section titled βIdentity and access managementβSystem-assigned managed identity
Section titled βSystem-assigned managed identityβThe App Service is configured with a System-Assigned Managed Identity. This identity is automatically created and managed by Azure.
"identity": { "type": "SystemAssigned"}Purpose: The Managed Identity allows the application to authenticate to Azure services without storing credentials in code or configuration.
Role assignments
Section titled βRole assignmentsβThe following permissions are granted to the Managed Identity:
| Permission Type | Scope | Purpose |
|---|---|---|
| Website Contributor Role | App Service | Enables in-app updates via Azure Resource Manager |
| Key Vault Access Policy (Get, List Secrets) | Key Vault | Read application secrets from Key Vault |
Why Website Contributor?
The in-app update feature allows administrators to update the application from within the portal. To do this, the application must be able to modify its own WEBSITE_RUN_FROM_PACKAGE app setting. The Website Contributor role grants this permission.
Why Key Vault Access?
Sensitive connection strings (SQL, storage) are stored in Azure Key Vault and read at runtime through the App Serviceβs managed identity.
There is no Microsoft Entra ID client secret. The App Service authenticates to Microsoft Graph as its own system-assigned managed identity and the Teams bot as its own user-assigned managed identity, so there is no application password anywhere in the product to store, reference, rotate or lose.
Scope limitation: All permissions are scoped to the minimum required resources (not the resource group or subscription), following the principle of least privilege.
{ "type": "Microsoft.Authorization/roleAssignments", "scope": "[concat('Microsoft.Web/sites/', variables('appName'))]", "properties": { "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772')]", "principalId": "[reference(resourceId('Microsoft.Web/sites', variables('appName')), '2022-09-01', 'full').identity.principalId]", "principalType": "ServicePrincipal" }}Microsoft Entra ID app registration
Section titled βMicrosoft Entra ID app registrationβApp Store for Intune uses a single Microsoft Entra ID app registration. It serves two roles bound to the same client ID: it validates incoming user tokens (the API trusts only tokens whose audience matches this client ID, then checks the scope) and it powers the single-page application sign-in flow.
Application type: Single-page application (SPA)
Authentication:
- Client ID only. There is no client secret: the App Service uses its managed identity for all service-to-service calls.
- MSAL.js with the authorization code flow and PKCE
API permissions (delegated):
| API | Permission | Type | Purpose |
|---|---|---|---|
| Microsoft Graph | User.Read | Delegated | Read the signed-in userβs profile and photo |
Token configuration:
- Access tokens issued for:
api://{client-id} - Scope exposed:
access_as_user
Redirect URIs (Single-page application platform):
https://{app-name}.azurewebsites.net/https://{custom-domain}/(if a custom domain is configured)
The Microsoft Graph application permissions App Store uses to call Intune, manage groups, read users, and send mail are not held on this app registration. They are granted to the App Serviceβs managed identity instead. See Managed identity configuration.
Optional: the workload API registration
Section titled βOptional: the workload API registrationβIf you enable unattended API access, a second app registration exists, separate from the sign-in one above. It holds no client secret, no certificate, no Microsoft Graph permissions and no Intune permissions. Its only contents are an Application ID URI, which names the audience, and App Storeβs application roles.
Keeping it separate is deliberate: the registration your staff authenticate against keeps its property of holding no credentials and no application roles, and a mistaken role assignment on a registration that exists only to hold roles cannot reach the sign-in identity.
The caller authorised through it is a customer-controlled managed identity, typically an Azure Automation Accountβs. It can perform seven reads and cannot approve, reject or change anything. See Call the API from Azure Automation.
If unattended access is not configured, this registration does not exist and App Store accepts no application token.
Teams bot note: No Microsoft Graph permissions are required for Teams bot notifications. Bot Framework handles its own authentication, and as of v1.30.0 the bot authenticates with a dedicated user-assigned managed identity (no client secret). Do not add TeamsActivity.Send or similar permissions; they are not used by this application.
Managed identity configuration
Section titled βManaged identity configurationβHow the managed identity works
Section titled βHow the managed identity worksβ-
Creation: When the ARM template deploys, Azure automatically creates a service principal in Microsoft Entra ID for the App Service.
-
Environment variables: Azure injects these environment variables into the application:
MSI_ENDPOINTorIDENTITY_ENDPOINT: Token endpoint URLIDENTITY_HEADER: Secret header for authenticationWEBSITE_SITE_NAME: App Service nameWEBSITE_RESOURCE_GROUP: Resource group nameWEBSITE_OWNER_NAME: Subscription ID
-
Token acquisition: The application uses
DefaultAzureCredentialfrom Azure.Identity SDK to acquire tokens:var credential = new DefaultAzureCredential();var armClient = new ArmClient(credential); -
Authorization: The Managed Identity authenticates to Azure Resource Manager and is authorized via the Website Contributor role assignment.
Microsoft Graph application permissions
Section titled βMicrosoft Graph application permissionsβThe same system-assigned managed identity also holds the Microsoft Graph application permissions App Store uses to call Microsoft Graph as itself, with no client secret. These are granted once after deployment by the Grant Microsoft Graph permissions PowerShell snippet:
| Permission | Purpose |
|---|---|
DeviceManagementApps.Read.All | Read the Intune app catalog and assignment state |
DeviceManagementApps.ReadWrite.All | Create and update Intune Win32 app deployments |
DeviceManagementConfiguration.Read.All | Read Intune assignment filters used by ring deployment settings |
DeviceManagementManagedDevices.Read.All | Read managed devices associated with the requesting user |
Device.Read.All | Resolve an Entra device from its Azure AD Device ID. Group membership is added by directory object, so this is what lets an app assigned to devices reach the device |
Group.ReadWrite.All | Create and manage the security groups that drive app assignments |
GroupMember.Read.All | Resolve whether a user is in a group, which is how the admin, approver, portal access and app target groups are evaluated |
User.Read.All | Read user profiles, managers, and group memberships for approvals |
Mail.Send | Send email notifications from a configured mailbox (optional) |
DeviceManagementManagedDevices.PrivilegedOperations.All | Ask a device to check in with Intune, for the Check status action on My Devices (optional, not granted by default) |
App Store asks for the narrowest permission that does each job. Device.Read.All grants reading device objects and nothing more; Directory.Read.All, which would also cover it, is deliberately not requested.
The one optional permission is the exception, and not by choice. DeviceManagementManagedDevices.PrivilegedOperations.All is the only permission Microsoft offers for a device check-in, and the same grant also covers wipe, retire, and rename. There is no narrower tier. App Store never calls wipe, retire, or rename; it calls check-in and nothing else. Because the granted authority is wider than the feature, the permission is left out of the setup snippet, has to be granted deliberately, and then still does nothing until an administrator separately enables the action in Store Administration. Every attempt is written to the audit log, refusals included.
What the managed identity can do
Section titled βWhat the managed identity can doβ- Call Microsoft Graph as the application using the granted permissions above (read and write Intune apps, manage groups, read users, send mail)
- Read and update the App Serviceβs own configuration settings
- Read the App Serviceβs properties
- Restart the App Service
- Read secrets from the provisioned Key Vault (Get, List permissions only)
What the managed identity canβt do
Section titled βWhat the managed identity canβt doβ- Access other resources in the subscription
- Modify other App Services
- Write, delete, or manage secrets in Key Vault
- Access SQL Database directly (uses SQL authentication via connection string from Key Vault)
- Deploy or delete resources
Network security
Section titled βNetwork securityβInbound traffic
Section titled βInbound trafficβ| Protocol | Port | Source | Destination | Purpose |
|---|---|---|---|---|
| HTTPS | 443 | Internet | App Service | User access |
| HTTPS | 443 | App Service | Azure SQL | Database connections |
| HTTPS | 443 | App Service | Microsoft Graph | API calls |
| HTTPS | 443 | Bot Framework Service | App Service | Teams bot messages (/api/messages) |
| HTTPS | 443 | App Service | Bot Framework Service | Proactive bot notifications |
App Service network configuration
Section titled βApp Service network configurationβ- Public Access: Enabled (internet-accessible)
- TLS 1.2: Minimum version enforced
- HTTPS Only: HTTP requests redirected to HTTPS
- IP Restrictions: None by default (can be configured)
SQL Server firewall
Section titled βSQL Server firewallβThe SQL Server is configured with the following security controls:
- Azure Services: Allowed (firewall rule
AllowAllWindowsAzureIps)- This allows the App Service to connect to the database
- Other Azure services in the subscription cannot access unless explicitly allowed
- Public IP Access: Denied by default
- No client IP addresses are on the allowlist
- Database is not accessible from the internet
- Private Endpoint: Not configured by default (can be added for enhanced security)
To verify SQL firewall rules:
az sql server firewall-rule list --server <server-name> --resource-group <rg-name>To add a client IP for temporary admin access:
az sql server firewall-rule create --server <server-name> --resource-group <rg-name> \ --name "AdminAccess" --start-ip-address <your-ip> --end-ip-address <your-ip>Remember to remove temporary rules after use.
Recommendations for enhanced security
Section titled βRecommendations for enhanced securityβConditional Access policies
Section titled βConditional Access policiesβWe strongly recommend configuring the following Microsoft Entra ID Conditional Access policies for App Store for Intune. Target them at the App Store app registration. Since v1.34.0 there is one registration: it both hosts the single-page application sign-in and is the audience the API validates tokens against, so a single policy covers the whole sign-in path.
| Policy | Description | Why It Matters |
|---|---|---|
| Require MFA | Require multifactor authentication for all users accessing the portal | Prevents unauthorized access from compromised credentials |
| Require compliant device | Only allow access from Intune-compliant devices | Since this portal manages Intune apps, ensuring the requesting device meets compliance is a natural fit |
| Require managed device | Only allow access from Microsoft Entra ID joined or hybrid joined devices | Prevents access from personal/unmanaged devices |
| Block risky sign-ins | Block sign-ins flagged as medium or high risk by Microsoft Entra ID Identity Protection | Automatically blocks access when suspicious activity is detected (requires Microsoft Entra ID P2) |
| Restrict by location | Only allow access from trusted named locations (office IPs, VPN ranges) | Limits exposure to known network boundaries |
| Sign-in frequency | Require re-authentication every 8-12 hours | Limits the window of exposure from a stolen session token |
Network security enhancements
Section titled βNetwork security enhancementsβ- Virtual network integration: Deploy App Service into a VNet
- Private endpoints: Use private endpoints for SQL and storage
- IP restrictions: Limit access to known IP ranges
- Azure Front Door: Add WAF protection
Data protection
Section titled βData protectionβData at rest
Section titled βData at restβ| Data Type | Storage Location | Encryption |
|---|---|---|
| Application data | Azure SQL Database | TDE (Transparent Data Encryption) |
| User settings | Azure SQL Database | TDE |
| Branding assets | Azure SQL Database | TDE |
| Bot conversation references | Azure SQL Database | TDE |
| Logs | Log Analytics | Azure-managed encryption |
Data in transit
Section titled βData in transitβ- All communication uses TLS 1.2+
- HTTPS enforced at App Service level
- SQL connections use encrypted connections
Sensitive data handling
Section titled βSensitive data handlingβ| Data | Storage Method | Notes |
|---|---|---|
| SQL Connection String | Azure Key Vault | Referenced via Key Vault reference in App Settings |
| Storage Connection String | Azure Key Vault | Referenced via Key Vault reference in App Settings |
| User tokens | Session storage (browser) | Not persisted server-side |
| Action tokens | SQL Database | GUID per request, used for email approve/reject |
| Bot conversation references | SQL Database | Conversation IDs and service URLs for Teams proactive messaging |
| Audit logs | SQL Database | Retained indefinitely |
Secrets management
Section titled βSecrets managementβAll sensitive secrets are stored in Azure Key Vault and accessed via Key Vault references:
ConnectionStrings__DefaultConnection = @Microsoft.KeyVault(SecretUri=https://{vault}.vault.azure.net/secrets/SqlConnectionString/)AzureStorage__ConnectionString = @Microsoft.KeyVault(SecretUri=https://{vault}.vault.azure.net/secrets/StorageConnectionString/)Key Vault security features:
- Secrets encrypted at rest with Azure-managed keys
- Soft delete enabled (7-day retention for accidental deletion recovery)
- Access restricted to the App Serviceβs Managed Identity only
- No direct secret access for users or administrators (must use Azure Portal/CLI with appropriate permissions)
- All secret access is logged in Key Vault diagnostic logs
Secret and key rotation
Section titled βSecret and key rotationβMicrosoft Entra ID credentials:
App Store no longer uses a client secret. The App Service authenticates to Microsoft Graph with its managed identity, so there is no Microsoft Entra ID secret to rotate or expire.
SQL password rotation:
- Reset password in Azure Portal β SQL Server β Reset admin password
- Update connection string in Key Vault:
Terminal window az keyvault secret set --vault-name <vault-name> --name SqlConnectionString --value "Server=tcp:..." - Restart App Service
Emergency key rotation:
If you suspect a secret has been compromised:
- Immediately rotate the affected secret using the steps above
- Review Key Vault access logs for unauthorized access
- Review App Service logs for unusual activity
- Consider rotating all secrets if compromise scope is unknown
Certificate management
Section titled βCertificate managementβSSL certificates:
| Certificate Type | Management | Renewal |
|---|---|---|
| Azure-managed (default) | Automatic | Auto-renewed by Azure |
| Custom domain with Azure certificate | Automatic | Auto-renewed by Azure |
| Custom uploaded certificate | Manual | Upload new certificate before expiration |
Microsoft Entra ID app credentials:
There are none to monitor. The App Store app registration has no client secret and no certificate; both identities that do privileged work are managed identities, and Azure issues those tokens to the workload itself.
Monitoring expiration:
Set up Azure Monitor alerts for:
- Key Vault secret expiration (90 days before), for the SQL and storage connection strings
- SSL certificate expiration (if you use a custom domain)
# Check Key Vault secret expiration datesaz keyvault secret list --vault-name <vault-name> --query "[].{name:name, expires:attributes.expires}"Authentication flow
Section titled βAuthentication flowβββββββββββββββββ ββββββββββββββββ βββββββββββββββββ Browser β β Entra ID β β App Service βββββββββ¬ββββββββ ββββββββ¬ββββββββ ββββββββ¬ββββββββ β β β β 1. Navigate to app β β ββββββββββββββββββββββββββββββββββββββββββββββββ>β β β β β 2. Redirect to sign-inβ β β<ββββββββββββββββββββββββββββββββββββββββββββββββ β β β β 3. User authenticates β β ββββββββββββββββββββββββ>β β β β β β 4. Return tokens β β β<ββββββββββββββββββββββββ β β β β β 5. API call with token β ββββββββββββββββββββββββββββββββββββββββββββββββ>β β β β β β 6. Validate token β β β<ββββββββββββββββββββββββ β β β β β 7. Token valid β β ββββββββββββββββββββββββ>β β β β β 8. API response β β β<ββββββββββββββββββββββββββββββββββββββββββββββββToken validation
Section titled βToken validationβThe API validates JWT tokens from Microsoft Entra ID:
- Issuer: Must match Microsoft Entra ID tenant
- Audience: Must match API Client ID
- Signature: Validated using Microsoft Entra ID public keys
- Expiration: Token must not be expired
- Claims: User identity extracted from token
Authorization model
Section titled βAuthorization modelβRole-based access control
Section titled βRole-based access controlβ| Role | How Assigned | Capabilities |
|---|---|---|
| User | Any authenticated user | Browse apps, submit requests, view own requests |
| Approver | Member of Approver Microsoft Entra ID Group | Approve/reject requests, view pending approvals |
| Admin | Member of Admin Microsoft Entra ID Group | Full access, manage apps, settings, users |
Group-based authorization
Section titled βGroup-based authorizationβAuthorization groups are configured in the database (PortalSettings table):
AdminGroupId -- Microsoft Entra ID Group Object ID for adminsApproverGroupId -- Microsoft Entra ID Group Object ID for approversUserAccessGroupId -- (Optional) Restrict access to specific groupAuthorization check flow
Section titled βAuthorization check flowβ// Check if user is adminvar userId = User.FindFirstValue("oid");var isAdmin = await _azureADService.IsUserInGroupAsync(userId, adminGroupId);Audit logging
Section titled βAudit loggingβWhat is logged
Section titled βWhat is loggedβ| Event | Data Captured |
|---|---|
| App request submitted | User ID, App ID, Device ID, Timestamp |
| Request approved/rejected | Reviewer ID, Decision, Comments, Timestamp |
| Settings changed | User ID, Setting changed, Old/New values |
| App sync | User ID, Apps added/updated, Timestamp |
| User sign-in | User ID, IP address, Timestamp |
| Administrative change (1.39.0) | Every write action in the administration API (settings, apps, workflows, packaging, updates, permissions) is recorded as Controller.Action with User ID, IP address, Timestamp |
| Access denied (1.39.0) | Access.Denied: the endpoint and the identity that was refused |
| Request cancelled (1.39.0) | Request.Cancelled: User ID, Request ID, Timestamp |
| Portal update (1.39.0) | Portal.UpdateRequested and Portal.UpdateInstalled, including the package URL applied and the one it replaced |
Audit log storage
Section titled βAudit log storageβ- Location: SQL Database (
AuditLogstable) - Retention: Indefinite (no automatic purge)
- Access: Admin-only via Reports section
Log schema
Section titled βLog schemaβCREATE TABLE AuditLogs ( Id NVARCHAR(450) PRIMARY KEY, UserId NVARCHAR(450) NOT NULL, UserEmail NVARCHAR(255) NOT NULL, Action NVARCHAR(100) NOT NULL, EntityType NVARCHAR(100) NOT NULL, EntityId NVARCHAR(450) NOT NULL, Details NVARCHAR(MAX), -- JSON payload Timestamp DATETIME2 NOT NULL, IpAddress NVARCHAR(50) NOT NULL);Security checklist
Section titled βSecurity checklistβPre-deployment
Section titled βPre-deploymentβ- App Store app registration created with delegated
User.Readonly, no client secret, and no application permissions - Microsoft Graph application permissions granted to the App Serviceβs managed identity, not to the app registration
- Admin consent granted for application permissions
- Strong SQL administrator password configured
- Deployed by a person, who becomes the initial administrator, or, for an automated deployment, Admin Group ID configured
- Approver Group ID configured (restricts approver access)
Post-deployment
Section titled βPost-deploymentβ- Verify HTTPS-only access working
- Test authentication flow
- Verify role-based access (admin vs. user)
- Review Microsoft Entra ID sign-in logs
- Enable Azure Security Center recommendations
- If Teams bot enabled: verify Azure Bot App ID matches
AzureAd:ClientId - If Teams bot enabled: test bot notification delivery
Ongoing operations
Section titled βOngoing operationsβ- Review audit logs regularly
- Monitor failed authentication attempts
- Update application when security patches released
- Review and remove unused app permissions
Optional enhancements
Section titled βOptional enhancementsβ- Enable Microsoft Entra ID Conditional Access policies (see Recommended Policies)
- Configure Microsoft Entra ID Identity Protection (required for risk-based CA policies)
- Implement Private Endpoints for SQL and Key Vault
- Add Azure Front Door with WAF
- Enable Azure Defender for App Service
- Azure Key Vault for secrets (enabled by default)
Package verification
Section titled βPackage verificationβApps deployed to Intune via the App Store originate as YAML manifests in the microsoft/winget-pkgs community repository. Each manifest declares an installer URL and the SHA256 hash that installer must match. The packaging pipeline verifies the downloaded installer against that hash before wrapping it for Intune (PackagingQueueService.DownloadFromGitHubAsync).
That hash check defends against a tampered installer at the publisherβs download server, but it trusts the manifest itself. The manifest is fetched from raw.githubusercontent.com over HTTPS, and anyone able to MITM that connection (or substitute a manifest in a compromised mirror) could feed the pipeline a manifest that points at a malicious installer with a matching hash.
Verified chain via source2.msix
Section titled βVerified chain via source2.msixβTo close that gap, the App Store can verify each package against Microsoftβs signed community index. The WinGet client itself uses this same chain (see PackagesTable.h in winget-cli for the upstream schema).
How it works (when VerifyManifestIntegrity is enabled):
- The portal downloads
source2.msixfromhttps://cdn.winget.microsoft.com/cache/source2.msix. - The .msix contains a SQLite database (
Public/index.db) with apackagestable: one row per package Microsoft has reviewed and merged into the community repository, with the SHA256 of the packageβs version data manifest in thehashcolumn. - Before packaging any WinGet-sourced app, the portal looks the package up in this index. If the package is not present, the packaging job fails with an explicit βManifest integrity check failedβ error rather than silently falling back to an unverified path.
- The downloaded MSIX and extracted SQLite are cached on disk for 12 hours so repeat lookups donβt re-download the ~10 MB archive.
What this protects against:
- Tampered manifest substituted on the GitHub fetch path. A malicious manifest for a non-existent or non-merged package ID will fail the index lookup.
- An attacker pointing an existing package ID at a different installer. Once paired with the version-data-manifest hash check (planned, see roadmap below), the manifest contents can be cryptographically tied back to what Microsoft moderators reviewed.
What this does not yet protect against (v1 limitations):
- The full design (documented internally as the WinGet manifest verification specification) calls for fetching the version data manifest from the Azure CDN by content-addressed URL and verifying its hash against the SQLite value, then doing the same for each per-version merged manifest. v1 implements only the index lookup gate; the hash-of-manifest comparison is a planned v2 enhancement.
- MSIX signature validation against Microsoftβs certificate chain (Authenticode-on-MSIX via WinTrust). v1 relies on HTTPS + DNS to
cdn.winget.microsoft.comas the trust root. A compromised CDN is out of scope for v1; v2 will add full signature validation.
Configuration: Store Administration > System, Catalog Sourcing, βVerify manifest integrity against Microsoftβs signed indexβ. Default is on. An upgrade turns it on once for installations that predate the default; after that an administratorβs choice is kept. Admins running internal hardened mirrors of the WinGet repo can turn it off and rely on their mirrorβs own integrity controls.
What the check does, precisely. It confirms that the package ID is present in Microsoftβs signed index and refuses to package anything that is not. It does not compare the contents of the manifest fetched from GitHub with the index. Separately, the installer the portal downloads must match the SHA-256 published in the manifest for the version being packaged, or packaging stops.
Failure mode: Verification failures are loud, not silent. The packaging job is marked failed and the error message names the package and explains the integrity check failed. There is no fallback to the unverified path while verification is enabled. The only escape valve is to disable the setting from the Settings page.
Compliance considerations
Section titled βCompliance considerationsβData residency
Section titled βData residencyβ- All data stored in the Azure region selected during deployment
- No cross-region data replication by default
Data retention
Section titled βData retentionβ- Audit logs: Retained indefinitely
- Application data: Retained until manually deleted
- App Insights logs: 90 days default (configurable)
GDPR considerations
Section titled βGDPR considerationsβ- User data limited to: Name, Email, User ID (from Microsoft Entra ID)
- No sensitive personal data stored
- Data can be exported/deleted upon request via database access
Incident response
Section titled βIncident responseβSecurity event indicators
Section titled βSecurity event indicatorsβMonitor for these events in Microsoft Entra ID and App Insights:
- Multiple failed sign-ins from same IP
- Unusual geographic access patterns
- Bulk data access (many API calls in short time)
- Privilege escalation attempts
- Configuration changes outside business hours
Response actions
Section titled βResponse actionsβ- Disable App Service if compromise suspected
- Rotate secrets (SQL password, storage keys). There is no Entra ID client secret to rotate; the App Service and the Teams bot both use managed identities
- Review audit logs for unauthorized access
- Revoke user access if account compromised
- Contact Azure Support for assistance
Contact
Section titled βContactβFor security questions or to report vulnerabilities:
- Email: info@powerstacks.com