Working with Microsoft 365 Sensitivity Labels from SAS programs

If you've read my smash hit blog post, Using SAS with Microsoft 365 (OneDrive, Teams, and SharePoint), then you already know that Microsoft 365 content (OneDrive, SharePoint, and Microsoft Teams) can be a rich data source for your SAS programs. With the Microsoft Graph API and a bit of SAS macro glue, you can discover files, download them into a SAS session, and automate repeatable analytics workflows.

But there's an important control layer that sits on top of Microsoft 365 content that you have to respect: Sensitivity Labels.

In this post, I'll introduce Sensitivity Labels, explain where they come from, and show how they affect what you can (and can't) do when you're automating data pipelines in SAS. I'll also introduce some new SAS macro routines I added to help you detect whether sensitivity labels are applied.

Sensitivity labels and Microsoft Purview Information Protection

Sensitivity labels are part of Microsoft Purview Information Protection. Purview is Microsoft's governance, risk, and compliance framework, and sensitivity labels are one of its core mechanisms for classifying and protecting content.

Administrators define sensitivity labels in the Microsoft Purview portal. Those same labels are then surfaced throughout Microsoft 365:

In Word, Excel, and PowerPoint

In Outlook

In SharePoint and OneDrive

In Microsoft Teams–backed document libraries

From a user's perspective, these labels often look simple -- Confidential, Internal, Public, and so on. Under the hood, though, a sensitivity label can carry real enforcement:

Restrictions on sharing

Restrictions on download or copy

Optional encryption of the file contents

That last point is especially important if your workflow involves pulling content into SAS.

Why sensitivity labels matter for SAS automation

When you use SAS to download files through Microsoft Graph APIs, you're operating outside of the Office application experience. That has consequences:

Files without encryption (even if they are labeled) can generally be downloaded and read normally.

Files with encryption enforced by a sensitivity label cannot be read by automated SAS processes.

This isn't a limitation related to SAS. It's a designed boundary for information protection, carried through in Microsoft 365. If a sensitivity label includes encryption, Microsoft Graph APIs will prevent you from accessing the decrypted content stream. As a result:

PROC IMPORT will fail with an error ("File not found")

LIBNAME engines (like XLSX) won't be able to read the file (library will appear empty)

Any unattended process that assumes "download success == readable" will break

Before downloading and importing Microsoft 365 content into SAS, you should understand whether sensitivity labels are applied, and what they enforce.

Detecting sensitivity labels with Microsoft Graph APIs (from SAS)

The macros in the sas-microsoft-graph-api project now include support for extracting sensitivity label metadata from supported files. Under the covers, it uses the extractSensitivityLabels API to get this information for each file.

While useful, note that there are some limitations:

Currently, sensitivity labels apply only for Microsoft-native file formats: .docx, .xlsx, .pptx and so on. Formats like CSV and TXT do not have sensitivity labels.

PDF files can also have labels if you create them from within Microsoft apps or by using a supported Adobe Acrobat integration.

The API provides label IDs, not friendly names like "Confidential".

That last point catches many people by surprise.

Why you don't get the friendly label name

With the Microsoft Graph API, listing all sensitivity labels (including their names and policies) is considered a privileged operation. Most users and most apps will not have permission to call those endpoints. (There is an API method to query these but it's not usable by most users.) So when you use the extractSensitivityLabels API, what you get back is something like:

sensitivityLabelId = 4e4234dd-377b-42a3-935b-0e42f138fa23

That ID is meaningful (in that you can see there is a label applied), but not human-readable on its own.

Building your own "sensitivity label data dictionary"

Even though you can't usually list labels directly, you can still build something useful. A practical approach is to create your own sensitivity label data dictionary:

Use the SAS macros to extract sensitivity label IDs from files you can access. Then correlate those IDs with:

Labels you see when opening documents interactively in Office

Information from your Microsoft 365 or Purview administrators

Store that mapping in a small SAS table or JSON file. Over time, this gives you a working reference like:

Sensitivity Label ID | Label name (observed) | Encryption enforced
4e4234dd-… | Confidential | Yes
91b12a7c-… | Internal | No

That's often enough to drive automation decisions, such as:

Skip encrypted files

Raise warnings in logs

Route files for manual review

Example: listing sensitivity labels for a folder

Here's a simple example that lists sensitivity labels for all supported files in a SharePoint or OneDrive folder.

First, list the contents of the folder (you can use whatever discovery pattern fits your environment). Then fetch the sensitivity labels for all files in the root of that folder.

/* pull ALL items from root folder */
%listFolderItems(driveId=&libraryId., folderId=root, out=work.paths);
proc print data=paths (obs=10);
run;

/* Find the folder named "Sensitivity Labels */
proc sql noprint;
select id into: folderId from work.paths where name="Sensitivity Labels";
quit;

/* Fetch all Sensitivity Labels (if they exist) from the items in the "Sensitivity Labels" folder */
%getAllSensitivityLabels(driveId=&libraryId., folderId=&folderId.,out=work.senslabels);
proc print data=work.senslabels;
run;

Example of sensitivity labels data

The resulting dataset includes:

File identifiers

File names

Sensitivity label IDs (when present)

From here, you can:

Join back to your file listing

Filter out files with known "encrypted" label IDs

Decide which files are safe to download and import into SAS

Final note on encrypted content

It's worth repeating: automation stops at encryption. If a sensitivity label results in an encrypted file, Microsoft Graph APIs will not give SAS access to the decrypted content. That's exactly how it should work.

Rather than trying to work around this, treat it as a design signal:

If a file is encrypted, it probably requires a human-in-the-loop process.

Your SAS job can still detect the file and report on it, even if it can't read it.

That alone is valuable for data governance and auditing workflows. If an automated process is needed to process the file, you will need to consider using a different label that does not confer encryption. Or, consider an "in-platform" process that uses Microsoft Power Automate or other Microsoft 365 tools.