Scope — what is PII, what is NOT
SkillDev toolsDetect 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.
No other account needed.
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
-
Run
git diff develop...HEAD. This is the primary source — start here, not from grep. -
In added lines, identify:
- Assignments of high-risk variables (see above)
- New calls to third-party sinks or wrappers:
track(),trackPage(),logger.*(),captureException()
-
In removed lines, identify:
- Removed guards:
confidentialityFilter, scrubbing calls, PII-stripping wrappers — flag each removal as a potential leak enabler.
- Removed guards:
-
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
-
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
-
Use the grep commands below only to trace a pattern already found in the diff. Never run them independently to source findings.
-
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