Sensitive data flow report
1. Summary
0 raw sensitive values were sent to external or LLM destinations in this period (6 call(s) checked).
How this was measured and what it does not cover: see sections 7 and 9.
2. Calls that touched sensitive data
A call counts here when Taintward found sensitive data in its input or output, or when it ran later in a run that had already touched sensitive data. One call can carry more than one class.
| Class | Calls |
|---|---|
| pii | 18 |
| secret | 18 |
3. Calls by destination
Each tool is configured with a destination class. Internal means systems you run; llm, external, log and rag mean the data leaves that boundary or is stored where it is hard to remove.
| Destination | Calls | With sensitive data | Violations |
|---|---|---|---|
| internal: Internal systems (own database, own services) | 6 | 6 | 0 |
| llm: LLM providers | 3 | 3 | 3 |
| external: External APIs and third parties | 3 | 3 | 3 |
| log: Logs | 3 | 3 | 3 |
| rag: Retrieval / vector store | 3 | 3 | 0 |
4. Policy violations and what happened to them
A violation is a call where the policy says sensitive data must not reach that destination as is. The outcome shows what Taintward did.
| Outcome | Violations |
|---|---|
| Redacted before sending | 3 |
| Sent with no raw value left to redact | 6 |
| Blocked (the call was not made) | 0 |
| Audit only (recorded, data sent unchanged) | 0 |
By policy rule
| Rule | Count |
|---|---|
| pii_egress | 9 |
| transfer | 6 |
Rules: pii_egress = sensitive data reaching an external, llm or log destination; transfer = personal data going to a jurisdiction the policy marks as not adequate (GDPR Art. 44); sdk_egress_gate = flagged by the SDK when no collector decision was recorded.
Who made the decision: collector: 18 call(s).
5. Cross-border transfers (GDPR Art. 44)
Calls whose destination is in another jurisdiction, grouped by jurisdiction. A transfer flag is raised by the policy for personal data going to a jurisdiction it does not treat as adequate.
| Jurisdiction | Calls | With personal data | Transfer flags | Outcome of flagged calls |
|---|---|---|---|---|
| us | 6 | 6 | 6 | redacted before sending: 3, sent with no raw value left to redact: 3 |
6. Recipients of data (GDPR Art. 30)
Every tool that received data in this period, with its destination class and jurisdiction. This is the list of recipients for a record of processing activities, taken from what actually ran.
| Tool | Destination | Jurisdiction | Calls | With sensitive data | Classes | Violations | Outcome |
|---|---|---|---|---|---|---|---|
internal_store | internal | - | 3 | 3 | pii, secret | 0 | |
query_db | internal | - | 3 | 3 | pii, secret | 0 | |
ask_llm | llm | us | 3 | 3 | pii, secret | 3 | redacted before sending: 3 |
call_external_api | external | us | 3 | 3 | pii, secret | 3 | sent with no raw value left to redact: 3 |
write_log | log | - | 3 | 3 | pii, secret | 3 | sent with no raw value left to redact: 3 |
rag_retrieve | rag | - | 3 | 3 | pii, secret | 0 |
7. Raw value check on data sent out
Every call to an llm, external, log or rag destination was checked. The recorded input of the call (gen_ai.tool.call.arguments or gen_ai.input.messages) was scanned for raw values with these patterns: US_SSN, AWS_ACCESS_KEY, GITHUB_TOKEN, EMAIL_ADDRESS, PHONE_NUMBER, CREDIT_CARD, PRIVATE_KEY. Masks such as [PII] do not match.
| Destination | Calls | Input checked | Input not recorded | Blocked | Audit only, sensitive | Calls with raw values | Raw values found |
|---|---|---|---|---|---|---|---|
| llm | 3 | 3 | 0 | 0 | 0 | 0 | 0 |
| external | 3 | 3 | 0 | 0 | 0 | 0 | 0 |
| log | 3 | 3 | 0 | 0 | 0 | 0 | 0 |
| rag | 3 | 3 | 0 | 0 | 0 | 0 | 0 |
No raw values were found in the checked inputs.
8. Tamper-evident evidence log
Each violation is stored as a leaf in an append-only Merkle log (SHA-256). Changing, removing or reordering any record changes the root. Signed checkpoints fix the roots at a point in time with an Ed25519 key.
| Item | Value |
|---|---|
| Log location | evidence-log |
| Records in the log | 9 |
| Violations in this period | 9 |
| Of these, found in the log | 9 |
| Of these, covered by a signed checkpoint | 9 |
| Newest checkpoint | #1 at 2026-10-24T10:23:57Z |
| Checkpoint hash | 62b3162ebc495f9c079eec5cfcfc93691da5ada96be46c9ba6be96547e3ccf32 |
| Signing key id | 4572b3464d294310 |
| Verification when this report was made | passed (1 shard(s) checked) |
Shards for the days in this report
| Tenant | Day (UTC) | Records | Root |
|---|---|---|---|
| acme | 2026-10-24 | 9 | 6cea02385fd81fb327893bbfaa473ed0a369f4390dc956aa61bfe8159483641f |
How to verify
taintward-evidence verify-checkpoints --evidence-dir <dir> --public-key evidence.pub \
--expect-head 62b3162ebc495f9c079eec5cfcfc93691da5ada96be46c9ba6be96547e3ccf32
# one record, with only the proof file, the checkpoint and the key:
taintward-evidence prove-shard --evidence-dir <dir> --tenant <t> --day <YYYY-MM-DD> --index <i> > proof.json
taintward-evidence verify-proof proof.json --public-key evidence.pub
Ask the operator for the public key through a separate channel, not together with this report.
9. Method and limits
How the data is produced: each tool call made through Taintward is recorded as an OpenTelemetry span. The SDK or gateway detects sensitive data, carries a taint label along the run, and redacts the input before it reaches an outside destination. The Taintward collector evaluates a Rego policy on every span and records the decision (taintward.policy.*). This report reads those spans back and counts them. It does not call any LLM.
What this report does not show:
- The report covers only calls made through Taintward (SDK wrappers, framework adapters or the MCP gateway). Calls that bypass it are not recorded and not counted.
- Sensitivity comes from Taintward's detectors (Presidio and secret patterns) plus the taint carried along each run. A value the detectors do not recognize is not counted as sensitive.
- The raw value check reads the input as recorded on the span. For SDK calls this is the input after the redaction gate, the same value the destination received. For the MCP gateway, arguments listed in passthrough_args are forwarded unchanged but stored masked on the span, so they cannot be checked here; review that list separately.
- Calls in audit-only mode forward data without redaction. When such a call carried sensitive data, the report does not make the "0 raw values" statement.
- The numbers are only as complete as the trace store. Sampling, retention limits or dropped spans reduce what is counted. The evidence log and its signed checkpoints show that recorded violations were not changed or removed later; they do not prove that every call was recorded.
- Jurisdictions come from the destination configuration (taintward.jurisdiction). A transfer flag means the policy marked that jurisdiction as not adequate for personal data and the call was part of a run that had touched personal data. It does not by itself mean raw personal data was sent; see the raw value check.
- The raw value check uses fixed patterns (SSN, AWS key, GitHub token, email, phone, card number, private key). Names, addresses and free text personal data are not matched by these patterns. Run with --deep-scan to also use the Presidio detectors (slower, more false positives).
10. List of violations
| Time | Tool | Destination | Jurisdiction | Classes | Rules | Outcome | Trace |
|---|---|---|---|---|---|---|---|
| 2026-10-24 04:54:37 UTC | ask_llm | llm | us | pii, secret | pii_egress, transfer | Redacted before sending | 7e87959920b32aff7ec13f5f52820ec6 |
| 2026-10-24 04:54:37 UTC | call_external_api | external | us | pii, secret | pii_egress, transfer | Sent with no raw value left to redact | 7e87959920b32aff7ec13f5f52820ec6 |
| 2026-10-24 04:54:37 UTC | write_log | log | - | pii, secret | pii_egress | Sent with no raw value left to redact | 7e87959920b32aff7ec13f5f52820ec6 |
| 2026-10-24 10:23:48 UTC | ask_llm | llm | us | pii, secret | pii_egress, transfer | Redacted before sending | 67cc8f836555a234a5482812f6665f3e |
| 2026-10-24 10:23:48 UTC | call_external_api | external | us | pii, secret | pii_egress, transfer | Sent with no raw value left to redact | 67cc8f836555a234a5482812f6665f3e |
| 2026-10-24 10:23:48 UTC | write_log | log | - | pii, secret | pii_egress | Sent with no raw value left to redact | 67cc8f836555a234a5482812f6665f3e |
| 2026-10-24 10:23:51 UTC | ask_llm | llm | us | pii, secret | pii_egress, transfer | Redacted before sending | aac9b1d6f82b793de0f8762a62f65695 |
| 2026-10-24 10:23:51 UTC | call_external_api | external | us | pii, secret | pii_egress, transfer | Sent with no raw value left to redact | aac9b1d6f82b793de0f8762a62f65695 |
| 2026-10-24 10:23:51 UTC | write_log | log | - | pii, secret | pii_egress | Sent with no raw value left to redact | aac9b1d6f82b793de0f8762a62f65695 |