30-second answer

PowerShell
Get-PnPTenantSite -Identity https://contoso.sharepoint.com/sites/team |
  Select-Object Url, DenyAddAndCustomizePages

True establishes one thing precisely: nobody on this site can insert script into a page, and nobody can mark a file as executable. It does not establish that no interactive content can reach a reader on that site.

What this proves

That the AddAndCustomizePages permission is held by nobody on the site, which is the permission the entire classic scripting model turns on. Microsoft is explicit about why that matters: script in a SharePoint page, including an HTML page in a document library, runs in the context of the user visiting the page, has access to everything that user has access to, and can reach other Microsoft 365 services through Microsoft Graph. Once scripting is allowed, the documentation states you can no longer identify what code was inserted, where, or by whom.

Turning it off closes that door. It is a real control, and it is why Microsoft turns it off by default on modern sites.

What it does not prove

  • That the HTML file in the library is inert because of this setting. It is inert for a second reason. Under strict browser file handling, which is now the only model available, files that could cause harm are not executed but downloaded or shown as raw content.
  • That HTML is blocked. It is not, and the control's own reference page is where that is settled rather than in commentary about it. Under What features are affected when custom scripts are blocked?, the row for files that potentially include script lists exactly nine extensions that cannot be uploaded, copied, moved or opened in a library: .asmx, .ascx, .aspx, .htc, .jar, .master, .swf, .xap, .xsf. .html and .htm are not among them; .htc, an Internet Explorer behaviour file, is. The list was written for the classic surface it governs. Writing about Content Security Policy, Microsoft states the same thing from the other side: Added script will not execute, added HTML will still work. HTML and executable script stopped being one thing, and a control named for script does not speak for both.
  • That no approved code runs in the page. SPFx is the governed alternative Microsoft recommends and it is not a sandbox: the documentation says the framework runs in the context of the current user in the browser and its controls render in the normal page DOM. What SPFx changes is who authorises the code, not where it executes.

PowerShell

PowerShell
# The setting, per site.
Get-PnPTenantSite -Identity https://contoso.sharepoint.com/sites/team |
  Select-Object Url, DenyAddAndCustomizePages

# Every site where it is allowed, which is the list worth having.
Get-PnPTenantSite |
  Where-Object { -not $_.DenyAddAndCustomizePages } |
  Select-Object Url, Template, Owner

# The other four controls in the chain are read elsewhere:
#   Trusted script sources, in the SharePoint admin centre
Get-SPOContentSecurityPolicy
#   Whether CSP is being enforced yet in this tenant
(Get-SPOTenant).ContentSecurityPolicyEnforcement

Example output

Text
Url                                              DenyAddAndCustomizePages
---                                              ------------------------
https://contoso.sharepoint.com/sites/team                            True
https://contoso.sharepoint.com/sites/legacy                         False

Read the second line as this site still allows the classic model, and the first as this site does not, not as this site cannot render anything interactive.

Explanation

Five controls sit between an HTML file and a reader's browser, and each answers a different question.

ControlQuestion it answers
DenyAddAndCustomizePagesMay anyone here insert script into a page?
The nine blocked extensionsMay this kind of file be put in a library at all?
The execution mark on a fileWas this file put here by somebody holding AddAndCustomizePages?
Strict browser file handlingWhat does the browser do when the file is opened?
App Catalog approvalDid an administrator approve this component?
Content Security PolicyWhich origins may serve script to this page, and is inline script allowed?

The second row is where the classic model and the modern one part company. .aspx is on that list and .html is not, so the same setting that stops a classic page being uploaded does not, by that mechanism, stop an HTML file.

The second row is the mechanism the first one actually operates through, and it is the one usually left out. A file becomes executable only when somebody holding AddAndCustomizePages marks it so. Microsoft records both halves of the consequence: a rename performed by a site member produces a file that is not marked for execution and is therefore downloaded rather than executed, and any later change to such a file marks it non-executable again.

So on a noscript site nobody can mark anything executable, and on any site editing a file removes the mark it had. The setting and the file state are one mechanism seen from two ends.

Production considerations

CSP is enforced on non-classic pages from 1 March 2026, with a tenant option to delay it to 1 June 2026. It controls which origins may serve script, blocks inline script outright, and is administered through Trusted script sources in the SharePoint admin centre. Expressions that are too permissive, such as *, *.domain, 'unsafe-inline' and 'strict-dynamic', are refused, and the list is capped at 300 entries.

CSP is also the first control in this chain that leaves an audit trail: violations are logged to Microsoft Purview as ViolatedContentSecurityPolicy with DocumentUrl and BlockedUrl. Against a model whose own documentation says you cannot identify what code was inserted or by whom, that is a real change.

Its limits are documented too. CSP is not enforced for SPFx components on classic pages, eval() remains available because 'unsafe-eval' is part of the standard header, and it does not apply to SharePoint Add-Ins, which stop working on 2 April 2026.

The classic door is being closed on a schedule, and it is worth the dates. From 15 September 2025 custom scripting is disabled by default on the classic publishing templates, and neither new classic publishing site collections nor the publishing feature can be created or activated, through the interface or the API. The tenant-level reprieve, Set-SPOTenant -DelayDenyAddAndCustomizePagesEnforcementOnClassicPublishingSites, ends on 15 March 2026. At site level the setting is held shut by a timer rather than a switch: any change allowing custom script is overridden to Not allowed within 24 hours. And Baseline security mode in the Microsoft 365 admin centre now offers Don't allow new custom scripts in SharePoint sites, which Microsoft describes as permanently removing the ability to add new custom scripts across OneDrive and SharePoint.

And a second path to HTML on a page is scheduled. Microsoft 365 roadmap item 569208, SharePoint: HTML pages, published 11 August 2026 and targeted for October CY2026, reads in full: Create HTML with Copilot in SharePoint or upload your own HTML from another source. Once stored in the pages library, you can render HTML as a page in SharePoint, make additional edits, and share with your audience. Note upload your own, which removes any model from the question, and the pages library, which is not the document library every paragraph above is about.

What this article does not cover, and will not guess at. No published Microsoft document read for this article states whether DenyAddAndCustomizePages, strict browser file handling or Content Security Policy govern that render path. The feature has not shipped, and a roadmap entry is one sentence long: silence there is not evidence of an absent control. What the two facts together do support is narrower and firm. An audit line reading Custom script: blocked was always a statement about one mechanism, and there is now a second published route by which HTML reaches a page. Whether that route is governed by the same setting is a question to be answered by observation, not by inference, and it is tracked as a separate investigation.

The honest summary. SharePoint did not make HTML safe and it did not quietly let scripts back in. It split one question into several, and each control now answers its own. An audit line reading Custom script: blocked states a fact. The conclusion usually drawn from it, that no executable or interactive experience can run on the site, is a wider claim and does not follow from that fact alone.

SPO-SCRIPT-001 reads DenyAddAndCustomizePages and reports the site that permits custom script, on the consequence Microsoft states rather than on a preference. It is deliberately the only rule in this family: it says the site permits custom script, and it does not say a site is safe when it does not, because everything above is why that second sentence would be false.

The setting has a third value and the rule refuses to commit for it. When SharePoint answers Unknown, the rule reports unknown rather than a pass: the platform declining to state something is not the same as it stating the safe thing.

References

Found something wrong? Suggest a correction. The article source is not public; the engine it cites is.

What this answer underwrites

The engine reads these Microsoft operations to collect evidence, so what is established here is what those collectors rest on.

  • activitywhen a person last changed something on one site
  • sharingwhat one site permits, and its default link
  • sitesevery site this identity can enumerate