Safeguard
Developer Tools•

How do you keep API keys out of Jupyter notebooks?

Read keys from the environment or a secret manager, never type them into cells, and scan before you commit. Steps to follow and what to do after a leak.

Safeguard Security Team
4 min read

Read keys from the environment or a secret manager at run time, never type them into a cell, and scan every notebook before it is committed or shared. A notebook is a document that stores code and output together, so a key that appears anywhere in it is saved with it.

Why notebooks leak more than scripts

Scripts live in a repository with review and hooks. Notebooks are often shared by email or chat, uploaded to hosted services, and committed with outputs. They also invite quick tests, and the quickest test is pasting a key into a cell. Sharing a hosted notebook shares text, code, output and comments, as covered in what gets shared when you share a Colab notebook.

Patterns, from worst to better

PatternProblem
Key typed in a code cellSaved in the file and in history
Key printed to check it loadedSaved in output
Key in a config file next to the notebookEasy to commit by accident
Key in an environment variableBetter, but visible to anything running in that process
Key from a secret manager, short livedBest option for shared work

Steps that work

  1. Use environment variables for local work. Set them in your shell or a local env file that is Git ignored, and read them in code with the standard library.
  2. Prompt when you must. For a one time key, use the standard library getpass function so the value is not echoed and not stored in the cell.
  3. Prefer short lived credentials. Use your cloud identity tooling so a leaked value expires.
  4. Never print the secret. Print a length or the last four characters at most, to confirm it loaded.
  5. Keep a Git ignore entry for env files, credential files and notebook checkpoints.
  6. Strip outputs before commit with a pre commit hook. See clean notebook outputs before you commit.
  7. Scan for secrets in pull requests and on a schedule across the whole repository.

A minimal code pattern:

import os
api_key = os.environ["SERVICE_API_KEY"]

If the variable is missing, the code fails with an error instead of using an empty or pasted value, which is what you want.

Least privilege for the key itself

Create a key just for the notebook, with the narrowest scope the work needs. Read only where possible, one project, an expiry date, and a spending limit if the service offers one. A separate key per person makes it possible to revoke one without breaking the team.

After a leak

  1. Revoke the key at the provider. Do this first.
  2. Create a new key and update the places that use it.
  3. Check the provider's usage logs for activity you do not recognise.
  4. Remove the key from the file, and clear history if you can, but do not rely on that for safety.
  5. Add the check that would have caught it.

Also see DVC remote credentials: what goes where.

Safeguard scanning and pull request gates can help catch secrets in repositories before merge. Try the free scan at gold.safeguard.sh/scan.

Try it yourself

Click through it at your own pace, or open it full screen. See how a check can stop a commit that should not merge.

Quick check

Is an environment variable secure enough?

It is better than a cell, but any code in the process can read it. Use short lived credentials for shared or untrusted code.

I deleted the key from the notebook. Is it safe?

No. Revoke it, since copies and history may remain.

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.