Imagine deploying Snowflake with rigorous row-level security policies, confident that your European users can’t access American customer data, or your junior analysts are locked out of executive compensation figures. Now imagine discovering that any user with basic Python UDF creation privileges can bypass these protections entirely and exfiltrate restricted data through error messages. This isn’t theoretical, it’s happening right now in Snowflake deployments worldwide.
The Uncomfortable Reality: RLS Policies That Don’t Work
Snowflake’s row-level security (RLS) promises fine-grained data access control. In theory, you can create policies that restrict data access based on user attributes, roles, or data characteristics. The most common implementation looks something like this:
CREATE OR REPLACE ROW ACCESS POLICY amer_rls
AS (region STRING)
RETURNS BOOLEAN ->
CASE
WHEN CURRENT_ROLE() = 'AMER_ANALYST' AND region = 'AMER' THEN TRUE
ELSE FALSE
END;
This policy should ensure that users with the AMER_ANALYST role can only see records where the region is ‘AMER’. When running standard SQL queries against protected tables, this works exactly as expected. But the security model collapses when Python UDFs enter the picture.
The Python UDF Exploit: A Simple Bypass Mechanism
The vulnerability centers on how Snowflake handles Python UDF execution context. Here’s the exact exploit that’s causing concern:
CREATE OR REPLACE FUNCTION retrieve_restricted_data(value INT)
RETURNS BOOLEAN
LANGUAGE PYTHON
AS $
def check(value):
if value == 1234912434125:
raise ValueError('Restricted value: ' + str(value))
return True
$;
-- This query bypasses RLS entirely
SELECT account_name, region, number FROM accounts WHERE retrieve_restricted_data(account_number);
The result? A NotebookSqlException: 100357: Python Interpreter Error that reveals the supposedly restricted value: ValueError: Restricted value: 1234912434125.
What’s happening here defies security expectations: The Python UDF executes with access to the full row data, including columns protected by RLS policies, before those policies are applied. This creates a timing vulnerability where sensitive data can be extracted through error messages, return values, or other side channels.
Why This Matters: The Root Cause Analysis
The fundamental issue appears to be in Snowflake’s execution model for Python UDFs. When a UDF is called in a WHERE clause, Snowflake appears to:
- Execute the UDF against each row before applying RLS policies
- Pass the actual column values to the UDF, not policy-filtered values
- Maintain this behavior regardless of whether the UDF runs with CALLER or OWNER rights
This violates the principle of least privilege in a spectacular fashion. Users with minimal UDF creation privileges, often granted for legitimate data transformation tasks, can suddenly bypass carefully crafted security policies that should prevent them from even knowing restricted data exists.

The Snowflake Security Model: Where It Breaks Down
Snowflake’s security documentation emphasizes the importance of proper privilege management and recommends using EXECUTE AS CALLER to ensure procedures run with caller privileges. However, this vulnerability suggests a deeper architectural issue.
The problem extends beyond simple privilege escalation. Consider Snowflake’s extensive support for Snowpark API languages including Python, Java, and Scala. Each language integration introduces potential vectors for similar exploits if the underlying security context isn’t properly isolated.
Real-World Implications: More Than Just Error Messages
While the initial exploit uses error messages for data exfiltration, the implications run much deeper:
Data Enumeration: Attackers can systematically probe for the existence of specific records, even without reading the actual data.
Side-channel Attacks: UDFs could write to external systems, encode data in timing patterns, or use return values to leak information.
Privilege Escalation: Users with limited table access but UDF creation rights could elevate their effective permissions.
The community response has been telling, developers are questioning whether Snowflake is truly “enterprise ready” for security-sensitive workloads. This isn’t just about a coding bug, it’s about whether organizations can trust Snowflake’s fundamental security model for compliance frameworks like GDPR, HIPAA, or SOC 2.
Immediate Mitigation Strategies
While waiting for an official fix from Snowflake, security-conscious organizations should consider these immediate measures:
Restrict UDF Creation: Limit CREATE FUNCTION privileges to trusted administrative roles. Seriously evaluate whether general users need Python UDF capabilities at all.
-- Revoke UDF creation from standard users
REVOKE CREATE FUNCTION ON SCHEMA your_schema FROM ROLE standard_user;
Audit Existing UDFs: Scrutinize all Python UDFs in your environment, particularly those created by non-administrative users.
Implement Additional Controls: Consider using Snowflake’s exfiltration protection features and monitoring query patterns for suspicious UDF usage.
Layer Security: Don’t rely solely on RLS, implement additional application-level controls and data masking.

The Bigger Picture: Trust in Cloud Data Platforms
This vulnerability raises uncomfortable questions about security assumptions in modern data platforms. When organizations migrate sensitive data to cloud platforms like Snowflake, they’re placing tremendous trust in the platform’s security implementation. Discovering that fundamental access control mechanisms can be bypassed through standard features shakes that trust.
The security discussion highlights a tension between functionality and security. Snowflake’s powerful UDF system enables complex data transformations and machine learning workflows, but this flexibility comes at a security cost. Organizations must now weigh whether the benefits of Python UDFs outweigh the risks to their most sensitive data.
Looking Forward: What Snowflake Needs to Fix
The ideal resolution would involve Snowflake implementing one of several architectural changes:
Policy-Aware UDF Execution: Apply RLS policies before UDF execution, ensuring UDFs only see filtered data.
Security Context Isolation: Execute UDFs in a security context that respects RLS policies independently.
Enhanced Audit Controls: Provide better logging and monitoring specifically for UDF security violations.
Until these fundamental issues are addressed, organizations using Snowflake for sensitive data must treat RLS as a complementary control rather than a primary security boundary. The platform’s extensive support for multiple programming languages in stored procedures and UDFs means this vulnerability could manifest in various forms across different execution contexts.
The Bottom Line: Rethink Your Snowflake Security Strategy
The Python UDF bypass vulnerability isn’t just another security bug, it’s a fundamental challenge to Snowflake’s security model. Organizations that assumed RLS provided airtight data segmentation now face uncomfortable conversations about data governance, compliance, and risk management.
Until Snowflake addresses this architectural weakness, the safest approach is to assume that any user with UDF creation privileges can potentially bypass RLS policies. This means reevaluating privilege assignments, implementing defense-in-depth strategies, and potentially delaying sensitive workloads until the platform provides credible assurances that this class of vulnerability has been eliminated.
The window for exploiting this vulnerability may eventually close, but the lesson remains: in complex data platforms, never assume security controls work exactly as documented. Test them, challenge them, and always prepare for the possibility that your carefully constructed data protections might have unexpected gaps.




