Skip to main content

A lightweight framework for safely enabling LLMs to analyze pandas/Polars data without exposing raw data or blindly executing generated code.

Project description

safedata-guard

CI PyPI Python versions License: MIT

A safety layer for asking AI questions over sensitive tabular data.

safedata-guard scans your DataFrame, removes unnecessary sensitive fields, executes the analysis through a safe engine (the model returns a validated JSON plan, not raw Python), and returns an answer with an audit receipt.

Status: beta. A safety layer, not a compliance guarantee. It reduces the exposure of sensitive data; it does not certify GDPR/HIPAA/PCI compliance and cannot promise nothing will ever leak. PII detection and code screening are best-effort heuristics. See SECURITY.md.

30-second example

import safedata as sd

def my_model(prompt):            # plug in any LLM (callable, or an object with .generate)
    ...                          # returns the model's text reply

result = sd.ask(df, "What is total revenue by region?",
                model=my_model, profile="banking")

print(result.answer)             # safe, aggregated answer
print(result.receipt.summary())  # audit trail: PII dropped, no Python run, ...

Why this exists

Many simple "chat with your data" workflows send rich table context to the model or execute model-generated Python. Without careful controls, that can expose sensitive data or run unsafe code. In a measured benchmark (gpt-4o-mini, 6 synthetic datasets, 48 attack prompts), plain LLM-generated code leaked real PII on ~85% of attacks, while SafePlan showed 0 literal name/email leaks in this benchmark (see BENCHMARKS.md for the full method and limitations). safedata-guard's default engine never runs generated Python: the model returns a restricted JSON analysis plan that the library validates and executes itself, with privacy rules applied.

How it works

       your DataFrame
             |
        sd.scan()            assess risk (PII, sensitive categories, quality)
             |
        sd.protect()         drop un-needed PII / sensitive / business-id columns
             |
   schema + synthetic sample only  ->  LLM returns a JSON plan (no raw rows)
             |
     validate the plan                 (allow-list, k-anonymity, caps)
             |
   execute it locally (no generated Python)
             |
       answer + audit Receipt

The four doors

You want to... Use
Ask a question safely sd.ask(df, question, model, profile)
Assess a dataset's risk sd.scan(df, profile)
Get a privacy-filtered view sd.protect(df, question, profile)
Reuse a configured setup sd.Guard(profile, model)

The everyday API is intentionally small (sd.Policy controls the behaviour). Power-user tools live under sd.advanced.*.

Ask safely

result = sd.ask(df, "average balance by region", model=my_model, profile="banking")
print(result.answer)             # None if blocked; check result.ok / result.blocked
print(result.warnings)           # e.g. "all groups suppressed by k-anonymity"

ask uses the SafePlan engine by default. Guarded Python is only used when the policy allows it (regulated profiles disable it). mode= can force plan, summary (explain risk, no data execution), or python.

Scan data risk

report = sd.scan(df, profile="banking")
print(report.risk_level)                    # low | medium | high
print(report.pii_columns)                   # e.g. ["full_name", "email"]
print(report.business_identifier_columns)   # e.g. ["account_number", "sort_code"]
print(report.financial_columns, report.health_columns, report.free_text_columns)
print(report.quality_issues, report.recommendations)

Protect data before AI

safe_df = sd.protect(df, question="average balance by region", profile="banking")
# unneeded PII / sensitive identifiers dropped; analytical columns kept.
safe_df, report = sd.protect(df, question="...", profile="banking",
                             return_report=True)

Reuse settings with Guard

guard = sd.Guard(profile="banking", model=my_model)
guard.ask(df, "average balance by region")
guard.scan(df)
guard.protect(df, question="average balance by region")
session = guard.session(df)                 # multi-turn, privacy-budgeted

Industry profiles

profile= (or sd.Policy.from_profile(name)) picks safe defaults:

Profile min group size Python fallback Notes
general none allowed non-regulated data
energy 5 disabled SafePlan only
banking 10 disabled SafePlan only
insurance 10 disabled SafePlan only
healthcare 15 disabled smallest result caps
strict 20 disabled strongest defaults; Docker/Presidio when installed and configured

Override any field: sd.Policy.banking(min_group_size=25).

Audit receipts

Every sd.ask() returns a Result carrying a Receipt:

r = result.receipt
print(r.audit_id, r.profile, r.engine, r.mode)
print(r.pii_columns, r.dropped_columns, r.min_group_size)
print(r.python_fallback_used, r.raw_rows_exposed, r.warnings)
print(r.summary())              # human-readable; r.to_dict() for JSON

Advanced tools

The everyday API stays small; power-user tools are one level deeper under sd.advanced:

sd.advanced.leak_test(df, model=my_model)        # privacy red-team score
sd.advanced.create_shadowframe(df)               # synthetic same-shape stand-in
sd.advanced.run_safely(code, df)                 # guarded Python on a copy
sd.advanced.SafeSession(df, model=my_model)      # differencing/budget guard
sd.advanced.safe_query(df, q, model=my_model)    # low-level SafePlan call
sd.advanced.safe_answer(df, q, model=my_model)   # guarded-Python answer (dict)
sd.advanced.summarize(df)                         # quality-aware text summary
sd.advanced.token_stats(df)                       # token-saving estimate
sd.advanced.to_pandera_schema(df)                 # Pandera / Great Expectations
sd.advanced.redact_text("call +44 ...")          # best-effort PII masking

ShadowFrame creates a schema-compatible synthetic stand-in; it is not a formal anonymization guarantee. Most low-level and advanced tools from earlier versions are available under sd.advanced (run dir(sd.advanced) to see them) - the top level just stays small.

Upgrading from v1.x

Version 2.0.0 is a redesign with a smaller public surface and includes breaking changes. Some v1.x top-level imports and usage patterns no longer work the same way - old tools now power the new high-level API or live under sd.advanced (e.g. sd.advanced.safe_query, sd.advanced.safe_answer, sd.advanced.summarize, sd.advanced.run_safely).

See MIGRATION.md for the full mapping and examples. To stay on v1 for now: pip install "safedata-guard<2".

Install

pip install safedata-guard
pip install "safedata-guard[openai]"     # OpenAI support for the CLI's --model openai
pip install "safedata-guard[polars]"     # optional Polars support
pip install "safedata-guard[presidio]"   # optional international PII detection

CLI

safedata scan data.csv --profile banking
safedata protect data.csv --profile banking --question "revenue by region" --out safe.csv
safedata ask data.csv "revenue by region" --profile banking --model openai
safedata advanced inspect-policy banking

scan and protect need no model; ask (and advanced leak-test) use --model openai with OPENAI_API_KEY set.

Documentation

  • SECURITY_MODEL.md - what it protects against, reduces, and does not guarantee; the recommended enterprise deployment pattern.
  • THREAT_MODEL.md - per-threat risk / mitigation / limitation / test coverage.
  • SECURITY.md - how to report a vulnerability.
  • BENCHMARKS.md - measured leak rates vs plain LLM-generated code, with methodology and honest caveats.
  • examples/ - runnable per-domain scripts; docs/examples.md - the same as a guide.
  • CHANGELOG.md - what changed in each release.

Limitations

  • This is a safety layer, not a compliance guarantee.
  • PII detection is best-effort; names and free text are especially hard.
  • k-anonymity here is a practical heuristic, not differential privacy.
  • The recommended SafePlan engine is far safer than generated Python, but policies must be configured correctly. Review high-risk outputs yourself.

License

MIT - see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

safedata_guard-2.0.0.tar.gz (150.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

safedata_guard-2.0.0-py3-none-any.whl (104.3 kB view details)

Uploaded Python 3

File details

Details for the file safedata_guard-2.0.0.tar.gz.

File metadata

  • Download URL: safedata_guard-2.0.0.tar.gz
  • Upload date:
  • Size: 150.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for safedata_guard-2.0.0.tar.gz
Algorithm Hash digest
SHA256 c0d48ea11462110241bb228fa34ebacbc9b5b36de7b89f8b21d5396e45e9f3ff
MD5 af4d63de443c8b299809760a998b3396
BLAKE2b-256 23525210e46aefce2bd1d613c7c6cbedce23000425e9dc367c591d3688486bc5

See more details on using hashes here.

Provenance

The following attestation bundles were made for safedata_guard-2.0.0.tar.gz:

Publisher: publish.yml on Aravindcy/safedata-guard

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file safedata_guard-2.0.0-py3-none-any.whl.

File metadata

  • Download URL: safedata_guard-2.0.0-py3-none-any.whl
  • Upload date:
  • Size: 104.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for safedata_guard-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 846c295d61908a8092bc598b968b69007054a45732cef365cc7ac7f7d0b49559
MD5 04cdd3b9a732d5d46f8c6ac2f70dc786
BLAKE2b-256 24afa1ef0145b754847959d5f8f5ccb9e93af824a394affcb89b9ca12f549a4f

See more details on using hashes here.

Provenance

The following attestation bundles were made for safedata_guard-2.0.0-py3-none-any.whl:

Publisher: publish.yml on Aravindcy/safedata-guard

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page