Secure Dropbox with cnspec
Scan Dropbox Business team sharing settings, members, groups, linked devices, and third-party apps against security and compliance best practices with cnspec.
A Dropbox Business team holds company content, and the settings that decide who may share it outward, which devices hold a copy, and which third-party apps hold standing access decide how far that content travels. cnspec reads a Dropbox Business team through its Business API and evaluates the team wide external and public sharing settings, the members and their role, status, and email verification, the groups that structure sharing, the devices and web sessions linked to member accounts, and the OAuth apps members have authorized against their accounts.
cnspec reads team administration only. It never reads file contents, folder structure, or shared link targets: it queries the Business API's team endpoints, which have no access to member file data.
If you're new to cnspec, start with the Quickstart. For an overview of every SaaS platform cnspec can scan, see the SaaS scanning overview.
The Dropbox resources are experimental. Field names and behavior can change in a future cnspec release.
Prerequisites
To scan Dropbox with cnspec, you must have:
- cnspec installed on your workstation
- A Dropbox Business team, since the team endpoints aren't available on individual plans
- A team scoped access token
Authenticate
cnspec authenticates as the team rather than as a member, using a Dropbox Business App with team level access. In the Dropbox App Console, create an app, choose Scoped access, and select a Team scoped access type rather than a user scoped one. On the app's Permissions tab, grant the team information, member, group, and session read scopes such as team_info.read, members.read, groups.read, and sessions.list. Then generate an access token on the Settings tab.
A user scoped token authenticates as one person and can't reach the team endpoints, so cnspec can't use it.
cnspec shell dropbox --token YOUR_TEAM_TOKENEnvironment variables
DROPBOX_TEAM_TOKEN supplies the token:
export DROPBOX_TEAM_TOKEN=YOUR_TEAM_TOKENWhen this is set, you can omit the --token flag from the commands below.
Connection options
| Option | Description |
|---|---|
--token | Dropbox Business team access token |
Verify with a quick Dropbox check
Confirm that cnspec can reach your team by opening a cnspec shell:
cnspec shell dropbox --token YOUR_TEAM_TOKENcnspec> dropbox.team { name numLicensedUsers numUsedLicenses }
dropbox.team: {
name: "Lunalectric"
numLicensedUsers: 250
numUsedLicenses: 187
}If cnspec connects and reports your team, you're ready to scan.
Scan Dropbox
cnspec scan dropbox --token YOUR_TEAM_TOKENThe team is a single asset. There are no child assets to discover.
When a scan completes, cnspec prints a summary of all the checks it ran, grouped by policy, along with a risk score from 0 (no risk) to 100 (highest risk). Failed checks include remediation guidance to help you fix issues. To learn more about reading scan results, read Understand cnspec Results.
Mondoo doesn't yet ship an out-of-the-box Dropbox policy, so use the checks below as a starting point and create your own policies to meet your specific requirements.
Explore and test checks interactively
Open a cnspec shell to discover resources and try out checks:
cnspec shell dropbox --token YOUR_TEAM_TOKENReview the team sharing settings
These two settings bound how far team content can travel:
cnspec> dropbox.team {
name
externalSharingAllowed
publicSharingAllowed
numLicensedUsers
numProvisionedUsers
numUsedLicenses
}List members, their role, and their status
cnspec> dropbox.members { email displayName role status membershipType emailVerified }Review the administrators
Dropbox roles differ in reach. A team_admin can change the sharing settings themselves:
cnspec> dropbox.members.where(role != "member_only") { email role status }Review the additional addresses tied to each account
A secondary email is another address that can receive account mail, so it's another way in:
cnspec> dropbox.members { email secondaryEmails joinedAt }Review the groups and how they're managed
managementType distinguishes a group an admin controls from one synced in from an identity provider:
cnspec> dropbox.groups { name memberCount managementType externalId }List linked devices and sessions
clientType separates a desktop client holding a local copy of team content from a web session that doesn't:
cnspec> dropbox.devices { hostName clientType platform clientVersion country lastActivity }Find sessions that have gone quiet
lastActivity is the last time the session was used, so a stale value is standing access nobody is watching:
cnspec> dropbox.devices { hostName clientType ipAddress country createdAt lastActivity }Review the third-party apps members have authorized
Each linked app holds standing access to that member's Dropbox content until someone unlinks it:
cnspec> dropbox.linkedApps { appName publisherName isAppFolder linked }Review which apps hold full access rather than folder scoped access
isAppFolder is the difference between an app that sees one folder and an app that sees everything:
cnspec> dropbox.linkedApps.where(isAppFolder == false) { appName publisherName publisherUrl }Walk from a member to what they've linked
Devices and apps both carry a memberId, and each member resolves its own:
cnspec> dropbox.members { email devices { hostName clientType } }
cnspec> dropbox.members { email linkedApps { appName isAppFolder } }Example security checks
Ensure the team doesn't allow public shared links
A public link is reachable by anyone who has the URL, with no account required:
cnspec> dropbox.team.publicSharingAllowed == false
[ok] value: trueEnsure shared folders stay inside the team
cnspec> dropbox.team.externalSharingAllowed == false
[ok] value: trueEnsure every member has verified their email address
An unverified address hasn't been proven to belong to the person using the account:
cnspec> dropbox.members.where(status == "active").all(emailVerified == true)
[ok] value: trueEnsure administrator roles stay rare
cnspec> dropbox.members.where(role == "team_admin").length <= 3
[ok] value: trueEnsure suspended members hold no linked devices
Suspending a member stops the sign-in. It doesn't remove the copy of team content already sitting on their laptop:
cnspec> dropbox.members.where(status == "suspended").all(devices.length == 0)
[ok] value: trueEnsure suspended members hold no linked apps
An authorized app keeps its token until someone unlinks it:
cnspec> dropbox.members.where(status == "suspended").all(linkedApps.length == 0)
[ok] value: trueEnsure invitations don't linger
An invitation that's never accepted is a license nobody watches:
cnspec> dropbox.members.none(status == "invited")
[ok] value: trueEnsure the team isn't over licensed
Unused licenses are seats available to anyone who can invite:
cnspec> dropbox.team.numUsedLicenses <= dropbox.team.numLicensedUsers
[ok] value: trueEnsure desktop clients support remote wipe
Without it, unlinking a lost device leaves the local copy of team content behind:
cnspec> dropbox.devices.where(clientType == "desktop").all(isDeleteOnUnlinkSupported == true)
[ok] value: trueEnsure third-party apps are scoped to their own folder
An app without isAppFolder reaches the member's whole Dropbox, not just the folder it created:
cnspec> dropbox.linkedApps.all(isAppFolder == true)
[ok] value: trueEnsure every linked app identifies its publisher
An app with no publisher name is one nobody can attribute during a review:
cnspec> dropbox.linkedApps.all(publisherName != "")
[ok] value: trueEnsure system managed groups come from one place
A system_managed group is synced from an identity provider, so mixing it with hand managed groups makes the source of access ambiguous:
cnspec> dropbox.groups.where(managementType == "system_managed").all(externalId != "")
[ok] value: trueReview members holding more than one role
cnspec> dropbox.members.where(role.contains(",")) { email role }Learn more
- Dropbox Resource Pack Reference: every Dropbox resource and field cnspec can query
- Write Effective MQL: guide to authoring checks and queries