Scope — what is PII, what is NOT

SkillDev tools

Detect new PII leaks introduced by the current branch. Use when asked to check for potential data leaks for the current changes.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Scope — what is PII, what is NOT skill

What this skill tells your AI

The instructions your AI receives, as published by ledgerhq/ledger-live in .agents/skills/detect-data-leaks/SKILL.md and read by ahel’s review.

We only consider PII that is sent to third-party services. Any call to our own backend with PII is not considered a data leak.

Every third-party service should be considered, but each has a different risk level. Logging services are the highest risk.

Some information is only PII in context — for example, public addresses are not PII by themselves, but on a logging service such as Datadog, an address can be linked to a location and device, allowing identification of the person behind it.

Crash reports need to be studied alongside logs — they are a common source of data leaks.

Any service that queries the blockchain for an address is not a concern — the query is mandatory for the system to function and the data is not linked to any other identifiable information. This applies to all coin modules. Examples:

  • Kaspa → api.kaspa.org
  • EVM (Ethereum, BSC, Polygon…) → Etherscan-family
  • Tron → TronGrid (api.trongrid.io)

Known third-party sinks in this repo

Prioritize these, but do not exclude others:

  • Datadog
  • Sentry
  • Mixpanel

High-risk variables

Treat any of these as high-risk when found in added lines:

location.pathname, window.location.hash, address, walletAccountId, txId, publicKey, signature, rawData, payinAddress, fromAccountAddress, toAccountAddress, binaryPayload

Process

  1. Run git diff develop...HEAD. This is the primary source — start here, not from grep.

  2. In added lines, identify:

    • Assignments of high-risk variables (see above)
    • New calls to third-party sinks or wrappers: track(), trackPage(), logger.*(), captureException()
  3. In removed lines, identify:

    • Removed guards: confidentialityFilter, scrubbing calls, PII-stripping wrappers — flag each removal as a potential leak enabler.
  4. For each high-risk variable in added lines, trace its lineage:

    • Check if it flows into a sink call within the diff
    • If it may pass through intermediate calls, read the affected file to follow the chain
  5. For each new sink call in the diff:

    • Read surrounding context in the file
    • Follow the call chain to determine what gets serialized
    • If the call is a wrapper (e.g. track()), read its implementation — do not assume from the name
  6. Use the grep commands below only to trace a pattern already found in the diff. Never run them independently to source findings.

  7. Score each finding 1–10. Report only those scoring 7 or higher with a concrete fix.

Grep helpers (investigation only)

location.pathname flowing into track() — pathname often assigned before the call:

find apps \( -name "*.ts" -o -name "*.tsx" \) | grep -vE "\.test\.|/__tests__/|/tests/" | \
  xargs perl -0777 -ne 'BEGIN { exit unless @ARGV } print "$ARGV\n" if /track(?:Page)?\([\s\S]{0,500}?location\.pathname/'

window.location.hash in analytics:

grep -rn "window\.location\.hash" apps/ --include="*.ts" --include="*.tsx"

Address interpolated into new Error(...) in coin modules:

find libs \( -name "*.ts" -o -name "*.tsx" \) | grep -vE "live-e2e-shared|coin-tester-modules|__tests__|tests|\.test\." | \
  xargs perl -0777 -ne 'BEGIN { exit unless @ARGV } print "$ARGV\n" if /new Error\(`[\s\S]{0,300}?\$\{[^}]*(address|sender|hash|walletAccountId|txId|publicKey)[^}]*\}/i'

Signed tx payload on broadcast failure:

grep -rn -E "broadcast_failure|broadcastLogger" apps/ --include="*.ts" | grep -v "\.test\."

Full transaction object spread into analytics:

grep -rn -E "value:[[:space:]]*(params|transaction)\b" apps/ --include="*.ts" --include="*.tsx" \
  | grep -v "\.test\." \
  | grep -vE "value:[[:space:]]*(params|transaction)\."

Signed payload fields in track():

grep -rn -E "binaryPayload|payinAddress|fromAccountAddress|toAccountAddress" libs/ apps/ --include="*.ts" --include="*.tsx" \
  | grep -vE "\.test\.|/__tests__/|/tests/"

confidentialityFilter coverage on trackPage():

find apps/ledger-live-desktop apps/ledger-live-mobile -name "segment.ts" -path "*/analytics/*" | \
  xargs -I{} grep -n -E "confidentialityFilter|trackPage" {}

Output format

  • Score mapping: 9-10 → 🔴 Critical, 7–8 → 🟡 Suggestion. Scores below 7 are not reported.
  • If no findings reach score 7, produce no output.
🔴 Critical (10/10) — apps/.../useActivityIndicator.ts:39
track("SyncErrorList", { page: location.pathname, ... });
Fix: remove `page` from the payload or replace with a static route label stripped of account IDs.

🟡 Suggestion (8/10) — apps/.../someFile.ts:12
track("Event", { hash: window.location.hash });
Fix: pass only the route segment before the `#`, not the full hash.

References

.agents/skills/client-ids/SKILL.md

Signals

GitHub stars
618
Forks
490
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
detect-data-leaks
Source
github.com/ledgerhq/ledger-live