---
title: "ContentDocumentLink sharing, and the access nobody expects"
url: "https://trailassembly.com/contentdocumentlink-sharing/"
topic: "Admin and Permissions"
published: "2026-09-12T05:59:26+00:00"
updated: "2026-10-06T13:53:25+00:00"
---

# ContentDocumentLink sharing, and the access nobody expects

**The short answer:** a file’s access comes from its links, and a link with `ShareType = 'I'` inherits permission from whatever record it points at. So a file becomes visible to everyone who can see any record it is linked to, and there is nothing on the file itself that tells you which records those are. That is the access nobody expects.

## The three ShareType values

- **`V`, Viewer.** The linked record’s users can view and download. They cannot edit or delete the file.

- **`C`, Collaborator.** They can also edit the file, upload new versions, and change its sharing.

- **`I`, Inferred.** Permission follows the linked record: edit access on the record means collaborator access on the file, read access means viewer.

Inferred is the default for files uploaded through the Files related list on a record, which means most files in an org are on inferred sharing without anyone having chosen it.

## Visibility narrows it further

`Visibility` is a second dimension, and both apply:

- **`AllUsers`** — internal and external users with access to the linked record.

- **`InternalUsers`** — internal only, even if a community user can see the record.

- **`SharedUsers`** — only users the file has been explicitly shared with, ignoring the record.

For anything sensitive on a record that community or portal users can reach, `InternalUsers` is the setting you want and it is not the default.

## Why you cannot audit this easily

ContentDocumentLink cannot be queried without a filter on `ContentDocumentId` or `LinkedEntityId`. This is enforced by the platform:

```apex
SELECT Id FROM ContentDocumentLink
// Implementation restriction: ContentDocumentLink requires a filter by a
// single Id on ContentDocumentId or LinkedEntityId
```

So there is no “show me every file link in the org” query. An audit means iterating over records and querying links per record, in batch, which is slow and is the only route available.

```apex
for (List<Account> chunk : [SELECT Id FROM Account]) {
    Set<Id> ids = new Map<Id, Account>(chunk).keySet();
    for (ContentDocumentLink l : [
        SELECT ContentDocumentId, LinkedEntityId, ShareType, Visibility
        FROM ContentDocumentLink WHERE LinkedEntityId IN :ids
    ]) { ... }
}
```

Note that `IN` with a set is permitted even though an unfiltered query is not.

## The exposure pattern

A support agent uploads a customer’s document to a case. The case is linked to an account. Later, someone links the same file to an opportunity so the sales team can see it. The opportunity is visible to the whole sales organisation through the [role hierarchy](https://trailassembly.com/role-hierarchy/), and the customer document now is too.

Nothing in this sequence is a misconfiguration. Each step is a reasonable action, and the file’s access is the union of every link. That union is the thing to reason about, and it is why files carrying anything sensitive should be linked to exactly one record and set to `SharedUsers` or `InternalUsers`.

## Deleting a link is not deleting the file

Removing a ContentDocumentLink removes the file from that record. The ContentDocument still exists, still belongs to whoever uploaded it, and is still in their personal Files. If the intent is that the file is gone, delete the ContentDocument, and note that it goes to the recycle bin with the usual 15 days.

## Guest users

[Guest user](https://trailassembly.com/guest-user-security-model/) access to files is deliberately restrictive. A guest user generally cannot see a file through an inferred link, and making a file publicly available means a ContentDistribution record, which generates a public URL with optional password and expiry. That URL bypasses Salesforce login entirely, so treat generating one as a publishing decision.

## Frequently asked

**Why can a user see a file they were never given?** Query the links for that ContentDocumentId. One of the linked records is visible to them.

**Can I change ShareType after the fact?** Yes, update the ContentDocumentLink. It is an ordinary record.

**Does file access respect [field-level security](https://trailassembly.com/apex-enforcing-crud-and-fls/)?** Not meaningfully. A file is not a field. Access is the link model described here and nothing else.

---

Source: https://trailassembly.com/contentdocumentlink-sharing/
Trail Assembly — independent Salesforce write-ups.
