30-second answer
Get-PnPTenantSite -Identity https://contoso.sharepoint.com/sites/team |
Select-Object Url, DenyAddAndCustomizePagesTrue 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. SharePoint HTML
pages, which run their own JavaScript in a sandbox, are governed by a different
setting: Microsoft documents them as on by default and switched off by each site
owner in the Site Pages library.
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..htmland.htmare 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
# 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).ContentSecurityPolicyEnforcementExample output
Url DenyAddAndCustomizePages
--- ------------------------
https://contoso.sharepoint.com/sites/team True
https://contoso.sharepoint.com/sites/legacy FalseRead 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.
| Control | Question it answers |
|---|---|
DenyAddAndCustomizePages | May anyone here insert script into a page? |
| The nine blocked extensions | May this kind of file be put in a library at all? |
| The execution mark on a file | Was this file put here by somebody holding AddAndCustomizePages? |
| Strict browser file handling | What does the browser do when the file is opened? |
| App Catalog approval | Did an administrator approve this component? |
| Content Security Policy | Which 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 stopped working
in SharePoint Online 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 the tenant setting AllowClassicPublishingSiteCreation
defaults to False, under which classic publishing site collections cannot be
created and the publishing features cannot be activated; set to True, it
still allows both. The tenant-level reprieve for script on those sites,
Set-SPOTenant -DelayDenyAddAndCustomizePagesEnforcementOnClassicPublishingSites,
ended on 15 March 2026. Microsoft's current schedule closes what remains. From
1 March 2027 AllowClassicPublishingSiteCreation is enforced as False in every
tenant and cannot be changed, and a tenant created on or after that day gets no
new classic pages and DenyAddAndCustomizePages enforced as True. From
1 October 2028 every remaining tenant follows: classic user-created pages become
read-only, and DenyAddAndCustomizePages is enforced as True and cannot be
changed. Until then, 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 now exists, governed elsewhere.
SharePoint HTML pages (Microsoft 365 roadmap 569208, message centre
MC1479517) render an uploaded or Copilot-made .html file from the Site Pages
library as a page. The message centre gives public preview in early October 2026
and general availability from mid-November to late December 2026. Microsoft's
support article documents the control, and it is not this setting: HTML pages
are enabled by default, a site owner switches them off with Allow HTML
files in the Site Pages library, and to Can I disallow or restrict HTML pages
at the tenant level? it answers No. The HTML runs in a sandboxed iframe.
JavaScript is supported when it is contained in the same file, outbound calls
are blocked, and Content Security Policy (CSP) rules provide extra isolation.
The article does not mention custom script, and a published test by Denis
Molodtsov found HTML pages running on a site with custom scripting denied.
What the two facts together establish. An audit line reading Custom script: blocked was always a statement about one mechanism. Whether a user's
own HTML and JavaScript can run on the site is now answered by a different
setting, held by each site owner, and we have found no documented API that
reads it. Until one exists, that second question is reported as not established, never inferred from the first.
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.
Related governance rules
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
- Security considerations of allowing custom script (Microsoft Learn)
- Allow or prevent custom script (Microsoft Learn)
- Migrating from the permissive browser file handling to the default strict browser file handling (Microsoft Learn)
- Support for Content Security Policy (CSP) in SharePoint Online (Microsoft Learn)
- Get started with Copilot in SharePoint (preview) (Microsoft Learn)
- Baseline security mode settings (Microsoft Learn)
- MC1117115, Updates to custom scripting in sites and Classic Publishing site creation (Microsoft 365 message centre, 18 July 2025, last updated 29 July 2026)
- Upcoming changes to classic publishing sites, classic pages, and custom scripting in SharePoint Online (Microsoft Learn, read 7 November 2026)
- Set-SPOTenant,
AllowClassicPublishingSiteCreation(Microsoft Learn, read 7 November 2026) - Microsoft 365 roadmap 569208, SharePoint: HTML pages (created 11 August 2026; on 6 November 2026 still In development, targeted October CY2026)
- Create, upload, edit, and publish HTML pages in SharePoint (Microsoft Support, read 6 November 2026)
- MC1479517, SharePoint: HTML pages (Microsoft 365 message centre, September 2026, read through public copies)
- SharePoint HTML pages, what they can and cannot do (Denis Molodtsov, August 2026, updated October 2026)
- Get-PnPTenantSite (PnP PowerShell)
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.