Permissions & Storage Lock
What permissions designers and users need, and how configuration writes are controlled.
Model Overview
The form configuration is a file in the Site Assets library, so it is protected by SharePoint permissions. The model has three layers:
- Who may open the designer (designer role in the configuration): site owners, or site owners and a designated designer group.
- Who may write the configuration: controlled by locking the
SiteAssets/FormCustomizerfolder (unique permissions). - Who may read it: the form runtime reads the configuration as the signed-in user, so anyone opening the form must have read access.
The "editor lock" password in the designer is not a security boundary. It prevents accidental opening of the editor, not reading or overwriting the file. True protection is provided only by the folder lock described below.
Designer Permissions
The Form Settings button (gear icon) and the Custom form command are visible only to authorized users. The role is configured in the settings (securityConfig.allowedEditorRole, see Configuration Security and the user guide page on security).
allowedEditorRole Value | Who May Open the Designer |
|---|---|
manageWeb (default for new forms) | Site owners: users with the ManageWeb permission on the list. |
group | Site owners and members of the SharePoint group specified in allowedEditorGroup (by group name). |
manageLists (legacy value) | Behaves like manageWeb: only site owners can modify the configuration. The "Manage Lists" permission alone is not sufficient because members with Edit level also have it. |
Permissions are verified by checking the list's effectiveBasePermissions and group membership. If verification fails (REST error), the buttons are not displayed and the user is treated as unauthorized.
To lock the storage itself, the ManagePermissions permission on the site (site owner) is required. A designer from the designer group can save configurations, but cannot change folder permissions.
Creating Columns from the Designer
Only a user with the ManageLists (Manage Lists) permission on the list can create a new list column from the designer. This permission is read from pageContext.list.permissions and reported by the data provider as canCreateFields; without it, the create column action is not offered. This is separate from the designer role above: the column is created under the signed-in user's identity, so SharePoint would reject it without permissions anyway. The column is added only to the content types selected by the user. If adding to a content type fails (e.g., missing permission on the content type), the column remains in the list and the designer lists which types it could not be added to.
Locked Configuration Storage
While the storage is unlocked, the folder inherits permissions from the Site Assets library. Anyone with write access to the library (typically a site member with Edit permission) could then overwrite the configuration and inject custom actions. The lock prevents this.
What the Lock Does
The root folder SiteAssets/FormCustomizer receives unique permissions:
- Permission inheritance is broken copying existing permissions (readers do not lose access).
- The site owners group and the signed-in user performing the lock receive Full Control.
- All other principals retain only Read and Limited Access. Anything higher (Contribute, Edit, Design, or custom roles with Manage Lists or Manage Permissions) is replaced with Read. Roles are identified by type, not by localized name.
- Read is added for the entire organization (Everyone except external users, EEEU) and for guests (Everyone). Both can be disabled in the designer: Read configuration for entire organization (
securityConfig.configReadAllUsers) and Read configuration for external users (guests) (securityConfig.configReadGuests); both are enabled by default. - Nested items with unique permissions are reset to inherit from the root. List subfolders are an exception (see below).
Access is added first and removed afterwards during changes, so nobody temporarily loses read access. If locking fails, the original inheritance is restored. If restoring also fails, the designer displays a warning with a repair command.
Locking includes cleaning up nested items under FormCustomizer that have unique permissions (resetting them to inherit). The query finds nested items by FileRef and reads the unique permissions flag (HasUniqueRoleAssignments) for each item individually. If SharePoint's response omits this field for any item, locking fails with lockFailed and nothing is considered safe.
When It Locks
- Automatically on the first save by a site owner (a user with
ManagePermissions). - By clicking Lock Now under Security, Configuration Storage section.
- Manually via a PowerShell command.
An unauthorized user (a designer without permission to manage permissions) cannot lock the storage. After saving to an unlocked storage, the designer receives a warning "Configuration storage is not locked" with a command for the site owner.
Reconciling Permissions on Subsequent Saves
When the storage is already locked, a site owner saving the configuration does not re-apply permissions unless the inputs have changed: the signed-in owner, designer group, organization read access, guest read access, and tenant. Saving is therefore fast and does not trigger dozens of REST calls. A fingerprint of these inputs is stored in SiteAssets/FormCustomizer/<listId>.perm.json in the storage root, which only owners can write to, so it persists across page loads and cannot be spoofed by a designer. It is written only after a clean reconciliation with no errors or warnings.
- If any input changes, or if the fingerprint is missing or unreadable, permissions are reconciled as before.
- Manual permission changes made outside the form are not automatically corrected on save. Force reconciliation by clicking Lock Now, which always reconciles permissions.
- If reconciliation fails after writing the configuration (e.g., 429 throttling), the configuration remains saved and only a warning "Configuration storage is not fully locked" with a repair command is shown. The fingerprint is not written, so the next save will retry reconciliation.
Confirmation on First Lock
If the configuration file was created before locking (or imported from a legacy location), anyone could have modified it in the meantime. Before sealing, the designer displays a Lock and save this configuration? dialog with a security summary:
- source: pre-lock file (when it was saved and who last modified it), or legacy configuration from the property bag,
- count and names of scripts (
onFormLoad,onBeforeSave, functions), - buttons with actions,
- number of rules,
- authorized editor role and designer group.
Only after clicking Confirm, lock and save is the storage sealed. When clicking "Lock Now" on an existing file, Lock and seal existing file is offered. If you do not trust the contents, cancel the dialog and save the form from the designer: the file will be overwritten with your draft. On the first lock, pre-lock history is also deleted and the backup is replaced with the sealed file.
Designer Group
To allow people who are not site owners to edit the configuration, set the role to group and specify the SharePoint group name (allowedEditorGroup).
- Each list has its own subfolder
SiteAssets/FormCustomizer/<listId>. The subfolder receives unique permissions: copied from the root plus Contribute for the designer group. The group can thus write only the configuration for this list, not others. - Permissions are applied only upon saving by a site owner. If a designer changes the group, they receive a warning that permissions were not updated and an owner must save it again.
- If the list has no designer group, the subfolder inherits from the root (any previous unique permissions are removed).
- A designer cannot create the list folder in the root: if it does not exist yet, the message "This list's configuration folder does not exist yet. A site owner must save the form first." is shown.
Rejected Groups
Saving is rejected and permissions are not changed if the designer group is:
- the site's associated Members or Visitors group (which would grant write access to all members),
- a group whose members include Everyone or Everyone except external users (which would grant write access to everyone).
A group that does not exist on the site is saved with a warning "designer group … does not exist on the site": it has no write access. Check the exact name.
License File
The license.txt file resides directly in the root FormCustomizer folder, so after locking it inherits its permissions: only a site owner can write to it; members and designers receive a 403 error and the license dialog explains why. Read access remains open to everyone (the license is also read by unauthorized users). While the storage is unlocked, anyone with write access to Site Assets can overwrite the file, but the key is signed so a valid key cannot be forged. See Licensing.
Manual Locking and Repair in PowerShell
The designer provides the command under Security, Configuration Storage section, and also displays it in post-save warnings (notLocked, lockFailed, rollbackFailed). The command is intended for PnP.PowerShell and a site owner. It includes the list subfolder if a designer group is configured. The example below uses placeholders; copy the actual command from the designer (it includes your site URL, <listId>, and group name).
Connect-PnPOnline -Url "https://<tenant>.sharepoint.com/sites/<site>" -Interactive
$web = Get-PnPWeb -Includes AssociatedOwnerGroup,CurrentUser,RoleDefinitions
$ctx = Get-PnPContext
$role = { param($t) $web.RoleDefinitions | Where-Object { $_.RoleTypeKind -eq $t } | Select-Object -First 1 }
$full = & $role "Administrator"; $read = & $role "Reader"; $contrib = & $role "Contributor"
function Grant($item, $principal, $def) {
$b = New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($ctx); $b.Add($def)
$null = $item.RoleAssignments.Add($principal, $b)
}
# 1) FormCustomizer root: break inheritance WITH copy (readers keep access)
$root = (Get-PnPFolder -Url "/sites/<site>/SiteAssets/FormCustomizer" -Includes ListItemAllFields).ListItemAllFields
$root.BreakRoleInheritance($true, $true); Invoke-PnPQuery
# 2) owners and current user = Full Control
Grant $root $web.AssociatedOwnerGroup $full; Grant $root $web.CurrentUser $full; Invoke-PnPQuery
# 3) leave only Read and Limited Access for everyone else
$null = Get-PnPProperty -ClientObject $root -Property RoleAssignments
foreach ($ra in @($root.RoleAssignments)) {
$null = Get-PnPProperty -ClientObject $ra -Property Member, RoleDefinitionBindings
if ($ra.Member.Id -eq $web.AssociatedOwnerGroup.Id -or $ra.Member.Id -eq $web.CurrentUser.Id) { continue }
$keep = @($ra.RoleDefinitionBindings | Where-Object { $_.RoleTypeKind -in 'Reader','Guest' })
if ($keep.Count -ne @($ra.RoleDefinitionBindings).Count) {
$ra.RoleDefinitionBindings.RemoveAll(); $ra.RoleDefinitionBindings.Add($read)
foreach ($k in $keep) { if ($k.RoleTypeKind -eq 'Guest') { $ra.RoleDefinitionBindings.Add($k) } }
$ra.Update()
}
}
Invoke-PnPQuery
# 4) read access for entire organization and guests (omit what you don't want)
$eeeu = "c:0-.f|rolemanager|spo-grid-all-users/$(Get-PnPTenantId)"
foreach ($login in $eeeu, "c:0(.s|true") { Grant $root ($web.EnsureUser($login)) $read }
Invoke-PnPQuery
# 5) only when using a designer group: list subfolder (copy from root + Contribute)
$sub = (Get-PnPFolder -Url "/sites/<site>/SiteAssets/FormCustomizer/<listId>" -Includes ListItemAllFields).ListItemAllFields
$sub.BreakRoleInheritance($true, $true); Invoke-PnPQuery
Grant $sub $web.SiteGroups.GetByName("Form Designers") $contrib; Invoke-PnPQuery
The command generated by the designer has not been verified against a live tenant (a comment in the code notes this). Test it on a staging site before production use and verify the result on the folder permissions page.
Residual Risks
- Before the first lock: until an owner saves the form or locks the storage, anyone with write access to Site Assets can modify the configuration. The designer shows a warning to the owner when storage is unlocked (Configuration storage is not locked). That is why the first-lock confirmation dialog exists: review the script summary carefully.
- Deleting and recreating Site Assets: a user with Manage Lists permission can delete and recreate the Site Assets library, removing the folder lock. Such an action is audited and recoverable from the recycle bin. On the next save, the storage locks again.
- Second layer of defense: custom scripts are disabled by default (Script Policy). Even if a configuration is overwritten, foreign code cannot execute unless the policy allows scripts. Expressions are always safe.
- Tenant and site collection administrators are not restricted by the lock.
End-User Permissions
The form does not have its own data permissions: it operates with the signed-in user's permissions. Therefore, the user needs:
- New item: permission to add items to the list. Edit: permission to edit items. Display: permission to read items.
- Attachments: same permissions as the item (adding and removing attachments requires editing the item).
- Lookups, people, taxonomy, and related lists: read access to the source list, term set, or library. Without it, the field has no options or fails to load.
- Configuration read access: read access to the
SiteAssets/FormCustomizerfolder. After locking, site group members and anyone granted organization or guest read access have this.
Fields that fail to load (e.g., due to permissions or a batch query error) are shown as read-only in the form and are not written on save. See Unloaded Fields. Display mode (DisplayForm) never reports unsaved changes.
Users Outside Site Groups
A user who lacks read access to the configuration folder (e.g., access only via item sharing, or a guest when guest read access is disabled) cannot read the configuration. For them, the form runs with the default layout generated from list columns, without your tabs, rules, or buttons. A site owner sees a warning about the unreadable configuration, while a regular user sees the message "The form could not be loaded completely. Please contact the site owner." The solution is to keep organization read access (and guest access, if needed) enabled, or add the user to a site group.
If you rely on form rules to hide sensitive fields or block saving, ensure all users can read the configuration. Rules are not a security mechanism: true data protection is provided only by SharePoint list and column permissions.
NoScript Sites
On sites with DenyAddAndCustomizePages (NoScript, default on modern sites), writing to the web property bag is not possible, even for owners. Therefore, the product does not write to the web property bag: both configuration and license are stored as files in Site Assets. Legacy keys in the property bag are still read. You do not need the AddAndCustomizePages permission.