Skip to content

Cloud-sync protection, claim by claim ​

WIN-DLP-EPIC-018 asks to recognise managed synchronisation directories and treat them correctly, including placeholders, because a synced library is where the documents are, and it is where a naive agent does the most damage.

The placeholder half is done, and done with unusual care - it is the clearest example in this product of declining to do something because doing it would cause the harm.

The recognition half is implemented by DLP-189: Windows reads the providers' own configuration and combines it with administrator-declared roots. The capability matrix reports the channel as monitor-and-warn, never as prevention.


1. Placeholders: the damage a naive agent does ​

A file in a OneDrive or SharePoint-synced library may be a placeholder: the metadata is local and the content is not. Opening it downloads it.

So an agent that scans a synced library the obvious way hydrates every placeholder in it - megabytes to gigabytes of download, on somebody's laptop, on a metered connection, caused by the security tool. And each download is itself a data transfer the product would then report.

ClaimProved by
A dehydrated placeholder is reported, never readmonitor::tests::a_dehydrated_placeholder_is_reported_not_read
Each recall attribute has its own sentencemonitor::tests::each_recall_attribute_has_its_own_sentence
The most specific attribute wins when several are setmonitor::tests::the_most_specific_attribute_wins_when_several_are_set
An ordinary file is not mistaken for a placeholdermonitor::tests::an_ordinary_file_is_not_a_placeholder
A real local file is read normallymonitor::tests::a_real_local_file_is_read_normally

The reporting is what makes it defensible: a placeholder is not skipped silently, it is reported with the reason - "cloud placeholder: the content is not on this machine, and reading it would download it" - so an operator sees a file that was not scanned rather than a file that looked clean.

The last two rows matter as much as the first. A check this conservative is worth nothing if it also refuses ordinary local files, and both directions are tested.

2. Recognition: configured evidence, never a folder-name guess ​

agent/core/src/cloud_sync.rs recognises OneDrive roots from the provider's registry accounts (including loaded user hives under HKEY_USERS when the service runs as LocalSystem), Dropbox roots from info.json, and any root an administrator declares. A directory merely called OneDrive is not enough: the provider or the administrator has to identify it.

agent/core/src/runner.rs resolves each file path against those roots before the event is built. A matching write is emitted as Channel::CloudSyncFolder, so a policy scoped to that channel can fire; the event names the provider and, only where the provider publishes it, whether the account is personal or business. It never guesses an account name, address or tenant.

Whether the destination is sanctioned (DLP-1210). A declared root is trusted and a personal account is not. A OneDrive business account is trusted when the tenant OneDrive recorded for it (ConfiguredTenantId) is on the administrator's sanctioned_cloud_tenants list in agent.toml. It is untrusted when the list exists and leaves that tenant out. With no list, or no recorded tenant, it is undecided. The tenant id is read from the same registry text and used only for that decision on the endpoint; the event carries the provider, the account kind and the answer, never the tenant (PRIVACY_MODEL.md §44). A business Dropbox publishes no team identifier, so it stays undecided. The registry value is parsed and tested from recorded reg.exe text; it has not been read from a real OneDrive account on a Windows host.

This is the correction delivered by DLP-189. DLP-132 remains the regression history: before recognition existed the matrix claimed a channel no event could emit. The matrix now names the evidence behind the row and the tests pin both sides:

ClaimProved by
A folder name alone proves nothingcloud_sync::tests::a_folder_that_merely_looks_like_a_sync_root_is_not_one
OneDrive personal and business roots remain distinctcloud_sync::tests::a_personal_and_a_business_account_are_both_read_and_told_apart
An unpublished account kind stays absentcloud_sync::tests::an_account_kind_the_provider_did_not_publish_is_absent
A business account's tenant is read, and only a business account'scloud_sync::tests::a_business_account_carries_the_tenant_onedrive_recorded_whatever_the_value_order
The sanctioned list decides a business account, and no list decides nothingcloud_sync::tests::the_sanctioned_list_decides_a_business_account_and_nothing_else_does
A list entry that is not a tenant id is refused at startconfig::tests::a_sanctioned_tenant_that_is_not_a_tenant_id_is_refused
The most specific nested root winscloud_sync::tests::the_most_specific_root_wins
A provider this build does not know is carried, not discardedcloud_sync::tests::a_provider_this_build_has_not_heard_of_is_carried_rather_than_dropped

The test that would have caught it ​

platform::tests::a_channel_is_claimed_only_where_something_produces_it now asserts that every channel claimed as monitored appears in the list of channels the agent can actually emit.

It is a hand-maintained list, which is a weakness, and it is still better than a claim nobody checks: somebody adding a channel must edit it, and the assertion makes that edit necessary rather than polite.

It caught a second thing immediately. The first version of the list was built from a grep of runner.rs, and the test failed on mobile_device - which is emitted on Linux, through DeviceClass::channel(), because a phone over MTP is a FUSE mount and a write to it is an ordinary file event on a real path. A channel reaches an event two ways and the second is easy to miss. The list now says which is which.

3. What is still not seen ​

GapState
Recognising a sync rootImplemented. Provider configuration or an administrator declaration; never a path-name heuristic (DLP-189)
The upload itselfAbsent, and not achievable from the filesystem. The local write is seen; what the sync client then does with it over TLS is not. DLP-1178 is scanning the cloud store server-side instead
A placeholder's contentDeliberately not read. §1

The second row is the honest limit of this whole channel: an endpoint agent watching a directory sees a file appear in it. Whether the sync client subsequently uploaded that file, to which tenant, under whose account, is not visible from the filesystem - and DLP-1178's answer is to ask the cloud provider rather than the endpoint.


4. What is not covered ​

  • Nothing here has been run against a real OneDrive client. The placeholder tests synthesise the file attributes; no test has a real dehydrated file, because that needs a Windows host with a signed-in account. DLP-3.
  • No test has exercised provider discovery against a real signed-in OneDrive or Dropbox client. Parsing and path resolution are unit-tested, and the Windows end-to-end runner does not carry a provider account. This is part of the real-fleet gap recorded as DLP-449.

Statements here describe what is built and tested; planned work is marked as planned.