30-second answer
Collection needs an Entra ID app registration and its client id. There is no default and there is no way around it, and the reason is a change in PnP.PowerShell rather than a choice made here.
Then choose one of two modes. Delegated signs a person in, interactively or with a device code, and the run sees what that person sees. Application-only authenticates the registration itself with a certificate, and the run sees what the tenant granted the application. They are not two prompts for the same thing, and the evidence records which one produced it.
Why --client-id is required
PnP.PowerShell removed its own multi-tenant application in 2.12.0. The release notes give the reason as the deprecation and shutdown of the PnP Management Shell.
A connection with no client id anywhere fails before it reaches the network:
Please specify a valid client id for an Entra ID App RegistrationSources, both checked 2026-08-09, and verified against PnP.PowerShell 3.3.0: the PnP.PowerShell changelog and the default client id article.
Why the collector will not read it from the environment
The module itself accepts a default client id, configured by a cmdlet or by an environment variable. This collector does not use either, and there are two separate reasons.
Evidence has to say which identity observed it. A value read from an ambient environment variable is one nobody can name afterwards, and provenance that cannot be named is not provenance.
The read-only gate is a regex over every file. A regex cannot tell a mention from a call, so naming the configuring cmdlet in the collector would mean loosening the pattern that proves nothing in the tree mutates a tenant. Loosening it is how a real write slips in.
Device code sign in
For a host with no browser:
m365-governance collect sites \
--client-id <id> \
--tenant-url https://<tenant>-admin.sharepoint.com \
--output ./evidence/ \
--device-loginApplication-only, with a certificate
For an unattended run, and for a run that must see the tenant rather than one person's view of it:
m365-governance collect owners \
--client-id <id> \
--tenant-id <tenant-id> \
--certificate-path ./app.pfx \
--certificate-password-env M365_GOVERNANCE_CERT_PASSWORD \
--site-url https://<tenant>.sharepoint.com/sites/<site> \
--output ./evidence.jsonA PFX. PnP.PowerShell 3.3.0's app-only parameter set takes ClientId,
Tenant, CertificatePath and CertificatePassword; it has no separate
private-key file, so a certificate and key have to be packaged together first.
A certificate with no password is supported: leave the option out.
The password is referenced, not written. --certificate-password-env takes
the name of an environment variable, and the collector reads it in its own
process. There is deliberately no option that takes the password itself: an
argument lives in the shell history, and in the process list of every user on
the machine, for as long as the command runs.
One mode per run. Naming both, or half of one, is refused before anything
reaches the network: a certificate together with --device-login, a
certificate without --tenant-id, a --tenant-id without a certificate, a
password variable that is unset, a certificate file that is not there.
Connecting is not being authorised
Connect-PnPOnline succeeds with zero permissions granted. Connecting
establishes who you are; what you may read is decided afterwards, by the
directory, when a command asks for something. A script that checks the
connection did not throw and then reports "connection verified" is verifying
authentication and reporting authorisation.
The two identities also differ in what they can resolve, and they differ
quietly. On a group-connected site read twice within a minute, a delegated
session returned the administrating group; an application-only identity holding
Sites.Read.All returned an empty list, with no error at all. An empty result
is not a smaller version of a full one, and which identity produced a document
is part of what the document says.
Where the credentials go
Nowhere near us. Authentication happens between you and Microsoft, with an identity you register in your own tenant. pH7x Systems receives no credentials, no token and no evidence: see the trust model for where the software runs, what it talks to, and what reaches us.
Which identity, and how much of it
The identity travels into every report:
- Identity: application, scopes: Sites.Read.AllTwo consequences follow, and both belong in the decision about what to grant.
Read only is the whole requirement. Nothing under the collector tree calls a mutating cmdlet, and CI proves it by parsing every file. An identity with write permissions grants more than the tool can use.
What the identity cannot see does not appear. A site absent from a sites
collection is a site this identity could not enumerate, not a site that does
not exist. Under-scoping produces a report that understates the estate while
looking complete.