PRIVATE WINGET REPOSITORY

Your own winget source, and only yours.

Attestree is a self-hosted winget repository that speaks the native winget REST protocol — so your endpoints resolve packages from a source you run, containing only the versions you approved. Every one of them was detonated in a real sandbox and signed before it was allowed in.

Free Community Edition — self-host up to 50 endpoints, no Azure required

THE SOURCE ITSELF

A real REST source, not a repackaging script.

Winget resolves packages over a documented REST protocol. Attestree answers it directly, so the native client on your endpoints talks to your server the same way it would talk to the public source — no wrapper, no re-authoring manifests, no second package format to maintain.

GET /manifestSearch

The search endpoint winget calls to resolve a name. Yours answers from your catalog, so a package you never admitted simply does not exist to the fleet.

GET /packageManifests/{PackageIdentifier}

The manifest fetch. Returns the exact version your ring policy says that endpoint should have, with the installer SHA-256 pinned.

Token-scoped per endpoint

Every endpoint gets its own feed token. Revoke one at decommission and that machine stops resolving packages, without touching the rest of the fleet.

WHY NOT JUST HOST A FEED

Hosting the packages is the easy half.

A feed answers "where from". It cannot answer "is this safe".

Hosting your own source controls provenance of delivery — nothing more. It does not inspect what the installer does. Attestree detonates every artifact in a real sandbox before admission, records the behaviour, and signs a verdict. The feed is the delivery half; the gate is the half that decides.

The bytes are yours, not the vendor’s CDN.

The feed can serve the attested installer bytes itself, over your LAN, pinned to the exact SHA-256 that was detonated. That removes the vendor download URL from the install path entirely — which is what makes a blocked CDN, a strict proxy, or a same-version republish a non-event rather than an outage.

Machine scope and user scope, both first class.

Most self-hosted winget setups run as SYSTEM and quietly break on per-user apps. Attestree treats scope as an attested catalog property and installs user-scope packages into the actual user’s profile — not SYSTEM’s.

A private repository only helps if the public one is switched off.

Standing up your own source does nothing while endpoints can still reach winget’s default community source and the Microsoft Store source. Disabling those is a Group Policy and Intune job — the DesktopAppInstaller ADMX, an allowed-sources policy, and a source lockdown that survives a user re-adding one.

How to fence it
FAQ

Straight answers.

What is a private winget repository?

It is a winget source you host yourself, instead of pointing your fleet at the public community repository. Winget speaks a documented REST protocol — a search endpoint and a manifest endpoint — so any server that implements it can act as a source. A private winget repo lets you decide which packages and which exact versions exist for your machines at all. Attestree implements that protocol and adds the part a plain feed does not have: an ingest gate that detonates and attests each artifact before it is allowed into the catalog.

Is this a real winget REST source, or a wrapper around winget-cli?

It is a real REST source. The control plane answers the documented winget source endpoints — information, manifestSearch and packageManifests — so the native winget client on your endpoints talks to it directly, with no wrapper script and no repackaging. Each endpoint authenticates with its own feed token.

How is this different from ProGet, Azure Artifacts, or winget-cli-restsource?

Those host a feed. That is a genuinely useful thing, and if all you need is somewhere to put manifests, they do it. What none of them do is inspect the artifact: there is no sandbox detonation, no CycloneDX SBOM generated at ingest, and no signed attestation recording what the installer actually did when it ran. Attestree is a source that refuses to serve what it could not verify, and leaves a signed receipt saying why.

Can I run an offline or air-gapped winget repository?

Your endpoints can be, and that is usually the half that matters: once a version is admitted and its bytes retained, endpoints resolve packages and download installers entirely from your server, so their egress collapses to a single allowlisted host instead of a fan of vendor CDNs. The control plane is a different story, and we would rather be blunt than sell you something that does not exist. Ingest reaches out — it fetches the manifest and the installer so they can be detonated — so the server needs upstream access at admission time. You move the egress rather than eliminating it. A genuinely air-gapped deployment, where nothing reaches out at all, is not something we ship today.

Does it handle per-user applications, or only machine-wide installs?

Both, and the per-user case is the one most self-hosted setups get wrong. Running winget as SYSTEM installs a per-user application into SYSTEM’s own profile, where the person who asked for it will never see it. Attestree carries scope as an attested property of the package, installs user-scope apps into the real user’s profile, and attributes each copy to the user who actually has it. When nobody is logged on, it holds honestly and retries rather than reporting a success that is not there.

What happens when someone runs winget install for a package you never approved?

It does not resolve, because the package does not exist in your source — but the request is recorded rather than silently dropped. Blocked demand becomes catalog signal: you can see what people are asking for and decide whether to ingest it, instead of finding out when someone files a ticket or installs it from a browser download.