Active Directory & Identity

What Injects Script Into Your Entra Sign-In Page? Microsoft Starts Blocking It on October 19

Dark cyberpunk illustration of a single lit doorway in a vast night-time hall, with stray orange threads of light reaching toward the frame and stopping short against a faint cyan barrier.

What else runs inside your users' browsers when they land on login.microsoftonline.com? Most organizations cannot answer that, and in about three weeks the answer stops being academic. Microsoft is enforcing a Content Security Policy on the Entra ID sign-in page, so any script that arrives from outside Microsoft's own allowlist will be blocked from executing. The message center post MC1481309, published September 28, puts the rollout in mid-to-late October 2026 and gives administrators an action date of October 19.

Sign-in keeps working. That is the part to internalize early: no user gets locked out, no tenant setting changes, and nothing in the Entra admin center flips. What stops working is whatever third-party code had been riding along inside that page, and it stops quietly, in whichever browser profile happened to be carrying it.

The sentence that makes this look like a non-event

Microsoft's guidance is reassuring, and most of the coverage has repeated it as the whole story. From the Microsoft Learn rollout page: "Microsoft recommends not using browser extensions or tools that inject code into the Microsoft Entra sign-in experience. If you follow this advice, your experience will remain unchanged, and no further action is needed." Read quickly, that sorts the world into two groups and puts almost everyone in the safe one. No IT director describes their company as a shop that injects script into Microsoft's login page.

A few paragraphs later, the same document reports what Microsoft actually measures: "Our analysis shows most violations come from external browser extensions or injected scripts linked to third-party tools." Those two statements only agree if you read "your organization uses" as "your organization deployed." A Content Security Policy does not care who installed the extension. It applies to the browser session in front of the user, which includes the password manager a sales rep added last spring, the accessibility overlay someone needed for one project, and the screen-sharing extension a vendor talked a user through installing during a support call.

So the useful question is whether anyone on your payroll has installed something that reaches into that page. Answering it takes an inventory, and most organizations do not have one.

The relevance verdict: you are in scope if your people authenticate to Microsoft through a browser at login.microsoftonline.com, which covers effectively every Microsoft 365 and Entra ID tenant with human users. Microsoft names three exclusions. MSAL-based and API authentication flows that talk to the Entra security token service directly are unaffected, because enforcement is scoped to the browser sign-in URL. Entra External ID tenants signing in on a custom or CIAM domain are unaffected. Anything that is not a browser sign-in is unaffected. If your estate is native desktop clients and service principals end to end, you can stop here. For everyone else the work is small, and it has a date attached.

Read the header before it starts enforcing

Microsoft is already shipping the policy in report-only mode, which means the exact rules are readable today instead of arriving as a surprise. Request the authorize endpoint and look at the response headers:

curl -sS -D - -o /dev/null \
  -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/141.0" \
  "https://login.microsoftonline.com/common/oauth2/v2.0/authorize\
?client_id=04b07795-8ddb-461a-bbee-02f9e1bf7b46&response_type=code\
&redirect_uri=https%3A%2F%2Flogin.microsoftonline.com%2Fcommon%2Foauth2%2Fnativeclient\
&scope=openid" \
  | grep -i '^content-security-policy'

On October 1, 2026 that returns a Content-Security-Policy-Report-Only header rather than an enforcing one, carrying this policy:

object-src 'none'; base-uri 'self';
script-src 'self' 'nonce-<per-response-random>' 'unsafe-inline' 'unsafe-eval'
  https://*.msauth.net https://*.msftauth.net
  https://*.msftauthimages.net https://*.msauthimages.net
  https://*.msidentity.com https://*.microsoftonline-p.com
  https://*.microsoftazuread-sso.com https://*.azureedge.net
  https://*.outlook.com https://*.office.com https://*.office365.com
  https://*.microsoft.com https://*.bing.com 'report-sample';
report-uri https://csp.microsoft.com/report/ESTS-UX-All

Three details in that header decide what happens to you.

The nonce is the mechanism. 'unsafe-inline' sits right there in the directive, which looks permissive until you recall how CSP Level 3 resolves the conflict: when a nonce source or a hash source is present, browsers ignore 'unsafe-inline'. Mozilla's script-src reference spells out the precedence, noting that a policy written as script-src 'unsafe-inline' https: 'nonce-abcdefg' 'strict-dynamic' "will act like https: 'nonce-abcdefg' in browsers that support CSP2." Every script Microsoft serves on that page carries the per-response nonce. An injected <script> element has no nonce, so it does not execute.

The allowlist is Microsoft properties only. There is no hook for a customer domain, no tenant-level override, and no field in the Entra admin center where you add your vendor's CDN. Microsoft's instruction to affected customers is to "work directly with their vendors to identify and implement fixes that comply with CSP requirements." In practice the vendor stops injecting, or the feature goes away.

The report-uri points at csp.microsoft.com, and this is where the official preparation guidance stops being a procedure. The report-only phase is working exactly as designed: every browser that hits a violation posts a JSON report naming the blocked script. Those reports go to Microsoft. There is no tenant-scoped view of them, no Graph endpoint, no Entra audit-log entry, and no export. Microsoft is collecting the data that would tell you which of your users are about to lose a tool, and your tenant has no way to ask for it.

The documented alternative is to sign in with the browser developer console open and read the violations printed in red. Every administrator should do that once, to learn the shape of the error. As a fleet procedure it fails for a reason the documentation itself concedes: "If a specific team or person caused the violation, it appears only in their flows." You would have to repeat the test inside every browser profile in the company, including the extension one engineer installed and nobody else has.

Which extensions break, and how to find them

Narrow the target first, because "all browser extensions" overstates the blast radius badly. Chrome and Edge run extension content scripts in an isolated world by default, a private execution environment with its own policy, separate from the page. Google's content script documentation states the rule in one line: "When a content script is injected into the main world, the CSP of the page applies." An isolated-world content script that reads the DOM, waits for a form, or restyles an element is untouched by Microsoft's header. Breakage lands on the narrower set of extensions that must execute in the page's own JavaScript context, either by declaring world: "MAIN" or by appending a script element into the page.

The four categories worth checking by name

  • Password managers whose autofill drives framework-managed input fields through page-context JavaScript rather than plain DOM writes.
  • Session, experience, and digital-employee-experience monitoring agents that hook page events to time the sign-in.
  • Accessibility, translation, and reader overlays that rewrite the page in place.
  • In-house or vendor single sign-on wrappers that prefill a tenant hint, inject a branding snippet, or auto-submit a form.

Both Chromium browsers keep every installed extension's manifest on disk under the user profile. The manifest declares host_permissions (or permissions under Manifest V2) and the content_scripts match patterns, which is enough to flag anything entitled to touch the sign-in page. Run this on a sample of workstations, or push it through your RMM and collect the CSV:

$roots = @(
  "$env:LOCALAPPDATA\Microsoft\Edge\User Data",
  "$env:LOCALAPPDATA\Google\Chrome\User Data"
)
$broad = @('<all_urls>','https://*/*','http://*/*','*://*/*')

$findings = foreach ($root in $roots | Where-Object { Test-Path $_ }) {
  Get-ChildItem "$root\*\Extensions\*\*\manifest.json" -ErrorAction SilentlyContinue |
  ForEach-Object {
    $m = Get-Content $_.FullName -Raw | ConvertFrom-Json
    $scopes = @($m.host_permissions) + @($m.permissions) +
              @($m.content_scripts.matches)
    $hit = $scopes | Where-Object {
      $_ -and ($broad -contains $_ -or $_ -like '*microsoftonline.com*')
    }
    if ($hit) {
      [pscustomobject]@{
        Computer  = $env:COMPUTERNAME
        Browser   = if ($root -like '*Edge*') { 'Edge' } else { 'Chrome' }
        Name      = $m.name
        Version   = $m.version
        MainWorld = [bool]($m.content_scripts | Where-Object { $_.world -eq 'MAIN' })
        Scopes    = (($hit | Select-Object -Unique) -join '; ')
        ExtId     = $_.Directory.Parent.Name
      }
    }
  }
}
$findings | Sort-Object MainWorld -Descending |
  Export-Csv "$env:TEMP\entra-csp-extension-audit.csv" -NoTypeInformation

Work the MainWorld rows first. Those extensions declare main-world injection in their own manifest and are the highest-confidence breakage candidates. Then take the rest by name: anything claiming <all_urls> earns a one-minute look at what it says it does on a login page. An extension nobody recognizes on a corporate device is a finding in its own right, whatever happens with this header.

Pair the list with policy. Edge and Chrome both support an install allowlist through group policy or Intune, where setting ExtensionInstallBlocklist to * and enumerating approved IDs in ExtensionInstallAllowlist turns a one-off audit into a standing control. If closing self-service extension installs has been sitting on your list, this deadline is a fair reason to finish it.

What the header does not fix

Microsoft frames this correctly as defense in depth, and the limits deserve saying out loud, because a reader who walks away believing the sign-in page is now hardened against credential theft has learned the wrong lesson.

An adversary-in-the-middle proxy is untouched. When a victim lands on an attacker-controlled clone of the Microsoft sign-in page, the attacker serves the headers, so there is no Microsoft policy in play at all. That class of attack - the kind behind the Okta vishing kits and the Entra passkey-enrollment campaigns of the last six months - is still answered by phishing-resistant authentication strength in Conditional Access, not by a CSP on the real domain.

A malicious extension also keeps most of its reach. CSP governs where executable script may come from. It does not revoke an isolated-world content script's access to the DOM, so an extension with permission on login.microsoftonline.com can still read what a user types into the password field and ship it elsewhere, with no main-world injection required. Post-authentication token and cookie theft happens outside the page entirely and is equally unaffected. What this header removes is one specific primitive: arbitrary script execution inside Microsoft's authentication origin, whether it came from a zero-day cross-site scripting bug or from an extension that wanted page context. That is a real narrowing of the attack surface, and it is also the whole of it.

Pull the extension list before the header starts enforcing

You have until roughly October 19 before report-only becomes enforcing, and the work in front of you is three steps long. Run the manifest sweep across a representative slice of the fleet and keep the CSV, because it is the first real inventory most teams will have of what executes inside their authentication flow. For each extension it flags, check the vendor's release notes for a CSP-compliant build, and brief the help desk on what the failure looks like, so the "autofill stopped working on the Microsoft login" ticket gets the right answer on first touch instead of fourth. Then set the browser extension allowlist and keep it. Microsoft's header is doing you a favor by naming the problem out loud: unreviewed third-party code has been running inside your sign-in page for years, and nobody kept a list. If you want a second set of eyes on your Entra authentication surface - the methods policy, Conditional Access, and now the browser layer in front of them - that is the assessment we run.

Need help hardening your identity infrastructure?

We assess Active Directory and Entra ID environments for the misconfigurations attackers actually exploit. Book a session to discuss your environment.