← Back to Blog

ENGINEERING · April 16, 2026 · 11 min read

Handling SharePoint blocked file types without breaking your migration

app.migrationfox.com/migration/mg_4c0b82a · verdict
Migration Verdict
gdrive/j.chen → contoso.sharepoint.com/sites/marketing
COMPLETE
Completed
42,091
Skip · source
14
Skip · dest
89
Failed
47
Skipped by source policy
SKIP Windows_Driver_v3.exe Google Drive malware policy
SKIP installer-build-2471.msi Google Drive malware policy
SKIP scan-helper.dll Google Drive malware policy
Skipped by destination tenant policy
SKIP config.aspx tenant blocks .aspx
SKIP macro-enabled-template.htc tenant blocks .htc
SKIP workflow-handler.soap tenant blocks .soap
Real verdict panel · source vs destination skip reasons labelled separately

Here is a migration verdict that quietly causes support tickets. A batch finishes, 42,091 files are in the destination, a hundred or so files are in a “failed” bucket that includes Windows_Driver.exe, installer-build-2471.msi, and config.aspx. The user reads “failed” and opens a ticket. Why did this fail? Can you retry it? The operator digs in, discovers that two of these files failed for one reason, the third failed for a completely different reason, and neither is going to succeed no matter how many times you retry.

The problem is not that the migration broke. The problem is that the verdict lumps three outcomes into one. Blocked at source, blocked at destination, and genuinely failed are not the same thing — they need different handling, different messaging, and different retry logic. Splitting them apart is the difference between a clean client sign-off and a week of follow-up tickets.

Two separate blocking problems

When you move data between cloud platforms, “blocked file type” is not a single concept. There are two different systems with different rules, and it matters which one stops a given file.

1. Google Drive’s malware download policy

Google inspects every file on upload and classifies some of them as potentially harmful — most commonly Windows executables (.exe, .msi), dynamic libraries (.dll), shell scripts, and a handful of other binary formats. Files that trip the policy can still live in Drive (Google does not delete them), but files.get?alt=media will refuse to serve the content unless the caller sets an acknowledgeAbuse=true flag. That flag cannot be set unconditionally — Google requires the request to come from a user who owns the file, and for many service-account migration flows the ownership chain does not satisfy the policy.

The practical effect: certain files in a Google Drive source cannot be downloaded by the migration engine no matter what SharePoint’s tenant policy says. The file is “blocked” but the blocker is the source, not the destination.

2. SharePoint tenant blocked file types

Every SharePoint tenant has a list of file extensions that cannot be uploaded. The list is configured by tenant admins. The default list is small and mostly consists of executables and server-scripting extensions (.aspx, .asmx, .ashx, .master, .htc, .soap). Many organisations relax this list — for example, an engineering tenant that hosts build artefacts will explicitly allow .exe and .dll.

The blocked list changes per tenant. It changes over time. It changes for specific site collections. There is no way to know what a given tenant blocks without asking the tenant, and there is no universal set of extensions that is safe to assume will always be rejected.

Why a hardcoded extension list is the wrong approach

The intuitive design for a migration tool is a pre-flight hardcoded list of SharePoint’s default blocked extensions. Files matching the list get skipped before any upload is attempted. The theory is kind — save a round trip to SharePoint, produce a nicer verdict up front. The practice is not kind.

The fix is structural: stop guessing, start asking. The tenant is the source of truth for what it accepts. Read the live blocked list from the tenant before the migration starts, and trust it.

The correct flow

Blocked-file handling
WRONG
Hardcoded ext list in pre-flight → silent skips → user cannot distinguish source/dest cause → retries that never succeed.
RIGHT
Read live tenant policy at scan → attempt upload → classify 400-response as SKIP-dest → classify source download-refusal as SKIP-source → only real transient errors become FAILED.

The sequence for any file should be:

  1. Scan enumerates the source. Every file, every extension, no extension-based filtering.
  2. Scan queries the destination tenant’s blocked list. For SharePoint destinations the tenant-admin REST endpoint returns the live policy; for targets where that endpoint is not available, the migration probes for upload rejections to derive the same list.
  3. Scan report shows the expected skip counts up front. The operator sees “12 files will be rejected by tenant policy” before starting, with the specific extensions and tenant policy listed.
  4. Migration runs. When a source-side download is refused by Google Drive’s malware policy, the file is classified SKIPPED-source-blocked with the reason “Google Drive malware policy.” When an upload returns a 400 with the SharePoint blocked-file-type error code, the file is classified SKIPPED-dest-blocked with the reason “tenant blocks .aspx.”
  5. Only transient or unexpected errors become FAILED. Network timeouts, throttle exhaustion after max retries, malformed content, storage quota — the things a retry or an operator decision can actually address.

Why skipped-not-failed matters

The distinction between SKIPPED and FAILED is more than aesthetic. A FAILED job implies a defect in the migration — something went wrong that should not have. A sensible operator retries. The retry consumes budget. If the cause was a policy decision the retry is pure waste.

A SKIPPED job implies a conscious exclusion — the file was excluded by a rule outside the migration’s control. A sensible operator does not retry; they either adjust the rule (relax tenant policy, copy the file manually via a different channel) or accept the skip and document it.

Labelling the outcome correctly removes an entire category of wasted operator time, and it makes the verdict panel something a client can sign off without follow-up questions. “Why did 89 files fail?” becomes “89 files were skipped by your own tenant policy — here are the extensions; if you want them migrated, relax policy and re-run.”

SharePoint’s default blocked list (for reference)

For teams that want to know the baseline before their tenant admin customises anything, the default list Microsoft ships is:

ExtensionWhy it is blocked by default
.aspx .asmx .ashxServer-side SharePoint page handlers — risk of uploaded content being executed as server code
.masterSharePoint master page — controls site chrome, a replacement can compromise the site
.htcHTML component — runs script in IE-era contexts; still flagged for compatibility
.soapSOAP message — associated with legacy SharePoint service endpoints
.shtm .shtml .stmServer-parsed HTML — historic web-server execution paths
.dll .exe .msiWindows binaries — malware vector, not tied to SharePoint specifically but blocked at platform level
.config.NET configuration — blocked to prevent SharePoint behaviour overrides
.ps1 .psm1 .ps1xmlPowerShell — executable script, administrative risk
.vbs .wsf .jse .vbeWindows Script Host formats — legacy malware vector

Microsoft has trimmed this list over the years. Several extensions that used to be blocked by default (.html, .htm, .js, .jar) were removed as SharePoint’s execution model moved to client-side rendering and became safer. The exact current default is only authoritative by reading it from the tenant directly.

Relaxing the policy if you need it

If your organisation legitimately needs some of these extensions in SharePoint — an engineering team that ships .exe builds, a DevOps team that stores .ps1 scripts — a tenant admin can relax the list in the SharePoint admin centre under Settings → More features → SharePoint admin center → Policies → Blocked file types. Changes take effect within a few minutes across the tenant.

Two recommendations if you go this route. First, relax per site collection where possible instead of the whole tenant. The admin centre allows a site-level override so that your engineering hub accepts .exe while your finance sites continue to reject them. Second, document the relaxation in your migration run-book — if someone re-tightens the policy a month later, they will not know why the original relaxation existed, and the next migration will surprise them.

The Google Drive side

For the source-blocked case the solution is simpler but less satisfying: no migration tool can unilaterally make Google serve a file its malware policy has flagged. The options for the customer are:

In all three cases the verdict should be SKIPPED-source-blocked, the report should explain why, and the retry button should not be offered — because retry does not help.

What a four-column verdict looks like

A migration report with the right structure shows four columns instead of two: Completed, Skipped-Source, Skipped-Destination, Failed. Each column is clickable to drill into the full list. Each skip is annotated with its policy reason. For client sign-off documents, the split makes the conversation cleaner:

Related reading

Get started

Run a migration with live tenant-policy detection at app.migrationfox.com/register. The four-column verdict panel is on by default for every workspace.

Honest verdicts, not silent skips

Live tenant policy detection. Source vs destination labelled separately. Retry only what retry can fix.

Start Free →