Snowflake's data sharing feature is one of the more operationally useful parts of the platform. Instead of exporting data to files and transferring them to a partner, you can share live read access to specific database objects with another Snowflake account. No data movement, no file management, and the recipient sees changes as they happen. For data providers sharing product analytics with customers, analytics teams sharing reporting tables with business units in separate Snowflake accounts, or organizations sharing aggregated data with partners, it is a significant workflow improvement over the alternative.
The security problem is the governance side of shares. Creating a share is straightforward. Reviewing which shares exist, what data they expose, and whether the recipients still have a legitimate need is a separate operational discipline that most teams don't have in place. Data shares have a way of outlasting the business relationship that created them.
How Snowflake data shares work
A brief technical overview for context. A Snowflake data share is an object in the provider account that contains grants to database objects (databases, schemas, tables, views, secure views). The provider creates the share, adds the desired objects to it, and grants the share to one or more consumer Snowflake accounts identified by account identifiers. The consumer creates a database from the share in their account, and users in the consumer account with appropriate privileges can query the shared objects as if they were local tables.
The data is not copied. Queries against the shared database execute against the provider's storage, with the provider's compute reading the data. The consumer's queries appear in the provider's query history. Access can be revoked by the provider at any time by removing the consumer's access from the share or by dropping the share entirely.
A few details matter for security analysis:
- Shares are granted to external Snowflake account identifiers, not to individual users. Everyone in the consumer account with access to the shared database can query it.
- The objects granted to a share can include entire schemas (all tables in the schema, including tables created after the share was configured).
- Secure views are the recommended method for sharing controlled subsets of data: the view definition is hidden from the consumer, so you can apply row-level or column-level filtering without exposing the underlying query logic.
- Non-secure views expose their definition to consumers, which may reveal information about the source tables or business logic.
The stale share problem
A data share becomes stale when the business relationship that justified it has changed, but the share hasn't been updated to reflect that change. The most common scenarios:
Vendor offboarding. A company works with a marketing analytics vendor that needs access to campaign performance data. A share is created, the vendor gets a Snowflake account to access the shared data, and the engagement runs for six months. The vendor contract ends. The share is not revoked because there is no process that connects vendor offboarding to data share review. Twelve months later, the former vendor's Snowflake account still has live access to the campaign performance tables.
Partner scope expansion. A share is created to give a partner access to a specific reporting view. Later, the underlying schema evolves: new tables are added, the view is replaced by a broader schema grant because it was simpler to maintain. The partner now has access to more data than the original share intended to provide, but nobody revisited the grant scope when the schema changed.
Business unit reorganization. Two business units in separate Snowflake accounts had a data sharing arrangement for joint reporting. After a reorganization, they operate in the same account, and the original share is no longer needed. The share continues to exist in both accounts, and the consumer account's database-from-share continues to be accessible to users who no longer have a business reason to see the data.
Schema-level grants with new tables. If a share grants access to an entire schema rather than specific tables, any table added to that schema is automatically included in the share. An analyst adds a new table to the shared schema without knowing it expands the external access footprint. Tables containing sensitive data added to a broadly-shared schema are shared immediately on creation.
Finding stale shares: a walkthrough
Snowflake provides the information needed to audit shares through system views and SQL commands. Here is the practical procedure.
Start by listing all outbound shares in your account:
SHOW SHARES;
This returns all shares, including inbound (shares you consume from others) and outbound (shares you provide). Filter on kind = 'OUTBOUND' for shares you own and control. For each outbound share, examine what's in it:
SHOW GRANTS TO SHARE share_name;
This lists the database objects granted to the share: databases, schemas, tables, views. Review each one. Ask: does the current scope match the original intent? Are there tables in a shared schema that should not be visible to the consumer?
Next, examine who the share is granted to:
SHOW GRANTS OF SHARE share_name;
This lists the consumer accounts. For each consumer account identifier, map it back to the business relationship. Is that account still active? Is the organization using it the same one that requested the share originally? For external consumers (partners, vendors, customers), this requires cross-referencing the account identifier against your vendor or partner records.
To assess whether a share is actively being used, query the SNOWFLAKE.ACCOUNT_USAGE.ACCESS_HISTORY view (requires Enterprise edition) filtering for queries against the shared objects from the consumer account. If no access has occurred in the past 60 to 90 days, that is a signal for review: either the share is not being used and can be revoked, or the business relationship needs to be confirmed as still active.
For organizations with many outbound shares, this is a meaningful amount of work to do manually on any regular cadence. The operational goal is to automate the query execution and surface findings: shares with no access in N days, shares granting schema-level access where new tables were added since the share was created, shares to consumer accounts not in your current partner registry.
The over-permissioned role problem inside Snowflake
Separate from shares, the internal role model in most Snowflake environments has its own accumulation problem. Snowflake's access model is role-based: users are granted roles, roles are granted privileges on database objects. Roles can be granted to other roles, creating inheritance hierarchies.
The common failure pattern: a set of base roles (read-only access to specific schemas, for example) is created carefully during the initial deployment. Over time, as new users join and need access, the path of least resistance is adding them to a broader role rather than provisioning the specific access they need. The SYSADMIN role ends up with more grantees than intended. The DATA_ANALYST role has SELECT on schemas it was never intended to cover because someone granted a new schema to it for one user's use case and never scoped it back.
Auditing Snowflake role grants is analogous to the share audit. Useful commands:
SHOW GRANTS TO ROLE role_name; -- what this role can do
SHOW GRANTS OF ROLE role_name; -- who/what has this role
SHOW ROLES; -- all roles in the account
For large environments, querying the SNOWFLAKE.ACCOUNT_USAGE.GRANTS_TO_ROLES and SNOWFLAKE.ACCOUNT_USAGE.GRANTS_TO_USERS views gives a comprehensive picture that can be joined against query history to identify roles that are granted but never exercised.
Integrating Snowflake into your DSPM posture
For DSPM purposes, Snowflake exposure analysis combines three layers: what data is in which tables (classification), which roles and external shares can reach those tables (access graph), and whether that access is active or dormant (usage recency).
The classification layer requires sampling table contents to identify sensitive data types. For large fact tables, full column scans are expensive; statistical sampling of a representative row set is sufficient for classification purposes. Metadata approaches (column name matching against known PII field name patterns) are faster but have higher false negative rates. For a security posture baseline, combining both gives reasonable coverage.
The access graph layer requires pulling role grants, user role assignments, and outbound share definitions and building the reachability graph. This is deterministic given the Snowflake metadata views. The output is a set of paths from external actors (including external share consumer accounts) to sensitive table objects.
The usage recency layer requires ACCESS_HISTORY queries, which are available in Enterprise and Business Critical editions. If your Snowflake account tier doesn't include ACCESS_HISTORY, query history at the schema level provides a coarser approximation.
When PostQKey connects to a Snowflake environment, we build this three-layer view and surface findings by risk tier: tables classified as highly sensitive with external share access are top priority, regardless of recent usage, because the access path exists and the data is real. Tables with dormant role grants from internal users are lower urgency but still worth review on a regular cadence.
The operational goal is not a zero-share policy. Data sharing is a legitimate and useful Snowflake feature. The goal is that every share in your environment has a documented business justification, a defined owner responsible for periodic review, and a revocation procedure tied to partner/vendor lifecycle events. Without that governance layer, shares accumulate, and the access footprint of your Snowflake environment expands past the point where anyone can reason confidently about who can reach what.