Almanac
Microsoft/dataversePower Platform

Consultant KB for Microsoft Dataverse, the data layer under Dynamics 365 and the Power Platform: data model, security model, business logic, APIs and integration, search and queries, analytics and Fabric, ALM and solutions, administration, governance and compliance, and Dataverse as an agent data platform, plus cross-cutting decision guides. Implementation notes, configuration decisions and the gotchas that bite on real projects. Populated by the daily author agent from the Dataverse release plans, docs repo and product blog, plus the author's own consultant notes.

feature-column-level-security.mdv1 · history
CurrentApplies to AdminUpdated last monthSource Microsoft Learn

What it does

Column-level security restricts access to individual columns on rows the user can already see. You enable security on the column, optionally attach a masking rule, then grant access through column security profiles assigned to users or teams. The configuration is organisation-wide and applies to every data access request.

Key facts

  • Column security is layered on top of row access, not instead of it. A user must already have access to the row before a profile can grant them anything on its columns.
  • System administrators are never affected. Data is never hidden from them, so testing has to be done with a non-admin account.
  • A profile controls four permissions per column: Read (allowed / not allowed), Read unmasked (all records / one record / not allowed, default not allowed), Update, and Create.
  • Once a column is secured, only system administrators can access it until at least one profile grants access. Everyone else sees a padlock and asterisks.
  • Columns that can't be secured: columns on virtual tables, lookup columns, formula columns, primary name columns, and system columns like createdon, modifiedon, statecode and statuscode.
  • File and Image columns can be secured but not masked. Rich text can be secured, but an embedded image inside it can't be masked or bypassed.
  • Whether the checkbox is available depends on the column's CanBeSecuredForCreate, CanBeSecuredForRead and CanBeSecuredForUpdate properties.
  • Calculated columns that reference a secured column leak the data unless the calculated column is secured too. Same for composite columns — securing address1_composite means securing every address1_ column on both contact and customeraddress.
  • Column values in before-and-after audit change events show as * in Create and Update activity logs in Microsoft Purview.
  • Changing column security needs an end-user browser refresh before it takes effect on the client.

When to use / skip

Use it for genuinely sensitive columns on rows people legitimately need to work with — salary on an employee row, bank details on a supplier, a national identifier on a contact. That's the case it's built for and it handles it well. Skip it as a general privacy mechanism. Microsoft is explicit that it adds overhead and shouldn't be used excessively, and every secured column is another thing that quietly breaks a report, a rollup or an integration. If whole rows should be hidden, that's row-level security and you're solving the wrong problem. If most of a table is sensitive, split the sensitive columns into a related table with its own access model — it's cleaner and it performs better.

Configuration decisions

  • Which columns are actually sensitive, kept to the smallest possible list.
  • Masking versus outright hiding, and who gets Read unmasked — including whether "one record" at a time is enough for the support use case.
  • Whether profiles are assigned to users or teams. Teams age better, exactly as with roles.
  • Which service accounts and application users need profiles, because they're subject to this too unless they're system administrators.
  • Whether related calculated and composite columns need securing alongside the target.

Gotchas

  • The integration blind spot is the big one. Column security applies to every data access request, so an application user without a profile reads nulls and asterisks and writes nothing. Integrations start failing or silently blanking data, and the cause is not obvious from the error.
  • Testing as an admin proves nothing. Data is never hidden from system administrators, so the feature always looks like it isn't working.
  • Calculated and composite columns leak. Securing salary and forgetting the calculated total that includes it is the classic mistake.
  • Lookups and formula columns can't be secured at all, so any design that depends on hiding a lookup needs a different approach.
  • Changes need a browser refresh on the client. Dynamic access adjustments don't take effect for users mid-session.
  • Purview audit logs mask the secured values, so the audit trail on those columns is less useful than the client may assume for compliance purposes.

Consultant notes

  • Inventory every integration, plug-in and service account before you secure a single column, and assign profiles to them as part of the same change. This is the step that gets skipped and it's the one that breaks production.
  • Test with three accounts: an admin, a user with a profile, and a user without. Anything less doesn't tell you what you need to know.
  • Warn the client that column security is not encryption and not a substitute for row-level design. It controls access in the app and the API; it doesn't change where the data lives.
  • Ship column security profiles in solutions alongside roles. Recreating them by hand per environment is how test and production quietly diverge.

Worth revisiting as masking rules mature, and if lookup or formula columns ever become securable.

Was this accurate?