What you will be able to do
- Identify the three kinds of destination that COPY INTO <location> can write to, and the exfiltration risk each one carries
- Use PREVENT_UNLOAD_TO_INLINE_URL and PREVENT_UNLOAD_TO_INTERNAL_STAGES at the account or user level to block ad hoc and internal-stage unloads
- Use REQUIRE_STORAGE_INTEGRATION_FOR_STAGE_CREATION and REQUIRE_STORAGE_INTEGRATION_FOR_STAGE_OPERATION so that external writes only reach the locations a storage integration allows
Key concept
Unload destination control — Snowflake writes data out programmatically with COPY INTO <location>. To restrict exfiltration, you use parameters to narrow which of its destinations a statement may use: inline cloud URLs, internal stages, or external stages that carry their own credentials.
1.Three places COPY INTO <location> can write
Every programmatic write out of Snowflake goes through COPY INTO <location>. It can target three kinds of destination. The first is a named internal stage, or a table or user stage. Files written there can then be downloaded with the GET command. The second is a named external stage that points at Amazon S3, Google Cloud Storage or Microsoft Azure. The third is an external location: a cloud storage URL written directly into the statement.
The third form is the ad hoc one. The documentation describes it as a good fit when you aren't planning regular unloads with the same table and bucket. The statement itself names the bucket and says how to authenticate. For S3, the syntax accepts either STORAGE_INTEGRATION = <integration_name> or a CREDENTIALS clause with AWS_KEY_ID and AWS_SECRET_KEY.
COPY INTO 's3://mybucket/unload/' FROM mytable STORAGE_INTEGRATION = s3_int;From a security point of view, each destination is a separate exfiltration channel. An inline URL lets anyone who has credentials for a bucket write table data into that bucket, and no administrator-controlled object stands in the way. An internal stage keeps the files inside Snowflake, but GET can then move them to a local machine. An external stage is only as safe as the credentials and the URL stored in its definition. The rest of this page covers the parameter that controls each channel.
Checkpoint 1 of 6· Check yourself
Which destination type lets a single COPY statement name a bucket URL and its access credentials directly, without any stage object?
An external location is a cloud storage URL written into the COPY statement, along with a storage integration or credentials. Named stages keep the URL in a separate object.
“You must specify the URI for the S3 bucket and the storage integration or credentials for accessing the bucket in the COPY command.”Source: docs.snowflake.com
2.Closing inline URLs and internal stages
Two Boolean parameters close the first two channels. Both default to FALSE, so both channels are open until you change them.
**PREVENT_UNLOAD_TO_INLINE_URL** blocks ad hoc unloads to external cloud storage, meaning statements that put the URL and access settings inline. When it is TRUE, COPY INTO <location> must reference a named internal or external stage, or a user or table stage. A named external stage must store the URL and access settings in its own definition. Unloading to cloud storage is still possible. It just has to go through a stage object that someone created and can audit.
**PREVENT_UNLOAD_TO_INTERNAL_STAGES** blocks unloads into user stages, table stages and named internal stages. It shuts the route where data is unloaded into a stage and then pulled down with GET:
COPY INTO @~/unload/ from mytable FILE_FORMAT = (FORMAT_NAME = 'my_csv_unload_format' COMPRESSION = NONE);While it is FALSE, only the usual rules for each stage type apply. Users can unload only to their own user stage. They can unload to a table stage only when their active role owns the table, and to a named internal stage only when their role has WRITE on it.
The two parameters are set at the same levels. Both can be set at the account level and overridden for an individual user (Account » User). Both appear in the objectParams of ALTER USER. So you can set a strict account-wide default and exempt one service user, or leave the account open and lock down specific people.
| Parameter | Can be set for | Default | Effect when TRUE |
|---|---|---|---|
| PREVENT_UNLOAD_TO_INLINE_URL | Account » User | FALSE | COPY INTO <location> must reference a named or user/table stage; no inline URL |
| PREVENT_UNLOAD_TO_INTERNAL_STAGES | Account » User | FALSE | No unloads to user, table or named internal stages |
| REQUIRE_STORAGE_INTEGRATION_FOR_STAGE_CREATION | Account only | FALSE | CREATE STAGE for a private location must reference a storage integration |
| REQUIRE_STORAGE_INTEGRATION_FOR_STAGE_OPERATION | Account only | (see Parameters reference) | Loads and unloads to private storage must use a named external stage with a storage integration |
Checkpoint 2 of 6· Check yourself
With PREVENT_UNLOAD_TO_INLINE_URL = TRUE, which statement can still unload data to S3?
The parameter removes only the inline URL form. A named external stage that stores its own URL and access settings is still allowed.
“A named external stage must store the cloud storage URL and access settings in its definition.”Source: docs.snowflake.com
Checkpoint 3 of 6· Exam question
Developers in a Snowflake account on AWS can run `COPY INTO 's3://partner-bucket/out/' FROM sales CREDENTIALS=(AWS_KEY_ID='...' AWS_SECRET_KEY='...')` and send data to any bucket they hold keys for. The security engineer wants to block this pattern account-wide while still allowing unloads through approved named external stages. Which action achieves this?
Correct answer: B — Run `ALTER ACCOUNT SET PREVENT_UNLOAD_TO_INLINE_URL = TRUE` so COPY INTO <location> rejects a bucket URL typed directly in the statement
- A. This parameter only governs unloads into internal stages. A bucket URL typed straight into COPY INTO <location> is an external write and is untouched by it.
- B. Correct. The parameter rejects unloads whose destination is an inline URL, so only named stages remain usable as unload targets, which is exactly the pattern the team wants to keep.
- C. This governs CREATE STAGE statements. The statement in the scenario creates no stage at all, so the inline unload still runs.
- D. Allowed locations constrain stages that use the integration. They have no effect on an inline URL with embedded keys, which never references the integration.
3.Forcing external stages through storage integrations
Turning off inline URLs moves external writes onto named stages. A named stage can still hold raw cloud keys, though. Two account parameters remove that option.
**REQUIRE_STORAGE_INTEGRATION_FOR_STAGE_CREATION** applies when a stage is created. If it is TRUE, CREATE STAGE for a private cloud storage location must reference a storage integration object as its cloud credentials. If it is FALSE (the default), a stage can use explicit provider credentials such as secret keys or access tokens.
**REQUIRE_STORAGE_INTEGRATION_FOR_STAGE_OPERATION** applies when a stage is used. If it is TRUE, loading from or unloading to a private cloud storage location must go through a named external stage that references a storage integration. A stage built on explicit credentials raises a user error. The creation parameter only stops new credential-based stages. The operation parameter also makes existing credential-based stages fail when they are used, so expect breakage when you turn it on in an established account.
Unlike the two PREVENT parameters, both REQUIRE parameters are account-only. You can't exempt an individual user.
Checkpoint 4 of 6· Match them up
Match each parameter to the moment it is enforced
Tap a term, then the definition that fits it.
The creation parameter checks stage definitions, and the operation parameter checks every load or unload that uses a stage. The PREVENT parameters check the target of the COPY statement.
“Specifies whether to require using a named external stage that references a storage integration object as cloud credentials”Source: docs.snowflake.com
Checkpoint 5 of 6· Exam question
A platform team uses Terraform to create external stages. Auditors found several stages defined with `CREDENTIALS=(AWS_KEY_ID=... AWS_SECRET_KEY=...)` that point at buckets outside the company. The team wants Snowflake to reject any new external stage that does not name a storage integration, without affecting internal stages. What should the ACCOUNTADMIN configure?
Correct answer: D — Set `REQUIRE_STORAGE_INTEGRATION_FOR_STAGE_CREATION = TRUE` at account level so external CREATE STAGE must name a `STORAGE_INTEGRATION`
- A. That parameter targets COPY INTO <location> statements that carry a URL. It does not evaluate CREATE STAGE definitions, so the keyed stages could still be created.
- B. This parameter blocks unloads to internal stages. It neither inspects how external stages are defined nor requires an integration.
- C. This is a manual process control rather than a Snowflake parameter. It does not make Snowflake reject keyed stages, and it removes automation without enforcing anything.
- D. Correct. With this account parameter set, Snowflake refuses to create an external stage unless it names a storage integration, while internal stages are unaffected.
Sources3
4.Storage integrations decide which buckets are reachable
Requiring storage integrations restricts *where* data can go, not only *how* it authenticates. A storage integration stores a generated IAM entity for your external cloud storage. It also stores an optional list of allowed or blocked locations. Cloud administrators grant that entity access to specific storage, and users no longer supply credentials when they create stages or unload data.
The destination limit comes from STORAGE_ALLOWED_LOCATIONS. It restricts the external stages that use the integration to the buckets, containers and optional paths you list. Each stage's URL must fall within one of those locations. STORAGE_BLOCKED_LOCATIONS can exclude locations explicitly. Watch for the * wildcard: STORAGE_ALLOWED_LOCATIONS accepts it and treats it as "allow access to all buckets and/or paths", which removes the restriction completely.
The integration also works as a kill switch. With ENABLED = FALSE, no new stages can reference it, and existing stages that use it lose access to their storage location.
One limitation affects planning. Storage integrations can reach cloud storage in a government region only from a Snowflake account in that same government region, and the same applies to regions in China. In those cases the documentation points you to the CREDENTIALS parameter in CREATE STAGE instead.
Checkpoint 6 of 6· Fill the gap
Which clause makes this ad hoc unload authenticate through an administrator-defined integration instead of raw keys?
COPY INTO 's3://mybucket/unload/' FROM mytable ? = s3_int;STORAGE_INTEGRATION refers to the integration object, which can only reach locations listed in its STORAGE_ALLOWED_LOCATIONS.
Source: docs.snowflake.comSources5
Exam traps
Each one states something that sounds right. Open it to see what is actually true.
1.PREVENT_UNLOAD_TO_INTERNAL_STAGES still lets users unload to their own user stage.Why is that wrong?
When TRUE, it blocks unloads to every internal stage type, including user stages and table stages.
Covered in Closing inline URLs and internal stages
2.PREVENT_UNLOAD_TO_INLINE_URL = TRUE stops all unloading to external cloud storage.Why is that wrong?
It only removes the inline URL form. Unloads through a named external stage that stores its URL and access settings are still allowed.
Covered in Closing inline URLs and internal stages
3.Only newly created stages are affected by requiring storage integrations, so existing credential-based stages keep working.Why is that wrong?
REQUIRE_STORAGE_INTEGRATION_FOR_STAGE_OPERATION is checked when a stage is used. Loads or unloads through an existing stage with explicit credentials produce a user error.
Covered in Forcing external stages through storage integrations
Sources
Every claim above is drawn from one of these pages, quoted as it was written on the date shown.
- 1.
“Named internal stage (or table/user stage). The files can then be downloaded from the stage/location using the GET command.”
↩︎ Three places COPY INTO <location> can write“Unloads data from a table (or query) into one or more files in one of the following locations:”
↩︎ Key concept - 2.
“This option works well for ad hoc unloading, when you aren’t planning regular data unloading with the same table and bucket parameters.”
↩︎ Three places COPY INTO <location> can write“You must specify the URI for the S3 bucket and the storage integration or credentials for accessing the bucket in the COPY command.”
↩︎ Checkpoint - 3.
“Specifies whether to prevent ad hoc data unload operations to external cloud storage locations”
↩︎ Closing inline URLs and internal stages“Users can only unload data to named internal stages when their active role has the WRITE privilege on the stage.”
↩︎ Closing inline URLs and internal stages“TRUE: Creating an external stage to access a private cloud storage location requires referencing a storage integration object as cloud credentials.”
↩︎ Forcing external stages through storage integrations“Account — Can be set only for Account”
↩︎ Forcing external stages through storage integrations“Unloading data from Snowflake tables to any internal stage, including user stages, table stages, or named internal stages is prevented.”
↩︎ Exam trap 1“TRUE: COPY INTO <location> statements must reference either a named internal (Snowflake) or external stage or an internal user or table stage.”
↩︎ Exam trap 2“specifying a named external stage that references explicit cloud provider credentials, such as secret keys or access tokens, produces a user error.”
↩︎ Exam trap 3“Unloading data from Snowflake tables to any internal stage, including user stages, table stages, or named internal stages is prevented.”
↩︎ Prediction“A named external stage must store the cloud storage URL and access settings in its definition.”
↩︎ Checkpoint“Specifies whether to require using a named external stage that references a storage integration object as cloud credentials”
↩︎ Checkpoint - 4.
“PREVENT_UNLOAD_TO_INLINE_URL = TRUE | FALSE PREVENT_UNLOAD_TO_INTERNAL_STAGES = TRUE | FALSE”
↩︎ Closing inline URLs and internal stages - 5.
“The URL in the stage definition must align with the storage location specified for the STORAGE_ALLOWED_LOCATIONS parameter.”
↩︎ Storage integrations decide which buckets are reachable“Explicitly limits external stages that use the integration to reference one or more storage locations”
↩︎ Storage integrations decide which buckets are reachable“Existing stages that reference this integration cannot access the storage location in the stage definition.”
↩︎ Storage integrations decide which buckets are reachable