CertSafari
    Snowflake SnowPro Advanced: Security Engineer (SEA-C01)· Lessons

    Domain 2 · Lesson 5/21

    Projection, aggregation and differential privacy policies in Snowflake

    Implement data security features.

    9 min read
    4.29% of exam
    8 sources
    Published 5 Oct 2026
    Docs as of 4 Oct 2026

    What you will be able to do

    • Write projection policies with PROJECTION_CONSTRAINT and explain what they do not prevent
    • Create aggregation policies with a minimum group size and entity keys, and predict which queries they reject
    • Protect a table with a differential privacy policy and manage its privacy budgets

    1.Projection policies: usable but not displayable

    A projection policy is a schema-level object that decides whether a column can appear in a query's final output. A column can have only one. The signature takes no arguments and returns PROJECTION_CONSTRAINT. The body, which can include CASE expressions and context functions, returns PROJECTION_CONSTRAINT(ALLOW => true|false). It must never return NULL to block projection. A policy administrator creates the policy, for example from a proj_policy_admin role holding CREATE PROJECTION POLICY on the schema and APPLY PROJECTION POLICY on the account, then assigns it with ALTER TABLE ... MODIFY COLUMN ... SET PROJECTION POLICY.

    Checkpoint 1 of 5· Fill the gap

    Complete the return type of this projection policy.

    CREATE OR REPLACE PROJECTION POLICY mypolicy AS () RETURNS  ?  -> PROJECTION_CONSTRAINT(ALLOW => false);

    That flexibility is the whole design, and also its weakness. A blocked column can't be output, inserted into another table, or passed to an external function or stored procedure. But users can still target an individual with a filter. If they join the protected column to the same value in an unprotected table, they can project the value from that table. Snowflake tracks lineage through views, UDFs and CTEs, so a column derived from a constrained column stays blocked. Projection policies suit partners you already trust. To prevent leakage completely, drop the column or use differential privacy.

    When a table carries all three policy types, Snowflake applies the row access policy's filters first, then checks projection constraints, then applies column masks.

    Sources1

    2.Aggregation policies: answers only in groups

    An aggregation policy forces queries to return groups rather than individual rows. Its body can't reference UDFs, tables or views. It returns NO_AGGREGATION_CONSTRAINT() for unrestricted access, or AGGREGATION_CONSTRAINT(MIN_GROUP_SIZE => n) to set the smallest group a query may return. With MIN_GROUP_SIZE 1, every group must include at least one row from the protected table. With 0, an outer join can return groups made entirely of rows from another table. Groups that are too small are folded into a remainder group.

    ADMIN is exempt; every other role must aggregate into groups of at least 5sql
    CREATE AGGREGATION POLICY my_agg_policy AS () RETURNS AGGREGATION_CONSTRAINT -> CASE WHEN CURRENT_ROLE() = 'ADMIN' THEN NO_AGGREGATION_CONSTRAINT() ELSE AGGREGATION_CONSTRAINT(MIN_GROUP_SIZE => 5) END;

    By default the policy counts records, so one person with many rows could fill a group alone. An entity key, defined when you assign the policy, changes the minimum group size to count distinct entities. Entity keys are additive.

    Roles that aren't exempt must follow these query rules:

    - Allowed aggregates are AVG, COUNT [DISTINCT], HLL and SUM. Any other aggregate, such as MIN or MAX, fails. - Grouping must use a plain GROUP BY or a scalar aggregate. ROLLUP, CUBE and GROUPING SETS are rejected. - Window functions, recursive CTEs, and most set operators are rejected. UNION ALL is the exception, and each group must still meet every protected table's minimum. - Correlated subqueries or lateral joins that reference the aggregating part of the query are rejected. - External functions are rejected unless another part of the query has already aggregated.

    In a join, each group must take enough rows from each constrained table. Masking runs before aggregation; projection runs after it. External tables can't carry an aggregation policy.

    Assigning the policy with an entity keysql
    ALTER TABLE viewership_log
      SET AGGREGATION POLICY my_agg_policy
      ENTITY KEY (first_name,last_name);

    Checkpoint 2 of 5· Check yourself

    A non-exempt role queries an aggregation-constrained salaries table. Which query is rejected?

    Checkpoint 3 of 5· Exam question

    During a ransomware tabletop drill, a security engineer revokes Snowflake's access to the customer-managed AWS KMS key behind the account's Tri-Secret Secure configuration and leaves it revoked. What happens to the account?

    Sources234

    3.Differential privacy policies and privacy budgets

    Aggregation policies can be worn down by repeated queries. Differential privacy adds noise to results and caps the total privacy loss. A privacy policy has the signature AS () RETURNS PRIVACY_BUDGET. The body returns PRIVACY_BUDGET(BUDGET_NAME => ...) or NO_PRIVACY_POLICY(), never NULL, and it can branch on context functions such as CURRENT_USER, CURRENT_ROLE or CURRENT_ACCOUNT.

    Setup takes three steps. Create the policy. Assign it with ALTER TABLE ... ADD PRIVACY POLICY, usually with an ENTITY KEY; a table has at most one privacy policy. Only then grant SELECT, because granting earlier would give analysts full access. Users tied to a budget can't run non-aggregated SELECTs, and they get noisy results. Exempt users get exact results, and Snowflake doesn't track their loss.

    Conditional privacy policy: ADMIN is unrestricted, everyone else draws on the analysts budgetsql
    CREATE PRIVACY POLICY my_priv_policy AS () RETURNS PRIVACY_BUDGET -> CASE WHEN CURRENT_USER() = 'ADMIN' THEN NO_PRIVACY_POLICY() ELSE PRIVACY_BUDGET(BUDGET_NAME => 'analysts') END;

    Naming a budget in the policy body creates it. Budgets are namespaced to their policy and then to each consumer account, so every account's cumulative loss is tracked separately. Each successful query adds its loss to that total. A query that would exceed the limit fails until the budget refreshes. Managing a budget requires OWNERSHIP of the policy. To reduce noise before you touch the budget, narrow the privacy domain on the protected columns.

    Privacy budget controls and tools
    ControlEffect
    BUDGET_LIMITLimit on cumulative privacy loss; sets how many queries an analyst can run
    MAX_BUDGET_PER_AGGREGATEMaximum loss each aggregate (not each query) can incur; sets the noise per aggregate
    BUDGET_WINDOWHow often cumulative loss resets to 0; default weekly
    RESET_PRIVACY_BUDGETZeroes one account's loss, but only when the next query incurs loss
    PRIVACY_BUDGETS / CUMULATIVE_PRIVACY_LOSSESAccount Usage view of all budgets, or real-time losses for one policy
    Adjusting budget controls: restate every parameter you want to keepsql
    ALTER PRIVACY POLICY users_policy SET BODY ->
      PRIVACY_BUDGET(BUDGET_NAME=>'analysts',
      BUDGET_LIMIT=>300,
      MAX_BUDGET_PER_AGGREGATE=>0.1);

    Checkpoint 4 of 5· Check yourself

    An analyst's next differentially private query would push cumulative privacy loss past BUDGET_LIMIT. What happens?

    Checkpoint 5 of 5· Exam question

    Which statements about Tri-Secret Secure are correct? Select all that apply.(Select 3)

    Sources5678

    Exam traps

    Each one states something that sounds right. Open it to see what is actually true.

    1. 1.ALTER PRIVACY POLICY ... SET BODY changes only the budget parameters you name and keeps the others.Why is that wrong?

      Any of BUDGET_LIMIT, MAX_BUDGET_PER_AGGREGATE or BUDGET_WINDOW left out of the statement reverts to its default.

      Covered in Differential privacy policies and privacy budgets

    2. 2.Any aggregate function satisfies an aggregation policy, so MIN and MAX are fine.Why is that wrong?

      Only the listed aggregates are permitted. Any other aggregate makes the query fail.

      Covered in Aggregation policies: answers only in groups

    3. 3.Without an entity key, an aggregation policy protects each person even when they have many rows.Why is that wrong?

      Without an entity key, the policy protects individual records, so several rows from one entity can fill a group.

      Covered in Aggregation policies: answers only in groups

    Sources

    Every claim above is drawn from one of these pages, quoted as it was written on the date shown.

    1. 1.
      “A projection policy is a first-class, schema-level object that defines whether a column can be projected in the output of a SQL query result.”
      ↩︎ Projection policies: usable but not displayable
      “Do not return NULL to disallow projection.”
      ↩︎ Projection policies: usable but not displayable
      “you should omit the column entirely from your data, or employ differential privacy.”
      ↩︎ Projection policies: usable but not displayable
      “Apply row filters according to the row access policy.”
      ↩︎ Projection policies: usable but not displayable
      “columns that are hidden by projection policies can still be used in inner queries or in WHERE clauses”
      ↩︎ Prediction
    2. 2.
      “Use the MIN_GROUP_SIZE argument to specify how many rows or entities must be included in each aggregation group.”
      ↩︎ Aggregation policies: answers only in groups
      “The query cannot use related constructs like GROUP BY ROLLUP, GROUP BY CUBE, or GROUP BY GROUPING SETS.”
      ↩︎ Aggregation policies: answers only in groups
      “Window functions are not allowed in queries against an aggregation-constrained table or view.”
      ↩︎ Aggregation policies: answers only in groups
      “A query fails if it attempts to use an aggregation function that is not allowed.”
      ↩︎ Exam trap 2
      “Aggregation policies protect data for an individual record, not an entity.”
      ↩︎ Exam trap 3
      “The following aggregation functions are allowed in a query against an aggregation-constrained table: AVG COUNT [DISTINCT] HLL SUM”
      ↩︎ Checkpoint
    3. 3.
      “the minimum group size changes from a requirement on the number of records in a group to the number of entities in a group.”
      ↩︎ Aggregation policies: answers only in groups
      “Masking policies are enforced before aggregation policies.”
      ↩︎ Aggregation policies: answers only in groups
    4. 4.
      “Passing a 0 allows the query to return groups that consist entirely of records from another table.”
      ↩︎ Aggregation policies: answers only in groups
    5. 5.
      “If the query is executed successfully, Snowflake adds the privacy loss incurred by the query to the cumulative privacy loss for the user”
      ↩︎ Differential privacy policies and privacy budgets
      “because the analyst would have full access to the data.”
      ↩︎ Differential privacy policies and privacy budgets
    6. 6.
      “A privacy budget is created automatically when you define a privacy budget name in the body of the privacy policy.”
      ↩︎ Differential privacy policies and privacy budgets
      “The default budget window is weekly.”
      ↩︎ Differential privacy policies and privacy budgets
      “any parameter not specified in your ALTER PRIVACY POLICY command reverts back to its default value.”
      ↩︎ Exam trap 1
      “When a query would cause the cumulative privacy loss to exceed the privacy budget limit, the query fails until the privacy budget refreshes.”
      ↩︎ Checkpoint
    7. 8.
      “To indicate no privacy policy, you must return no_privacy_policy() rather than returning NULL.”
      ↩︎ Differential privacy policies and privacy budgets

    Ready to test yourself?

    Practise the 15 questions on this subdomain.

    Spotted a mistake, or was something unclear? Tell us.