How we keep your tenant safe

Read-only by design, and verifiable by anyone.

Tenant Strike can see your Microsoft 365 and Azure settings. It cannot change them. And you don’t have to take our word for it — the proof, down to every single API call we make, is published on this page.

01

Read permissions only

When your admin grants access, the 19 Microsoft permissions we request are all read-only — they let us see configuration, not change it. We don't request any "write" permission, because we don't have any code that could use one.

02

No changes to your tenant — ever

Our scanner lists users, reads policies, and checks settings. It cannot create, modify, or delete anything in your Microsoft 365. The endpoint manifests below show the reads in our code and let you review their permissions. A manifest describes the code; it is not a complete log of requests from an individual scan.

03

Auditable by anyone

Our build process automatically lists every API call in our code and fails the build if any "write" call sneaks in. Your security team can verify it themselves in five minutes — evidence below.

What we look at

Eight security surfaces — read-only, all of them.

Tenant Strike checks the parts of your Microsoft 365 tenant and Azure subscriptions that attackers target. Here's what each surface covers; the full check-by-check list is below.

  • Identity

    Sign-in policies, MFA enforcement, admin accounts, guest access, device registration settings, and unresolved user risk reported by Entra ID Protection. We read security configuration and risk state, never passwords.

  • Email

    DMARC, SPF, DKIM, Defender for Office policies, forwarding rules. We never read message content.

  • Sharing & collaboration

    SharePoint, OneDrive, and Teams external-sharing settings. We see the settings, not the documents being shared.

  • Apps & consent

    Enterprise apps and the permissions they were granted. Useful for spotting OAuth phishing and over-privileged add-ins.

  • Devices

    Intune compliance, BitLocker, Defender for Endpoint coverage. We see device status, not what's on the device.

  • Azure

    Servers, storage, databases, networking, access and backup across every subscription you connect. Read-only via the Azure Reader role — never Contributor, never Owner.

  • Logging & alerting

    Whether your audit log is on, where security alerts go, and what gets recorded. The forensics-readiness surface.

  • External attack surface

    What your tenant looks like from the public internet — exposed ports, expired TLS, DNS health. Outside-in, not inside your tenant. We also make read-only HTTPS requests to the portals and domains you list, to read their product/version banners — only to hosts under a domain Microsoft has verified you own, and only when you opt in.

  • Configuration metadata only.
    Never file, mailbox, or chat content.

Latest coverage · September 2026

Two new checks. 149 in the catalog.

Device registration policy

Checks registration MFA, local administrator defaults for joined devices, and the tenant’s Windows LAPS backup switch. It reads policy configuration, not device passwords or proof that every device backs up its password.

Uses Policy.Read.DeviceConfiguration.

Risky users

Reports unresolved risk and confirmed compromise identified by Entra ID Protection. Requires Microsoft Entra ID P2 and the corresponding read permission. A missing license or unreadable response is shown as a coverage limitation.

Uses IdentityRiskyUser.Read.All.

Already connected? An administrator may need to refresh scanner consent to grant these two read permissions. Existing grants do not expand automatically. Your scan shows checks it could not verify; missing access is never treated as a pass. The AI assistant’s separate permission list is unchanged.

External scans also distinguish known Cloudflare shared proxy IPs from your origin servers. Shared proxy observations do not become findings about ports or vulnerabilities on your server. An unobserved origin is a coverage limitation, not evidence that the origin is secure.

Permissions we request

The exact list — all read-only.

These are the 19 Microsoft Graph permissions your admin grants at consent time. They allow reading security configuration and assessment data. No permission in this list grants write access; Tenant Strike cannot change your Microsoft settings.

AI Assistant · Beta

A second app, with a shorter list.

The AI assistant does not borrow the scanner’s access. It is a separate Microsoft app registration with its own, narrower set of 11 permissions, which your admin consents to separately and can revoke on its own. Three consequences worth being concrete about: authentication appears in your Entra sign-in logs under their own name, “Tenant Strike AI Assistant”, identifying app access rather than every API request; revoking it does not stop your scans; and it is limited to its own consented permissions.

Permissions
11
Write scopes
0
Calls in the manifest
18
  • User.Read.Allread

    Who your users are — names, addresses, whether the account is active.

  • Group.Read.Allread

    Your groups and who is in them.

  • Reports.Read.Allread

    Which users have actually registered for multi-factor sign-in.

  • AuditLog.Read.Allread

    Sign-in history and recent admin changes.

  • Policy.Read.Allread

    Your Conditional Access rules.

  • Application.Read.Allread

    Apps connected to your tenant and what they were granted.

  • RoleManagement.Read.Directoryread

    Who holds admin roles, including standby (PIM) assignments.

  • SharePointTenantSettings.Read.Allread

    Your SharePoint and OneDrive sharing settings.

  • DeviceManagementManagedDevices.Read.Allread

    Whether your enrolled devices are compliant.

  • SecurityEvents.Read.Allread

    Your Microsoft Secure Score.

  • ServiceHealth.Read.Allread

    Microsoft outages affecting your tenant.

What it does not ask for

  • No access to email, files, chats, or calendars — no Mail, Files, or Chat permission is requested.
  • No write access of any kind. Every permission above ends in .Read; the assistant cannot change a setting, a user, or a policy.
  • No passwords or secrets. The assistant reads whether MFA is registered, never the phone numbers or keys behind it.

What leaves our servers is a separate question from what we can read, and it deserves a straight answer: your findings go to the AI provider you chose, under your own account and key, and email addresses, IP addresses and display names are replaced with placeholders before they are sent. The full data-handling detail is on the assistant’s page.

Optional external AI connections

Your saved assessments in Claude or ChatGPT.

Workspaces on either paid plan, on a trial, or managed by an MSP can use the read-only Tenant Strike connector. Sharing starts off. The customer’s administrator must enable it, and each administrator or authorized MSP team member separately approves one tenant for their connection. No AI API key is required.

The connector shares sanitized security facts, scores, findings and conditional attack paths from saved assessments. Names, email addresses, organization and resource identifiers, and customer-written text are withheld. Reference labels can correlate observations; the security information remains confidential, not anonymous. Identifying evidence opens separately after Tenant Strike sign-in.

Its separate Microsoft sign-in app requests only openid, profile and email. It cannot run scans, query Microsoft live, change tenant settings or reuse the scanner’s permissions. You choose a connection duration from 24 hours to six months; 30 days is the default. Access remains subject to current tenant permissions and can be revoked sooner. Revocation stops future reads; it does not remove information already in an AI provider’s chat history, which follows your agreement with that provider.

Continuous monitoring

What we register with Shodan — and what we refuse to.

On Pro, we watch your internet-facing addresses between scans by registering them with Shodan Monitor, which notifies us when one of them changes. This is the one place we routinely hand anything derived from your account to a third party, so here is the whole of it: we send IP addresses and nothing else. No names, no user accounts, no findings, no configuration. Nothing from inside your tenant is involved at any point — this operates entirely on what is already publicly visible from the internet.

What we register

Only addresses you provably control: resources read from your own Azure subscription, the A record for your primary domain and its www, and hostnames under a domain Microsoft has verified you own.

What we refuse to register

Addresses behind a CDN, and shared Azure platform infrastructure. Those are shared with thousands of unrelated sites, so watching one would mean emailing you about a stranger’s server. We record the exclusion and its reason rather than dropping the asset silently.

What reaches you

An email when a watched address changes — a new service or port, a database open to the internet, an expired TLS certificate, or software showing as known-vulnerable or end-of-life.

Storage and encryption

Encrypted in transit and at rest — and who holds the keys.

Your scan results live in Microsoft Azure, encrypted the whole way. “Encrypted” is a word that hides a lot, though — it rarely says who can decrypt, or who audited the claim. So here is the whole of it, including the parts we have not done yet.

In transit

The dashboard is served over HTTPS (TLS 1.2 or higher). Our application’s own connection to its database enforces TLS with full certificate verification — that link carries every tenant’s data, so an unverified handshake is not an option. Everything we read from your tenant comes over Microsoft Graph on HTTPS.

At rest

Scan results, tenant records and backups sit in Azure Database for PostgreSQL, Azure managed disks and Azure Blob Storage, each encrypted with AES-256 using Microsoft-managed keys. Application secrets live in Azure Key Vault and are fetched at deploy time through a managed identity — never committed to the codebase. We hold read-only permissions in your tenant and never receive your users’ passwords.

What this is not

The keys are Microsoft’s, not ours and not yours — customer-managed keys are not offered today. Data is protected by platform encryption and access control, not encrypted field by field inside the application. And no third party has audited any of this: our encryption meets what SOC 2 (CC6.7), ISO 27001 (A.8.24) and NIST 800-53 (SC-8, SC-28) ask for, but we are aligned with those standards, not certified against them. We would rather you hear that from us than discover it in a questionnaire.

Everything we check

All 149 checks, by name.

Not a category summary — the actual list, generated from the scanner's own registry when this page was built. Some checks need a specific Microsoft licence to return anything; those say so, and report honestly that they could not run rather than passing you by default.

Identity (25)
  • Use dedicated admin accountsHighidentity.admin-account-hygiene

    Admin work should happen on dedicated cloud-only accounts — no mailbox attached (no inbox to phish), no on-prem sync (no AD compromise = no tenant compromise). This is CIS M365 control 1.1.1.

  • Allow only strong MFA methodsMediumidentity.authentication-methods-policy

    A code sent by text message or voice call can be stolen with a SIM swap or relayed through a phishing proxy (Evilginx, EvilProxy). Microsoft Authenticator is stronger, and passkeys (FIDO2) are the methods Microsoft counts as phishing-resistant.

  • Emergency access (break-glass) accountsMediumidentity.break-glass-accounts

    Microsoft recommends two cloud-only Global Administrator accounts excluded from Conditional Access, so a bad policy, an expired federation certificate or an MFA outage cannot lock every administrator out of the tenant at once. This is a resilience control: without it, recovery from a lockout runs through Microsoft support and takes days.

  • Require MFA for adminsCriticalneeds EntraID_P1identity.ca.admin-mfa

    Checks a universal MFA baseline or an enforcing policy covering the 14 documented reference admin roles. Exclusions, custom roles and effective sign-ins need separate review.

  • Require phishing-resistant MFA for adminsMediumneeds EntraID_P1identity.ca.admin-phishing-resistant

    A code by text or an app approval can be relayed by a fake sign-in page. Passkeys, Windows Hello for Business and certificate-based MFA cannot. This checks that a Conditional Access policy makes admins use one of those for the same admin roles the admin MFA check covers.

  • Block device code flowHighneeds EntraID_P1identity.ca.device-code-flow-blocked

    Device code flow lets an attacker phish a working access token without a fake login page: the victim types a real code into a real Microsoft sign-in page, completes MFA themselves, and the resulting token goes to the attacker. Almost no organisation needs the flow, and Conditional Access can switch it off.

  • Conditional Access exclusions have outgrown break-glassHighneeds EntraID_P1identity.ca.exclusion-sprawl

    A Conditional Access policy only protects the people it applies to. Exclusion lists start as two break-glass accounts and grow — an exempt group here, a service account there — until the MFA policy the tenant believes is universal quietly isn't. This check reports who is exempt from the policies that enforce MFA and block legacy authentication.

  • Block legacy authenticationHighneeds EntraID_P1identity.ca.legacy-auth-blocked

    Checks for a policy blocking both legacy client types across all users and applications. A restricted or excluded policy cannot establish tenant-wide blocking.

  • Require MFA for all usersCriticalneeds EntraID_P1identity.ca.mfa-coverage

    Checks for a mandatory MFA policy covering modern sign-ins for all users and applications, with policy exceptions and unsupported scopes left for review.

  • Conditional Access policies stuck in Report-onlyMediumneeds EntraID_P1identity.ca.report-only-stalled

    A Report-only Conditional Access policy is evaluated on every sign-in and then ignored — it writes a verdict to the log and lets the sign-in through regardless. Report-only is the correct place to START a policy, but a policy left there for months is protection the tenant believes it has and does not.

  • Block risky sign-insMediumneeds EntraID_P2identity.ca.risky-signin-policy

    With Entra ID P2 you get Identity Protection — Microsoft scores every sign-in for risk (impossible travel, anonymous IP, leaked credentials, etc.). A CA policy that requires MFA or blocks high-risk sign-ins turns those signals into active defenses.

  • Keep trusted locations to your own networksMediumneeds EntraID_P1identity.ca.trusted-locations-broad

    A location marked trusted is often allowed to skip MFA and counts as lower risk. This flags trusted address ranges of 65,536 addresses or more, which cover far more than one organisation's offices.

  • Limit what ordinary users can createMediumidentity.default-user-permissions

    By default every user in a Microsoft 365 tenant can register applications, create new tenants and security groups, and read the BitLocker recovery key of their own devices. An attacker who gets into one ordinary account inherits all of that.

  • Control device join and registrationMediumidentity.device-registration-policy

    Whether joining or registering a device needs MFA, who may do it, who becomes local administrator during device join, and whether Microsoft Entra allows Windows LAPS backups. These tenant settings do not prove endpoint deployment or compliance.

  • Limit Global AdministratorsHighidentity.global-admin-count

    Microsoft recommends 2-4 Global Administrators per tenant. Too few = no recovery if one is locked out; too many = oversized blast radius from a single compromised credential.

  • Restrict guest invitationsMediumidentity.guest-invite-policy

    If 'everyone' or 'all members' can invite guests, any compromised user can create an attacker-controlled guest account, then use it as a persistence mechanism even after the original account's password is reset.

  • Accounts with credentials in known breachesCriticalneeds EntraID_P2identity.leaked-credentials

    Microsoft Entra ID Protection matches your users against credential dumps found on the dark web and in law-enforcement seizures. An account flagged here has a password an attacker can already look up — the most direct route into a tenant there is, and one that no amount of perimeter hardening closes.

  • Stop sign-ins that still use legacy authenticationHighneeds EntraID_P1identity.legacy-auth-signins

    Old mail protocols such as IMAP, POP and SMTP AUTH sign in with a password alone and cannot ask for MFA. This reads the last 30 days of interactive sign-ins for them: a successful one is access no MFA policy covered, and failed ones are usually someone guessing passwords.

  • Do not expire passwordsMediumidentity.password-expiry-policy

    Forcing people to change their password on a schedule makes passwords weaker: they pick something predictable and change one character each time. Microsoft, CISA and CIS recommend passwords that do not expire, backed by MFA.

  • Review recent privileged changesMediumidentity.recent-privileged-changes

    Lists the privileged changes made in your tenant recently — apps granted access, new app secrets, and accounts given admin roles. These are the first things an attacker does after getting in, because each one survives a password reset. They are also normal administration, so the point is to confirm each one was you.

  • Remediate users flagged as at riskHighneeds EntraID_P2identity.risky-users

    Entra ID Protection rates every user's risk from Microsoft's signals — leaked passwords, anonymous or malicious IPs, impossible travel, token anomalies. A user left at risk is an signal that needs investigation. Open risk or an enabled account does not prove an active attacker or a successful sign-in.

  • Enable Security Defaults or Conditional AccessCriticalidentity.security-defaults-status

    Checks Security Defaults configuration or a supported Conditional Access MFA and legacy-auth baseline. Configuration does not establish an MFA challenge at every sign-in.

  • Remove stale admin accountsHighidentity.stale-admin-accounts

    Admin accounts that haven't been used in 90+ days are likely former employees or unused service accounts. They hold privilege but receive no ongoing scrutiny — a near-perfect target for a patient attacker.

  • Remove stale guest accountsMediumidentity.stale-guest-users

    Guest accounts that haven't signed in for 90+ days are likely abandoned but still have access to whatever they were invited to. They're a common lateral-movement vector after a third-party breach.

  • Register MFA for every userHighidentity.users-without-mfa

    Reports MFA registration gaps among the member accounts returned by Microsoft's registration report. Registration does not establish policy enforcement or observed authentication.

Email (17)
  • Enable impersonation protectionHighneeds DefenderForOffice_P1email.anti-phishing-policy

    Defender for Office's anti-phishing policy uses ML to detect spoofed and impersonating senders. By default impersonation protection of executives is OFF — every tenant should add their executives explicitly.

  • Keep the IP allow list narrowMediumneeds DefenderForOffice_P1email.connection-filter-permissive

    IPs in the connection filter allow list bypass Defender for Office's spam/phish/malware scanning entirely. Large ranges, stale entries, or Microsoft's bulk-sender 'SafeList' create permanent backdoors past your email security.

  • Enable anti-malware and auto-purgeHighneeds DefenderForOffice_P1email.defender.antimalware-zap

    Anti-malware policy blocks common malicious file types regardless of content (executables, scripts). Zero-hour Auto Purge (ZAP) retroactively removes mail from inboxes when Defender later identifies it as malware or phish — critical when threat signatures arrive minutes after delivery.

  • Enable Safe AttachmentsHighneeds DefenderForOffice_P1email.defender.safe-attachments

    Safe Attachments detonates inbound attachments in a sandbox before delivery. Without it, malicious documents reach users immediately, relying on the recipient's endpoint AV — which often runs minutes after the user has already opened the file.

  • Enable Safe LinksHighneeds DefenderForOffice_P1email.defender.safe-links

    Safe Links rewrites URLs in email, Teams chats, and Office apps so Microsoft can check them at click time (after attackers' detonation evasion has fired). Microsoft's built-in protection applies a basic Safe Links policy to every licensed mailbox by default. Exceptions to it, the stricter Standard and Strict presets, and Safe Links for Office apps are what an admin controls.

  • Remove stale allow-list entriesMediumneeds DefenderForOffice_P1email.defender.tabl-hygiene

    Each allow entry in the Tenant Allow/Block List bypasses Defender's spam, phish, and malware verdicts for the matching sender/URL/file. Permanent (no-expiration) and forgotten old entries become backdoors past your phishing protection.

  • Enable DKIM signingHighemail.dkim-records

    DKIM cryptographically signs outbound mail so receivers can verify it wasn't altered or spoofed. Without DKIM, DMARC enforcement is effectively weaker since SPF alone is fragile under forwarding.

  • Enforce DMARCHighemail.dmarc-policy

    DMARC tells receiving mail servers what to do with email that fails SPF and DKIM. Without it (or with p=none), attackers can spoof your domain with impunity — a primary BEC technique.

  • Tag external sendersMediumemail.external-sender-tag

    Outlook's 'External' tag marks every inbound message from outside the tenant. It's a simple but highly effective UX defense against CEO impersonation and fake-IT phishing — users learn to scrutinize external messages that claim to be internal.

  • Enforce TLS for inbound mailMediumemail.inbound-mail-tls

    MTA-STS tells sending servers to require TLS when delivering mail to your domain, preventing on-path attackers from stripping encryption. TLS-RPT surfaces when delivery TLS is failing or being downgraded.

  • Remove risky inbox rulesCriticalemail.inbox-forwarding-rules

    Inbox rules are the most common BEC persistence mechanism. Attackers create forwarding rules to exfiltrate mail in real time, or delete/move rules keyed on words like 'phish' or 'security' to hide their tracks. Microsoft's own incident reports consistently rank this as the #1 post-compromise action.

  • Make sure your MTA-STS policy actually worksMediumemail.mta-sts-policy

    Publishing the MTA-STS DNS record is only half of it — sending servers also fetch a policy file over HTTPS. If that file is missing or malformed, they ignore your policy entirely and mail can still be downgraded to an unencrypted connection.

  • Route mail through Microsoft 365Highemail.mx-records

    If the domain's MX record points somewhere other than M365, mail isn't flowing through Exchange Online Protection — meaning Defender for Office, anti-phish, Safe Links, and the rest of M365's mail filtering aren't actually inspecting inbound mail. Often unintentional after a migration.

  • Block external auto-forwardingHighemail.outbound-forwarding-policy

    If users can auto-forward email externally via inbox rules, an attacker who phishes one account silently exfiltrates ALL inbound mail to their own address — surviving password resets and session terminations.

  • Set outbound spam limitsMediumneeds DefenderForOffice_P1email.outbound-spam-limits

    Without sensible outbound rate limits, a compromised account can send tens of thousands of phishing emails (to internal users, to your customers) before Microsoft's tenant-level limits kick in. Tight per-user limits AND BlockUser action when the limit is hit contain the blast radius of any single account compromise.

  • Publish a valid SPF recordHighemail.spf-record

    SPF authorizes which mail servers may send for your domain. Missing, soft-fail (~all), or too-many-lookups SPF records let spoofed mail through.

  • Remove risky mail flow rulesHighemail.transport-rules-risky

    A single transport rule can bypass spam filtering tenant-wide, redirect mail to attacker addresses, or strip Microsoft-added authentication headers. Far higher leverage than per-mailbox rules, and far less commonly reviewed.

Sharing & Collaboration (13)
  • Restrict cross-tenant collaborationHighsharing.cross-tenant.b2b-collaboration

    By default, ANY user from ANY external Microsoft Entra tenant can be added as a guest in your tenant. Combined with permissive Teams settings, this lets attackers in any tenant DM and share files with your users — bypassing email security entirely.

  • Restrict Teams shared channelsHighsharing.cross-tenant.b2b-direct-connect

    B2B Direct Connect lets users from other tenants access your data without becoming guests in your directory. This bypasses guest-account lifecycle controls, access reviews, and many CA policies that target guests specifically. Should be enabled only with vetted partner tenants.

  • Restrict OneDrive external sharingInfosharing.onedrive.sharing-capability

    OneDrive external sharing is controlled by the tenant-wide external sharing setting and, per Microsoft, can only be equal to or more restrictive than SharePoint — never more permissive. This informational check surfaces OneDrive's effective ceiling; the tenant-wide level itself is graded by the SharePoint external sharing check. (The OneDrive-specific override is not exposed by the read-only Graph API.)

  • Restrict SharePoint external sharingHighsharing.sharepoint-external-sharing

    When SharePoint allows 'Anyone' links, any user can generate an unauthenticated URL that grants access to a file or folder — no sign-in required. These links leak via screenshots, forwarded emails, and search engines.

  • Expire anonymous sharing linksHighsharing.sharepoint.anonymous-link-expiration

    If Anyone links don't expire, a single leaked URL remains exploitable indefinitely. Forcing a max lifetime (≤30 days is industry standard) limits the damage window when a link inevitably ends up somewhere unintended.

  • Default share links to view-onlyMediumsharing.sharepoint.default-link-permission

    When users click Share without changing options, the link defaults to this permission level. Edit-by-default means recipients can modify or delete content — including invoices, contracts, customer lists.

  • Block guest re-sharingMediumsharing.sharepoint.guest-resharing

    If guests can re-share, content fans out to people you never invited or audited. Each re-share is invisible to you and survives even if the original guest's access is revoked.

  • Disable SharePoint legacy authenticationMediumsharing.sharepoint.legacy-auth

    SharePoint has its own legacy-auth toggle separate from the tenant-wide Conditional Access block. When enabled, certain SharePoint-specific basic-auth and ACS-based flows bypass modern identity controls.

  • Restrict OneDrive sync to managed devicesMediumneeds Intunesharing.sharepoint.unmanaged-sync-restriction

    Without this restriction, users can sync OneDrive (and SharePoint libraries) to ANY device including personal laptops. A user keeping a synced copy on a personal device circumvents BitLocker, MDM remote wipe, and conditional access — all your tenant controls only apply while the data is in M365.

  • Restrict anonymous meeting joinMediumsharing.teams.anonymous-meeting-join

    If anonymous users can join Teams meetings AND auto-bypass the lobby, attackers can silently join scheduled meetings using only the meeting link — which routinely leaks via calendar invites, support tickets, and screenshots. They can then record audio/video and read chat.

  • Restrict Teams custom appsMediumsharing.teams.app-installation

    If users can install custom (sideloaded) Teams apps, an attacker who phishes a user can deliver an OAuth-grant attack via Teams — bypassing email security and the typical consent-attack UX users are trained on.

  • Block personal Teams accountsHighsharing.teams.consumer-federation

    If enabled, any person with a free Microsoft account (Teams Personal) can DM and call your users. This is a primary Teams phishing vector — attackers spoof internal user display names and message employees with credential-harvesting links.

  • Restrict Teams external accessMediumsharing.teams.external-domains-restricted

    Without a domain allowlist, your users can be DM'd by users from any external Entra tenant. While the Cross-tenant Access policy controls guest invites, this is the separate control governing who can initiate Teams chats and calls from outside your tenant.

Apps & Consent (9)
  • Enable the admin consent workflowMediumapps.admin-consent-workflow

    If you've restricted user consent (recommended), users need a way to request admin approval for legitimate apps. Without an admin consent workflow, users either go without the app or find workarounds.

  • Rotate app credentialsMediumapps.app-secrets

    App registration secrets that expire silently cause outages; secrets with multi-year validity are credential-stuffing magnets if leaked. Both worth knowing about.

  • Review delegated app consent grantsHighapps.delegated-grants

    Reviews delegated grants against the target API. User-specific consent does not identify who granted consent, and granted scopes do not prove active access or bypass of authentication controls.

  • Keep owners of powerful apps to app administratorsHighapps.privileged-app-owners

    Whoever owns an app can add a secret to it and sign in as the app, with all of its permissions and no MFA. This lists apps registered here that hold high-risk Microsoft Graph permissions and are owned by someone who is not an app administrator.

  • Tighten app registration redirect URIsHighapps.redirect-uri-hygiene

    A redirect URI is the address Entra delivers sign-in tokens to. Wildcards, plain http, and leftover localhost entries widen that address from one host you control to a range someone else might occupy — turning your own app registration into a token delivery service for an attacker.

  • Review high-risk app permissionsHighapps.risky-permissions

    Reviews granted application permissions against their target API. Known broad Microsoft Graph grants are flagged; other APIs and unresolved permissions require review. Grants do not prove effective access or exploitation.

  • Credentials attached to service principalsHighapps.sp-credentials

    Passwords or certificates added to a service principal (not its app registration) let anyone holding them authenticate as the app. On a third-party app this is the classic persistent backdoor.

  • Retire dormant app identities that still hold accessMediumneeds EntraID_P1apps.unused-app-registrations

    An app registration nobody has used in months, that still holds application permissions or a live secret, is a standing credential with no owner watching it. Nobody notices when it starts being used, and nobody would miss it if it were deleted — which is exactly what makes it attractive to an attacker.

  • Restrict user app consentHighapps.user-consent-policy

    If end users can consent to OAuth apps without admin approval, illicit consent attacks succeed: a phishing-like link grants an attacker-controlled app permission to read mail and files, bypassing MFA entirely.

Devices (11)
  • Defender reports known software vulnerabilitiesHighdevices.defender.known-vulnerabilities

    Review known vulnerabilities reported by Defender, grouped by affected software with distinct CVE and device counts. A CVE observation is not proof of exploitation.

  • Onboard devices to DefenderHighneeds Intunedevices.defender.onboarding-coverage

    Corporate Windows devices should be covered by Defender for Endpoint/Business (EDR, not just signature AV) with tamper protection enabled so malware can't switch Defender off. This reports the tenant's Defender licensing capability and per-device tamper-protection state — the signals readable via Microsoft Graph. (Per-device MDE onboarding status isn't exposed by Graph; it lives in the Defender portal's machines API.)

  • Defender security recommendations need reviewMediumdevices.defender.security-recommendations

    Review active Defender recommendations and documented exceptions for the visible device inventory. Recommendations are grouped into one control rather than counted as individual security checks.

  • Defender sensors are active and reportingMediumdevices.defender.sensor-health

    Review sensor health, onboarding state and seven-day reporting freshness for devices returned by the optional Defender connection. This does not establish coverage of every device in the organization.

  • Resolve high-severity alertsHighdevices.defender.unresolved-alerts

    Defender XDR surfaces alerts from MDE, MDO, MDI, and MDA in a unified queue. High-severity alerts in 'New' or 'InProgress' status for >7 days are a strong indicator of either an unstaffed security function or an in-progress incident that's stalled.

  • Protect apps on mobile devicesMediumneeds Intunedevices.intune.app-protection-policies

    Reviews iOS and Android app-protection assignments. Policy configuration does not establish protection for every app or device; other Intune workloads are outside this check.

  • Require BitLocker on WindowsHighneeds Intunedevices.intune.bitlocker-compliance

    Without BitLocker, a stolen or lost Windows device exposes all cached data — OneDrive sync content, cached Outlook PSTs, saved attachments, Teams cache — to anyone who removes the disk and reads it. Encryption is the foundational endpoint control.

  • Require compliant devicesHighneeds Intune / EntraID_P1devices.intune.ca-requires-compliant-device

    Compliance policies + enrolled devices only matter if a CA policy actually requires compliance before granting access. Without this grant, an attacker on a non-Intune device can sign in with valid credentials and access corp resources just as easily as a compliant managed device.

  • Set compliance policies per platformHighneeds Intunedevices.intune.compliance-policies-exist

    Without a compliance policy for a given OS, every device on that OS is in 'unknown' compliance state. CA policies that 'require compliant device' silently let those devices through (or block them all, depending on the rule design) because there's no compliance evaluation.

  • Fix noncompliant devicesHighneeds Intunedevices.intune.noncompliant-devices

    Devices in 'noncompliant', 'conflict', or 'error' state have failed their compliance policy. With a CA policy requiring compliant devices, they're blocked from corp resources. Without one, they're still accessing data despite failing the controls you've defined.

  • Remove stale devicesMediumneeds Intunedevices.intune.stale-devices

    Devices that haven't synced for 30+ days are likely lost, decommissioned, or belong to former employees. They distort your compliance metrics, occupy licenses, and represent potential offline-data exposure if lost or stolen.

Azure (50)
  • Alert on critical operationsMediumazure-activity-log-alerts

    Activity Log alerts notify on high-risk operations (role assignment changes, NSG edits, security-solution deletions) in near-realtime. Catching these as they happen beats finding them in a quarterly review.

  • Forward the Activity LogHighazure-activity-log-to-la

    Without an Activity Log → Log Analytics diagnostic setting, control-plane events (role changes, NSG edits, resource deletes) only retain 90 days natively. Most security investigations need year-plus retention.

  • Enable WAF on Application GatewayHighazure-app-gateway-waf

    WAF disabled, or in Detection mode, doesn't block attacks. Production App Gateways should run WAF in Prevention mode (blocks + logs).

  • Review App Service authenticationMediumazure-app-service-auth-disabled

    Reads App Service platform authentication settings. Apps may intentionally use their own authentication or serve public content; this check does not prove anonymous access or internet reachability.

  • Require HTTPS on App ServicesHighazure-app-service-https-only

    App Services should have httpsOnly=true so HTTP traffic is auto-redirected. Avoids credentials and cookies traveling in cleartext during the initial request.

  • Require TLS 1.2 on App ServicesHighazure-app-service-tls-min

    Reads the App Service web configuration and checks that the application endpoint requires TLS 1.2 or later. Deployment slots and the separate SCM endpoint are outside this check's scope.

  • Back up virtual machinesHighazure-backup-coverage

    Every virtual machine should be protected by Azure Backup with a healthy, recent recovery point. Unbacked-up VMs are unrecoverable after ransomware, accidental deletion, or a failed change — the restore simply does not exist.

  • Protect backup vaults from deletionHighazure-backup-vault-hardening

    Recovery Services and Backup vaults should have soft delete enabled so that backup data deleted by a compromised or mistaken administrator is retained and recoverable rather than destroyed immediately.

  • Enable DDoS ProtectionMediumazure-ddos-protection-standard

    DDoS Protection Standard mitigates volumetric attacks against public IPs. Only VNets containing public-IP attached workloads are evaluated — pure internal VNets don't need it.

  • Enable Defender for Cloud plansInfoazure-defender-plan-enablement

    Defender for Cloud's per-workload plans (Servers, Storage, SQL, etc.) provide threat-detection signal on each workload type. Subscriptions on the Free tier only get configuration recommendations — no runtime threat protection.

  • Top Defender recommendationsInfoazure-defender-recommendations-summary

    Per-subscription roll-up of the top 5 unhealthy high-severity Defender for Cloud recommendations. Informational — drives the 'what Defender thinks' dashboard panel. Never fails on its own.

  • Configure diagnostic settingsMediumazure-diagnostic-settings-coverage

    Per-resource diagnostic settings forward data-plane logs (storage requests, KV accesses, SQL audits, NSG flow logs) to Log Analytics. Coverage <80% across critical resource types indicates substantial blind spots for forensic investigation.

  • Attach a WAF to Front DoorHighazure-front-door-waf

    Front Door WAF is opt-in per frontend. Frontends without an attached WAF policy are unprotected against OWASP attacks and bot traffic.

  • Narrow overbroad custom rolesHighazure-iam-custom-roles-overbroad

    Custom roles whose actions include `*`, `*/*`, or `Microsoft.Authorization/*` grant near-Owner privileges and bypass least-privilege. Microsoft.Authorization/* in particular is a privilege-escalation primitive (holder can grant themselves Owner).

  • Review guest role assignmentsMediumazure-iam-guest-rbac-assignments

    Reviews direct role assignments using explicit directory evidence. Unknown identities remain unverified; effective access and group membership require separate review.

  • Use managed identitiesMediumazure-iam-managed-identity-coverage

    Managed identities eliminate stored credentials for service-to-service auth. Coverage <50% suggests significant credential-rotation debt; <80% is a hygiene target worth working toward.

  • Review deleted-principal role assignmentsLowazure-iam-orphaned-role-assignments

    Reviews direct role assignments using explicit directory evidence. Unknown identities remain unverified; effective access and group membership require separate review.

  • Use PIM for privileged rolesMediumneeds EntraID_P2azure-iam-pim-enabled

    PIM lets users hold privileged Azure roles as eligible rather than active, requesting just-in-time activation. Substantially reduces standing-access blast radius. Requires Entra ID P2.

  • Limit service principal scopeHighazure-iam-sp-broad-scope

    Service principals holding Owner or Contributor at subscription level have authority across every resource in the subscription. Scope them down to the specific resource groups they need.

  • Rotate service principal credentialsMediumazure-iam-sp-stale-credentials

    Reviews credential dates for directly assigned Azure service principals and their locally owned app registrations. Flags active credentials older than 365 days or configured for more than 365 days. Group-derived access and publisher-owned registrations are not fully assessed.

  • Limit subscription OwnersHighazure-iam-subscription-owners

    Microsoft recommends ≤2 Owners per subscription. Each Owner is a tenant-wide compromise risk; reducing the count reduces the blast radius of a phished credential.

  • Restrict Key Vault network accessHighazure-kv-public-network

    Key Vaults with publicNetworkAccess=Enabled expose the management endpoint to the internet. Disable and configure private endpoints for the applications that need vault access.

  • Use RBAC for Key VaultsMediumazure-kv-rbac-mode

    RBAC authorization integrates Key Vault with PIM, conditional access, and central RBAC auditing. Legacy Access Policies are vault-local and can't be governed centrally.

  • Enable Key Vault purge protectionHighazure-kv-soft-delete

    Soft delete retains deleted vaults/keys for 90 days; purge protection blocks force-delete during that window. Together they protect against scenarios where attackers delete keys to lock out the owner.

  • Retain logs for 90+ daysMediumazure-log-retention

    Workspace retention <90 days truncates data before most breach investigation windows. CIS recommends ≥90 days; PCI-DSS and HIPAA require at least 1 year of accessible logs.

  • Assign the security benchmarkMediumazure-mcsb-assigned

    MCSB is Microsoft's canonical Azure security baseline. Assigning it at the subscription or management-group root gives continuous compliance scoring in Defender for Cloud.

  • Enforce SSL on MySQLHighazure-mysql-ssl-enforce

    MySQL Single Server: sslEnforcement should be Enabled. Flexible Server: require_secure_transport server parameter should be ON. Without these, clients can connect in plaintext.

  • Block database ports from the internetHighazure-nsg-db-ports-internet

    Database ports (1433, 3306, 5432, 27017, 6379) open to *, Internet, or 0.0.0.0/0 expose databases to credential-stuffing, unauthenticated access (Redis default), and data exfiltration.

  • Remove allow-any firewall rulesMediumazure-nsg-overly-permissive

    Any-protocol, any-source, any-port Allow rules defeat the principle of least connectivity and provide lateral-movement paths even when not directly internet-exposed.

  • Block RDP from the internetCriticalazure-nsg-rdp-internet

    TCP/3389 open to *, Internet, or 0.0.0.0/0 exposes Windows RDP to the internet. Public RDP is a primary initial-access vector for ransomware.

  • Block SSH from the internetCriticalazure-nsg-ssh-internet

    TCP/22 open to *, Internet, or 0.0.0.0/0 lets the world brute-force SSH. Use Bastion / VPN / IP allowlists instead.

  • Delete unattached managed disksLowazure-orphaned-disks

    Managed disks in the Unattached state are billed at full provisioned capacity while serving no workload, and still contain a complete readable copy of whatever the deleted VM held.

  • Clean up orphaned network resourcesLowazure-orphaned-network-resources

    Network interfaces attached to no VM, public IPs attached to no resource, and network security groups attached to no subnet or NIC. Billed or reserved for nothing, and — in the NSG case — usually a rule set someone believes is in force.

  • Enforce SSL on PostgreSQLHighazure-postgres-ssl-enforce

    Postgres Single Server: sslEnforcement should be Enabled. Flexible Server: require_secure_transport server parameter should be ON. Without these, clients can connect in plaintext.

  • Public IP inventoryInfoazure-public-ip-inventory

    Catalogs every public IP in scope and what resource it's attached to. Never fails — purely informational. These IPs are also fed into the external attack surface (Shodan/crt.sh) as seed inputs.

  • Set an Entra admin for SQLHighazure-sql-aad-admin

    SQL Servers without an AAD admin force clients onto local SQL auth, which doesn't support MFA / conditional access / centralized governance.

  • Narrow SQL firewall rulesCriticalazure-sql-firewall-broad

    Firewall rules permitting 0.0.0.0 → 255.255.255.255 (all IPv4) or 0.0.0.0 → 0.0.0.0 (all Azure services) expose the SQL Server to anything on the internet or the entire Azure fleet.

  • Encrypt SQL databasesMediumazure-sql-tde

    TDE encrypts data at rest with negligible perf impact. On by default for new databases; older ones may still have it off.

  • Enable SQL threat protectionMediumneeds DefenderForCloud_SQLazure-sql-threat-protection

    Defender for SQL detects SQL injection attempts, brute force, and anomalous access patterns. Requires Defender for Cloud's SQL plan.

  • Block anonymous container accessCriticalazure-storage-anonymous-containers

    A container with publicAccess set to Blob or Container permits anonymous access at the container level. Effective access also depends on account-level anonymous-access permission and network restrictions; this setting alone does not prove internet readability.

  • Enable blob soft deleteMediumazure-storage-blob-soft-delete

    Blob soft delete protects against accidental and malicious deletion. Microsoft recommends ≥7-day retention; longer is better for ransomware recovery.

  • Restrict storage network accessHighazure-storage-firewall-public

    networkAcls.defaultAction = Allow means the storage firewall is open to any network. Set Deny with explicit allowlists or private endpoints.

  • Require TLS 1.2 on storageHighazure-storage-min-tls-version

    minimumTlsVersion below TLS 1.2 lets clients negotiate weaker cipher suites and breaks PCI-DSS / FedRAMP / most enterprise compliance baselines.

  • Use private endpoints for storageInfoazure-storage-private-endpoint-coverage

    Private endpoints let storage accounts be reached only over the VNet, eliminating public network exposure. Coverage <50% indicates substantial public-surface storage; ≥80% is a hygiene target worth pursuing.

  • Disable public blob accessCriticalazure-storage-public-blob-account

    When allowBlobPublicAccess is true, individual containers can opt into anonymous internet access. Disabling at the account level enforces the secure default across every container.

  • Require HTTPS on storageHighazure-storage-secure-transfer

    Storage accounts with supportsHttpsTrafficOnly=false accept plaintext HTTP requests. Forces all REST API calls to use TLS when enabled.

  • Encrypt VM disksHighazure-vm-disk-encryption

    VM disks should be encrypted via encryptionAtHost (preferred) or Azure Disk Encryption (legacy). Default platform encryption protects only the underlying storage; per-VM controls protect against escape scenarios.

  • Onboard VMs to DefenderMediumneeds DefenderForCloud_Serversazure-vm-mde-coverage

    Defender for Endpoint provides EDR on the guest OS. Coverage below 80% indicates onboarding debt; below 50% means significant attack surface is unmonitored. With a Defender for Servers plan, Defender for Cloud installs the sensor on supported machines by default.

  • Remove public IPs from VMsMediumazure-vm-public-ip

    VMs with a directly attached public IP expose the host to the internet. Prefer Azure Bastion (for admin access) or App Gateway / LB with WAF (for app traffic) rather than direct public IP exposure.

  • Retire unsupported OS versionsHighazure-vm-stale-os

    VMs on EOL operating systems receive no vendor security patches. Migrate to a supported image or apply Microsoft Extended Security Updates (paid).

Logging & Alerting (4)
  • Set security alert recipientsHighlogging.alert-recipients-configured

    Logs are useful only if someone reads them. Microsoft Defender ships high-value alerts (new forwarding rule, admin role elevation, suspicious forwarding activity) that go to nobody by default unless an admin sets email recipients. Untriaged alerts are equivalent to no detection.

  • Enable mailbox auditingHighlogging.mailbox-audit-default

    Mailbox auditing is the foundation for ALL post-incident investigation of an account compromise. Without it, you cannot tell what an attacker did inside a mailbox — when they signed in, what mail they read, what rules they created, what they deleted. Critical actions like UpdateInboxRules must be in the default owner audit set.

  • Use a monitored notification mailboxMediumlogging.service-health-notifications

    Microsoft sends service-health incidents, security advisories, and license/billing notifications to addresses on file in the tenant. If these default to the original signup contact (often a personal email of a long-departed admin), important messages — including Microsoft's own breach notifications to your tenant — get lost.

  • Enable the unified audit logHighlogging.unified-audit-log

    The unified audit log records sign-ins, file accesses, admin actions, policy changes — everything you'd need to investigate an incident. Whether it's ingesting is an Exchange/Purview setting our read-only Graph access cannot read, so we surface it for one-command verification rather than guessing from unrelated Entra logs.

External Attack Surface (20)
  • External attack-surface inventoryInfoexternal.attack-surface-summary

    Roll-up of every domain, IP, and exposed service Tenant Strike discovered from the outside-in view. Verify each entry corresponds to a known business system — anything unrecognized is a shadow-IT or decommissioned-but-still-on asset that warrants investigation.

  • Patch internet-facing servicesCriticalexternal.cve-vulnerabilities

    Shodan, a public index of internet-facing systems, lists the published vulnerabilities (CVEs) that match the software it saw on each address. Unless Shodan marks a match verified, it is inferred from that software and its version and has not been tested against the service. The same index is open to anyone, so an attacker can read the same list.

  • Enable DNSSEC and CAALowexternal.dns-integrity

    DNSSEC signs your DNS records so resolvers can detect tampering; CAA records restrict which certificate authorities may issue certificates for your domain. Both limit attacks that impersonate your domain.

  • Keep domain registration healthyMediumexternal.domain-registration

    An expired domain takes email and your website offline at the same time, and lets someone else register it and receive your mail. A registrar transfer lock is a free setting that blocks one leg of a domain hijack.

  • Lock down exposed admin panelsHighexternal.exposed-admin-panels

    Web admin interfaces (phpMyAdmin, cPanel, Jenkins, Kibana, vCenter, etc.) should be accessible only from a trusted network or behind an identity-aware proxy. Public exposure invites credential stuffing and exploitation of the steady stream of CVEs these products ship.

  • Close exposed database portsCriticalexternal.exposed-databases

    Databases should always be private — behind a VPC/VNET, accessible only from the application tier. Public exposure represents either a misconfigured cloud instance or a legacy server that was never moved behind a firewall. Many database engines (Mongo, ES, Redis) ship with no authentication by default.

  • Close exposed management portsCriticalexternal.exposed-management-ports

    Remote-management protocols (RDP, SMB, WinRM, VNC), hosting control panels (cPanel, WHM, Control Web Panel, Webmin) and cleartext file transfer (FTP) should be reachable only through a VPN or zero-trust gateway. Direct internet exposure of these is the leading initial-access vector for ransomware and remote-access breaches.

  • Watch for lookalike domainsMediumexternal.lookalike-domains

    Attackers register domains that resemble yours (character swaps, extra words, alternate TLDs) to send phishing and business-email-compromise mail that looks like it's from you. A lookalike with an MX record is infrastructure ready to send.

  • Keep the website's PHP on a release with the latest security fixesCriticalexternal.php-security-fix

    In October 2026 the PHP project fixed two critical flaws that let anyone run code on a web server without signing in. This reads the PHP version a public website announces and says whether it predates the fix, or that the site runs PHP without showing which version.

  • Stay off threat blocklistsCriticalexternal.reputation

    abuse.ch publishes blocklists of hostnames serving malware (URLhaus) and botnet command-and-control IPs (Feodo Tracker). If one of your own assets is listed, it has been compromised and is being used against others — and it will also get your mail and traffic blocked.

  • Send recommended security headersLowexternal.security-headers

    Security response headers (HSTS, X-Frame-Options / CSP, X-Content-Type-Options) harden your public web login pages against SSL-stripping, clickjacking, and MIME-confusion attacks.

  • Publish a security contact (security.txt)Lowexternal.security-txt

    A small text file at /.well-known/security.txt tells anyone who finds a security problem in your systems exactly how to reach you. Without one, reports go to a general inbox and often get missed.

  • Resolve flagged hostsHighexternal.shodan-flagged-host

    Shodan labels indexed hosts with tags such as compromised, malware, database, or ics. A flag on one of your own hosts is an independent signal that it's breached or exposing something it shouldn't.

  • Remove dangling DNS recordsCriticalexternal.subdomain-takeover

    A subdomain whose CNAME points at a deleted cloud resource (S3 bucket, Azure web app, GitHub Pages site, etc.) can be re-registered by anyone, who then serves content — with valid TLS — on your own domain. Prime phishing and cookie-theft infrastructure.

  • Keep TLS certificates healthyHighexternal.tls-certificate-issues

    TLS certificates that are expired, near-expiry, self-signed, or signed with weak algorithms cause user-facing errors or outages and erode trust.

  • Retire outdated TLS versionsMediumexternal.tls-protocol

    Deprecated TLS/SSL protocol versions (SSLv2, SSLv3, TLS 1.0, TLS 1.1) are vulnerable to downgrade and cipher attacks, fail PCI-DSS, and are rejected by up-to-date browsers and API clients.

  • Keep internet-facing servers on a supported versionHighexternal.unsupported-software

    A version of Windows or Exchange Server that Microsoft has stopped supporting gets no fix for flaws found after that date. On a machine reachable from the internet, each new flaw stays open for good.

  • Send the website's home page with browser protections switched onLowexternal.website-headers

    A website can tell a visitor's browser to always use an encrypted connection, to refuse being shown inside another site's frame, and not to guess a file's type. A home page sent without them leaves the browser on its looser defaults.

  • Keep the website's platform and plugins up to dateMediumexternal.website-parts

    A website built on WordPress shows visitors which version it runs and which plugins it uses. WordPress.org says which versions later releases have replaced and which plugins it has closed, and a site that shows one of those is worth a look.

  • Keep the public website on software its maker still supportsMediumexternal.website-software

    A website can announce the software it runs on to every visitor. When that is a version its maker has stopped fixing, flaws found afterwards stay open unless the hosting company patches it itself. PHP, the Apache web server and Microsoft's IIS are the software judged today.

For your security team — technical evidence

Reproduce it yourself

Tenant Strike's GraphReadOnlyClient (src/auth/graph.ts) exposes only GET. This manifest is regenerated on every build by scripts/build-graph-endpoints.ts, which fails the build if any write verb (post/patch/put/delete) is detected on a receiver typed as GraphReadOnlyClient. The list below is the complete set of Microsoft Graph endpoints Tenant Strike calls, with source-file references for line-level verification.

TypeScript AST walker (src/auth/graph-endpoint-extractor.ts) — resolves the receiver's type to GraphReadOnlyClient regardless of variable name. Catches aliases and `as any` casts that the prior regex-based extractor could have missed.
Endpoints
139
Unique paths
72
Source files
59
Write verbs
0

Endpoint manifest · auto-extracted

src/ai/consent-probe.ts (1)
  • GET · v1.0/usersL161
src/ai/graph-page.ts (2)
  • GET · v1.0<dynamic>L48
  • GET · v1.0<dynamic>L49
src/ai/tools/live-config-tools.ts (7)
  • GET · v1.0/groupsL44
  • GET · v1.0/groups/${String(read.rows[0].id)}/membersL59
  • GET · v1.0/admin/sharepoint/settingsL95
  • GET · v1.0/deviceManagement/managedDevicesL124
  • GET · v1.0/security/secureScoresL167
  • GET · v1.0/admin/serviceAnnouncement/healthOverviewsL215
  • GET · v1.0/auditLogs/directoryAuditsL261
src/ai/tools/live-tools.ts (8)
  • GET · v1.0/reports/authenticationMethods/userRegistrationDetailsL60
  • GET · v1.0/users/${encodeURIComponent(upn)}L115
  • GET · v1.0/auditLogs/signInsL153
  • GET · v1.0/identity/conditionalAccess/policiesL206
  • GET · v1.0/servicePrincipalsL279
  • GET · v1.0/servicePrincipals/${encodeURIComponent(spId)}/appRoleAssignmentsL314
  • GET · v1.0/roleManagement/directory/roleDefinitionsL375
  • GET · v1.0/roleManagement/directory/roleAssignmentsL382
src/app-risk/collect.ts (4)
  • GET · v1.0/servicePrincipalsL149
  • GET · v1.0/oauth2PermissionGrantsL164
  • GET · beta/beta/reports/servicePrincipalSignInActivitiesL177
  • GET · v1.0/applicationsL197
src/assessment/assessment.smoke.ts (3)
  • GET · v1.0/usersL120
  • GET · v1.0/users/uL134
  • GET · v1.0/usersL134
src/assessment/source.ts (3)
  • GET · v1.0<dynamic>L68
  • GET · v1.0<dynamic>L69
  • GET · v1.0<dynamic>L70
src/auth/graph-cache.ts (3)
  • GET · v1.0<dynamic>L21
  • GET · v1.0<dynamic>L26
  • GET · v1.0<dynamic>L31
src/auth/verify-admin-role.ts (1)
  • GET · v1.0/users/${input.objectId}/transitiveMemberOf/microsoft.graph.directoryRoleL65
src/auth/verify-domain.ts (2)
  • GET · v1.0/domainsL80
  • GET · v1.0/domainsL180
src/azure/principal-credentials.ts (2)
  • GET · v1.0/servicePrincipals/${id}L78
  • GET · v1.0/applications(appId='${sp.appId}')L103
src/azure/principals.ts (3)
  • GET · v1.0/directoryObjects/${id}L27
  • GET · v1.0/directory/deletedItems/${id}L31
  • GET · v1.0/users/${id}L45
src/azure/visibility.ts (1)
  • GET · v1.0/servicePrincipalsL16
src/branding/tenant-logo.ts (4)
  • GET · v1.0/organizationL52
  • GET · v1.0/organization/${orgId}/branding/localizations/default/squareLogoL61
  • GET · v1.0/organization/${orgId}/branding/localizations/default/bannerLogoL62
  • GET · v1.0/organization/${orgId}/branding/localizations/default/squareLogoDarkL64
src/catalog/licenses.ts (1)
  • GET · v1.0/subscribedSkusL74
src/checks/apps/admin-consent-workflow.ts (1)
  • GET · v1.0/policies/adminConsentRequestPolicyL28
src/checks/apps/expiring-app-secrets.ts (1)
  • GET · v1.0/applicationsL37
src/checks/apps/permission-evidence.ts (2)
  • GET · v1.0/servicePrincipals/${id}L26
  • GET · v1.0/servicePrincipals/${spId}/appRoleAssignmentsL54
src/checks/apps/privileged-app-owners.ts (7)
  • GET · v1.0/directoryRolesL44
  • GET · v1.0/directoryRoles/${role.id}/membersL46
  • GET · v1.0/roleManagement/directory/roleEligibilityScheduleInstancesL53
  • GET · v1.0/servicePrincipalsL89
  • GET · v1.0/applicationsL123
  • GET · v1.0/servicePrincipals/${sp.id}/ownersL134
  • GET · v1.0/applications/${reg}/ownersL135
src/checks/apps/redirect-uri-hygiene.ts (1)
  • GET · v1.0/applicationsL240
src/checks/apps/risky-app-permissions.ts (1)
  • GET · v1.0/servicePrincipalsL13
src/checks/apps/unused-app-registrations.ts (5)
  • GET · v1.0/servicePrincipals(appId='00000003-0000-0000-c000-000000000000')L133
  • GET · v1.0/servicePrincipalsL244
  • GET · beta/beta/reports/servicePrincipalSignInActivitiesL260
  • GET · v1.0/applicationsL335
  • GET · v1.0/servicePrincipals/${sp.id}/appRoleAssignmentsL364
src/checks/apps/user-consent-policy.ts (1)
  • GET · v1.0/policies/authorizationPolicyL57
src/checks/devices/defender-onboarding-coverage.ts (1)
  • GET · v1.0/deviceManagement/managedDevices/${d.id}/windowsProtectionStateL105
src/checks/devices/defender-unresolved-alerts.ts (1)
  • GET · v1.0/security/alerts_v2L55
src/checks/devices/intune-shared.ts (4)
  • GET · v1.0/deviceManagement/managedDevicesL79
  • GET · v1.0/deviceManagement/deviceCompliancePoliciesL89
  • GET · v1.0/deviceAppManagement/iosManagedAppProtectionsL105
  • GET · v1.0/deviceAppManagement/androidManagedAppProtectionsL115
src/checks/email/inbox-forwarding-rules.ts (2)
  • GET · v1.0/usersL130
  • GET · v1.0/users/${u.id}/mailFolders/inbox/messageRulesL160
src/checks/identity/authentication-methods.ts (1)
  • GET · v1.0/policies/authenticationMethodsPolicyL50
src/checks/identity/break-glass-accounts.ts (5)
  • GET · v1.0/directoryRolesL267
  • GET · v1.0/directoryRoles/${gaRole.id}/membersL294
  • GET · v1.0/users/${m.id}L333
  • GET · v1.0/policies/conditionalAccessPoliciesL374
  • GET · v1.0/groups/${g}/transitiveMembersL429
src/checks/identity/ca-admin-phishing-resistant.ts (1)
  • GET · v1.0/policies/authenticationStrengthPoliciesL31
src/checks/identity/ca-device-code-flow.ts (1)
  • GET · v1.0/organizationL70
src/checks/identity/ca-exclusion-sprawl.ts (3)
  • GET · v1.0/directoryRolesL401
  • GET · v1.0/users/${id}L418
  • GET · v1.0/groups/${id}L430
src/checks/identity/ca-policies-shared.ts (2)
  • GET · v1.0/policies/identitySecurityDefaultsEnforcementPolicyL95
  • GET · v1.0/policies/conditionalAccessPoliciesL133
src/checks/identity/ca-trusted-locations.ts (1)
  • GET · v1.0/identity/conditionalAccess/namedLocationsL66
src/checks/identity/default-user-permissions.ts (1)
  • GET · v1.0/policies/authorizationPolicyL74
src/checks/identity/device-registration-policy.ts (1)
  • GET · v1.0/policies/deviceRegistrationPolicyL84
src/checks/identity/guest-invite-policy.ts (1)
  • GET · v1.0/policies/authorizationPolicyL35
src/checks/identity/leaked-credentials.ts (1)
  • GET · v1.0/identityProtection/riskDetectionsL98
src/checks/identity/legacy-auth-signins.ts (1)
  • GET · v1.0/auditLogs/signInsL76
src/checks/identity/password-expiry-policy.ts (1)
  • GET · v1.0/domainsL60
src/checks/identity/privileged-roles-shared.ts (7)
  • GET · v1.0/groups/${groupId}/membersL72
  • GET · v1.0/usersL133
  • GET · v1.0/directoryRolesL157
  • GET · v1.0/directoryRoles/${role.id}/membersL182
  • GET · v1.0/users/${m.id}L201
  • GET · v1.0/roleManagement/directory/roleEligibilityScheduleInstancesL228
  • GET · v1.0/users/${principalId}L255
src/checks/identity/recent-privileged-changes.ts (1)
  • GET · v1.0/auditLogs/directoryAuditsL207
src/checks/identity/risky-users.ts (3)
  • GET · v1.0/identityProtection/riskyUsersL61
  • GET · v1.0/identityProtection/riskyUsersL76
  • GET · v1.0/users/${encodeURIComponent(u.id)}L325
src/checks/identity/security-defaults-status.ts (1)
  • GET · v1.0/policies/identitySecurityDefaultsEnforcementPolicyL16
src/checks/identity/stale-guest-users.ts (1)
  • GET · v1.0/usersL29
src/checks/identity/too-many-global-admins.ts (2)
  • GET · v1.0/directoryRolesL38
  • GET · v1.0/directoryRoles/${gaRole.id}/membersL66
src/checks/identity/users-without-mfa.ts (1)
  • GET · v1.0/reports/authenticationMethods/userRegistrationDetailsL23
src/checks/logging/service-health-notifications.ts (1)
  • GET · v1.0/organizationL50
src/checks/logging/unified-audit-log.ts (2)
  • GET · v1.0/auditLogs/directoryAuditsL53
  • GET · v1.0/auditLogs/signInsL61
src/checks/sharing/cross-tenant-shared.ts (2)
  • GET · v1.0/policies/crossTenantAccessPolicy/defaultL52
  • GET · v1.0/policies/crossTenantAccessPolicy/partnersL61
src/checks/sharing/sharepoint-settings-shared.ts (1)
  • GET · v1.0/admin/sharepoint/settingsL109
src/drift/resource-verification.smoke.ts (1)
  • GET · v1.0/test-deniedL138
src/exec/collect.ts (3)
  • GET · v1.0/usersL37
  • GET · v1.0/usersL41
  • GET · v1.0/subscribedSkusL64
src/exec/service-health.ts (2)
  • GET · v1.0/admin/serviceAnnouncement/issuesL46
  • GET · v1.0/admin/serviceAnnouncement/messagesL50
src/identity-risk/collect.ts (9)
  • GET · v1.0/oauth2PermissionGrantsL136
  • GET · v1.0/directoryRolesL211
  • GET · v1.0/directoryRoles/${role.id}/membersL222
  • GET · v1.0/roleManagement/directory/roleEligibilityScheduleInstancesL237
  • GET · v1.0/reports/authenticationMethods/userRegistrationDetailsL261
  • GET · v1.0/groups/${gid}/transitiveMembersL288
  • GET · v1.0/identityProtection/riskDetectionsL320
  • GET · v1.0/directoryRolesL389
  • GET · v1.0/directoryRoles/${role.id}/membersL401
src/offboarding/collect.ts (5)
  • GET · v1.0/usersL86
  • GET · v1.0/usersL90
  • GET · v1.0/subscribedSkusL104
  • GET · v1.0/domainsL129
  • GET · v1.0/users/${u.id}/mailFolders/inbox/messageRulesL150
src/scan.ts (1)
  • GET · v1.0/subscribedSkusL728
src/secure-score/fetch.ts (2)
  • GET · v1.0/security/secureScoresL31
  • GET · v1.0/security/secureScoreControlProfilesL67
src/vulnerability-watch/inventory.ts (2)
  • GET · v1.0/deviceManagement/detectedAppsL46
  • GET · v1.0/deviceManagement/managedDevicesL49

Azure Resource Manager · machine-verified read-only

Every ARM endpoint we call — for Azure scanning.

The same automated build check covers our Azure code: every call we make to Azure is a read. We never change, create, or delete anything in your subscriptions.

Endpoints
13
Unique paths
11
Source files
82
Write verbs
0
Show all 13 ARM endpoints
  • GET${app.id}/config/web
  • GET${app.id}/config/authsettingsV2
  • GET<dynamic>
  • POST/providers/Microsoft.ResourceGraph/resources
  • GET/subscriptions/${subId}/providers/Microsoft.Security/pricings
  • GET<dynamic>
  • GET/subscriptions/${subId}/providers/Microsoft.Authorization/roleAssignments
  • GET/subscriptions/${subId}/providers/Microsoft.Insights/diagnosticSettings
  • GET/subscriptions/${subId}/providers/Microsoft.Security/autoProvisioningSettings
  • GET<dynamic>
  • GET/subscriptions
  • GET/subscriptions/${sub.id}/providers/Microsoft.Authorization/roleAssignments?$filter=atScope()
  • GET/subscriptions/${sub.id}/providers/Microsoft.Authorization/denyAssignments

The one POST in the list is Azure's Resource Graph query endpoint — Azure requires POST there only because the (read-only) query is too long to fit in a URL. Nothing is changed by it, and our build check treats it as the single documented exception.

Comfortable with how we work?

See what we'd find in your tenant.

No write scopes, no agents, and a setup that takes a few minutes. See what your tenant looks like to an attacker.