ToxicJoin

A field can be safe on its own while the combination is not. ToxicJoin is a compositional privacy firewall for AI data agents that evaluates proposed SQL before execution, grounds fields in governed DataHub context and upstream lineage, and returns one deterministic outcome: ALLOW, REWRITE, or BLOCK.

The agent proposes. ToxicJoin decides. Uncertainty fails closed.

Try it

Current public demo: https://toxicjoin-public-demo.onrender.com/

The public deployment is a Render Free service running ToxicJoin in explicit fixture mode. It uses the real parser, deterministic policy engine, read-only DuckDB executor, independent verification, and authenticated-receipt path over synthetic judge data. It is not represented as a live external DataHub deployment, organization-data environment, mock, or static replay.

Public source: https://github.com/Z3X-1337/toxicjoin

Judge guide: https://github.com/Z3X-1337/toxicjoin/blob/main/docs/judge-testing.md

Sample outputs: https://github.com/Z3X-1337/toxicjoin/tree/main/examples

The problem

An AI data agent can combine individually ordinary fields — for example a stable pseudonym, coarse location, support category, purchase signal, or model score — into an unsafe disclosure. Column-by-column controls can miss the risk because the risk exists in the composition.

ToxicJoin reasons about what a query can actually expose, not only which columns it references.

Decision model

  • ALLOW — the proposed query is safe within the declared policy profile and may proceed through the guarded read-only execution path.
  • REWRITE — ToxicJoin produces one constrained safer query. The generated SQL is not trusted merely because ToxicJoin generated it: it is reparsed, regrounded against governance, reevaluated, and independently verified before any accepted output is released.
  • BLOCK — execution stops before DuckDB is called.

A genuinely low-risk aggregate remains ALLOW, so ToxicJoin is not a blanket deny layer.

Flagship flow

An analytics agent asks for a churn-risk aggregate grouped by coarse region. The proposed SQL lacks the trusted minimum distinct-subject threshold. ToxicJoin returns REWRITE and adds:

HAVING COUNT(DISTINCT c.customer_id) >= 20

The rewritten query is reparsed, regrounded, reevaluated, authorized, executed read-only, and independently verified. A separate individual-level composition of pseudonymous identity, quasi-identifiers, and sensitive data returns BLOCK before execution.

Why DataHub is essential

DataHub is on the governed decision path; it is not decorative metadata.

The repository contains retained live integration evidence using DataHub OSS and the official DataHub MCP Server to read governed entities, schema fields, classifications, and upstream lineage. The write side is process-isolated and application-allowlisted. ToxicJoin writes a sanitized DataHub Decision and verifies it through a fresh read-only MCP process.

The knowledge loop is:

read DataHub context
  -> deterministic compositional-risk decision
  -> take the safe action
  -> write sanitized decision knowledge back
  -> fresh reader inherits the result

The repository also contains a reusable Compositional Risk Review DataHub Skill: https://github.com/Z3X-1337/toxicjoin/blob/main/skills/compositional-risk-review/SKILL.md

Measured evidence

The current repository documents the following bounded regression evidence for its declared SQL/policy profile:

  • 30-case regression corpus: 30/30 expected decisions, reason codes, and effective outcomes; zero false allows.
  • 144 adversarial SQL mutations across known-unsafe compositional families: zero unsafe executions on the recorded evidence revision.
  • Two privacy bypasses found by adversarial review and closed, each with regressions that fail against the unfixed source.
  • 978 passed, 5 warnings across local unit, integration, security, and release-contract regressions.

These are bounded regression claims, not claims of universal privacy detection, differential privacy, formal verification, or legal-compliance certification.

Security and execution boundaries

ToxicJoin includes fail-closed handling for unsupported or ambiguous SQL, missing or stale governance, unresolved lineage, failed rewrites, failed verification, integrity failures, and incomplete evidence. The repository also includes authenticated receipts, request and result budgets, persistent cumulative disclosure state, role-separated DataHub MCP read/write/read-back, dependency audits, CodeQL, CycloneDX SBOMs, and a hardened non-root/read-only production container.

The public SQLite cumulative-disclosure authority is explicitly single-node. ToxicJoin does not currently claim a PostgreSQL/shared-authoritative disclosure backend, distributed transactions, cross-node replay state, or horizontally shared receipt/key custody.

The repository also contains staged vNext security components, but the canonical HTTP runtime has not fully migrated to the complete vNext proof chain; this boundary is documented and enforced by tests.

Open-source contribution

During the hackathon I opened DataHub Skills PR #48: https://github.com/datahub-project/datahub-skills/pull/48

It adds a dependency-free repository integrity check that prevents new dangling DataHub Skill references from entering the repository. The PR is currently open, mergeable, not merged, and not a draft. It is independent of the ToxicJoin product runtime and is represented as pending maintainer review.

Current project identity

  • Repository created: July 22, 2026
  • Current application version declared by source: 0.2.1
  • Policy version: 0.2.0
  • License: Apache-2.0
  • Public repository: Z3X-1337/toxicjoin

Evidence before claims. Fail closed on uncertainty.

Built With

Share this project:

Updates