Safeguard
Developer Tools•

Clean notebook outputs before you commit: data and secrets in .ipynb

Notebook files store cell outputs, including data samples and tokens. How to strip them automatically so they never reach the repository.

Safeguard Security Team
3 min read

A notebook file stores each cell's output next to its code, so a displayed dataframe, a stack trace or a printed token is saved in the file and committed with it. Strip outputs automatically before commit, and treat any notebook already pushed with outputs as potentially containing data.

What ends up in the file

A notebook is a JSON document. Alongside source it holds outputs: tables, charts as embedded images, error messages and printed text. Common leaks:

  • The head of a customer table shown with a quick preview call.
  • A connection error that prints a full URL with credentials in it.
  • A chart image whose labels contain names or account numbers.
  • Environment details in a traceback, such as usernames and file paths.

None of that is visible in a code review that only looks at the code cells, and diffs of the raw JSON are unreadable, so reviewers skim.

Strip outputs by default

Pick one of these approaches and make it the team standard.

  1. A pre-commit hook that runs an output stripping tool on staged notebooks and fails the commit if outputs are present.
  2. A CI check that rejects any pull request containing notebooks with non empty outputs.
  3. A convention of keeping exploration in untracked folders and committing only cleaned notebooks or plain scripts.

CI is the one to insist on, because hooks live on individual machines and can be skipped.

Keep the useful outputs on purpose

Sometimes a notebook is documentation, and a chart is the point. In that case, generate the chart from synthetic or aggregated data, review the output like any published artifact, and keep a short note stating the data source and sensitivity. Do not commit raw record level outputs.

If a notebook already went out

  1. Remove the outputs and commit, then understand that history still has them.
  2. Assess what the outputs contained. If it was personal data or a credential, rotate the credential and follow your incident process for the data.
  3. Rewrite history only if your process allows it, and remember clones and forks keep the old content.
  4. Add the CI check so it cannot happen again.

Trust and rendering

Jupyter's documentation says untrusted HTML and JavaScript in notebook outputs are sanitized and never executed unless the notebook's signature matches your signatures database. That is a defence against hostile notebooks. It does nothing about your own notebooks leaking data. See our checklist for hardening a Jupyter server.

Beyond the file

Rendered notebooks on shared drives, in wikis and in email attachments are copies too. Decide where finished notebooks live and delete the stragglers.

Where Safeguard fits

Safeguard can apply policies and gates to pull requests and scan repositories, including notebook dependencies. For a quick look at a repository, use the free scan at https://gold.safeguard.sh/scan.

Quick check

Does a code review of the cells catch leaked outputs?

Often not. Outputs sit in the JSON beside the code and reviewers rarely read them, so enforce stripping in CI.

Does deleting outputs in a new commit remove the leak?

No. The earlier commit still has them, so assess and rotate anything sensitive.

Sources

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.