skills/anonymization-enhanced-privacy-protection-mobile-g/SKILL.md
Implement available-but-invisible privacy protection for mobile GUI agents using PII-aware anonymization with deterministic, type-preserving placeholders. Use when: 'anonymize PII in UI automation', 'build privacy layer for mobile agent', 'protect sensitive data in screenshots', 'add PII detection to Android agent', 'type-preserving placeholder system', 'privacy-safe GUI agent pipeline'.
npx skillsauth add ndpvt-web/arxiv-claude-skills anonymization-enhanced-privacy-protection-mobile-gInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill enables Claude to build privacy protection layers for mobile GUI automation agents that follow the available-but-invisible principle: sensitive information (phone numbers, emails, addresses, financial data) remains usable for task execution but is never directly exposed to cloud-based LLM agents. The technique uses deterministic, type-preserving placeholders (e.g., PHONE_NUMBER#a1b2c) mapped via SHA-256 hashing, combined with a four-layer architecture (PII Detector, UI Transformer, Secure Interaction Proxy, Privacy Gatekeeper) that enforces consistent anonymization across user instructions, XML accessibility trees, and screenshots simultaneously.
The core insight is that GUI agents do not need to see sensitive data to use it. A phone number field can be represented as PHONE_NUMBER#cbnhu throughout the agent's reasoning chain -- the agent knows it is a phone number, can reference it, and can instruct actions on it, but never learns the actual digits. The placeholder is generated deterministically via P = TYPE # Truncate(Base36(SHA256(value || TYPE)), 5), ensuring the same real value always maps to the same placeholder within a session, which preserves referential consistency across multi-step tasks.
The system enforces cross-modality consistency through two mechanisms. First, a lookup-before-generation policy consults a session-scoped mapping table before creating new placeholders, so identical entities seen in XML attributes, OCR output, and user instructions always receive the same token. Second, fuzzy matching (normalized Levenshtein distance with threshold tau=0.85) handles OCR recognition errors that would otherwise break alignment between the screenshot and XML modalities.
A critical architectural choice is the layered trust boundary. The PII Detector and UI Transformer run on-device to anonymize all outgoing data. The cloud agent only ever sees the anonymized "Virtual UI." When the agent issues actions (tap, type), the Secure Interaction Proxy intercepts them, resolves any placeholders back to real values using the local mapping table, and executes the de-anonymized command on the actual device. For rare cases where the agent must reason over raw values (e.g., comparing two prices), the Privacy Gatekeeper -- a local small language model -- evaluates relevance, necessity, and minimization criteria before returning only a bounded, non-revealing result (boolean, categorical).
Define the PII taxonomy. Enumerate the sensitive entity types your agent may encounter: PHONE_NUMBER, EMAIL, ADDRESS, PERSON_NAME, CREDIT_CARD, ID_NUMBER, ACCOUNT_BALANCE, MESSAGE_CONTENT, etc. Each type becomes a placeholder prefix.
Implement the PII Detector as a hybrid pipeline. Use a label-guided NER model (GLiNER family works well -- accepts arbitrary label sets at inference) for natural-language PII, plus a regex fallback layer for structured identifiers (credit card patterns, national ID formats, phone number formats). Add XML-specific structural validation with a whitelist of schema element names to prevent false positives on UI framework tokens.
Build the deterministic placeholder generator. For each detected entity (value, type), compute placeholder = TYPE + "#" + truncate(base36(sha256(value + "|" + TYPE)), 5). Maintain a session-scoped bidirectional mapping table (placeholder <-> raw_value). Always look up existing mappings before generating new ones.
Construct the instruction-driven contextual whitelist. Before anonymizing the UI, scan the user's task instruction for PII-like tokens. Tokens the user explicitly references (e.g., "send a message to 555-1234") should be whitelisted so the agent can match them, but still replaced with their deterministic placeholder in both instruction and UI simultaneously for consistency.
Apply the UI Transformer across all modalities. For XML accessibility trees: replace text, hint, and content-desc attributes via mapping table lookup. For screenshots: run OCR (EasyOCR or similar), fuzzy-align extracted text against registered entities (Levenshtein threshold 0.85), then render opaque overlays with placeholder text at matched bounding boxes, preserving spatial layout.
Implement the Secure Interaction Proxy. Intercept all agent-issued actions. For spatial actions (tap, swipe): validate the numeric element index, map it to the real bounding box, convert to device coordinates -- no de-anonymization needed. For textual actions (type text): scan the string for placeholder tokens, resolve each to its raw value via the mapping table, leave non-placeholder natural language unchanged, then execute the de-anonymized input on the device.
Build the Privacy Gatekeeper for local computation. When the agent requests reasoning over raw values, evaluate three criteria using a local SLM: (a) Is the computation relevant to the user's goal? (b) Does it genuinely require raw values or can it work with the virtual UI? (c) Is the result expressible as a bounded, non-revealing value? Return only minimal results (true/false, "higher"/"lower") -- raw values never cross the trust boundary.
Add fuzzy OCR alignment. Screenshots yield imperfect text. Normalize both OCR output and registered entity values (lowercase, strip whitespace), then compute Levenshtein similarity. If similarity >= 0.85, treat as a match and apply the existing placeholder. This prevents duplicate placeholders for the same entity seen through different modalities.
Validate with privacy and utility metrics. Measure leakage rate (percentage of raw PII values that appear in agent outputs), match score (exact string match of leaked values), and BERTScore of leaked content against originals. Separately measure task success rate to quantify utility impact. Target: leakage reduction >75% with utility degradation <5%.
Instrument the pipeline for latency monitoring. The OCR + NER overhead is approximately 1.7 seconds per screenshot frame. Profile each component (OCR ~0.84s, NER ~0.66s, transformer + proxy overhead) and optimize hot paths. Consider caching placeholder mappings and OCR results for unchanged screen regions.
Example 1: Anonymizing a contact list screen for a messaging agent
User: "Build the anonymization layer for my Android GUI agent. The agent reads contact lists and sends messages."
Approach:
PERSON_NAME, PHONE_NUMBER, MESSAGE_CONTENTtext="John Smith" and text="+1-555-867-5309"sha256("John Smith|PERSON_NAME") -> base36 truncated -> PERSON_NAME#k8m2xsha256("+1-555-867-5309|PHONE_NUMBER") -> PHONE_NUMBER#a1b2cimport hashlib
def generate_placeholder(value: str, pii_type: str, mapping: dict) -> str:
"""Deterministic, type-preserving placeholder generation."""
# Lookup-before-generation policy
key = (value, pii_type)
if key in mapping:
return mapping[key]
raw = f"{value}|{pii_type}".encode("utf-8")
digest = hashlib.sha256(raw).hexdigest()
# Convert hex to base36 and truncate to 5 chars
base36 = int(digest, 16)
chars = "0123456789abcdefghijklmnopqrstuvwxyz"
b36_str = ""
while base36 and len(b36_str) < 5:
b36_str = chars[base36 % 36] + b36_str
base36 //= 36
b36_str = b36_str.ljust(5, "0")
placeholder = f"{pii_type}#{b36_str}"
mapping[key] = placeholder
mapping[placeholder] = value # Reverse mapping for de-anonymization
return placeholder
# Usage
session_map = {}
print(generate_placeholder("+1-555-867-5309", "PHONE_NUMBER", session_map))
# Output: PHONE_NUMBER#a9x7k
Example 2: Secure Interaction Proxy resolving a "type" action
User: "The agent wants to type a message to a contact. How does the proxy resolve placeholders?"
Approach:
type(element=5, text="Hi PERSON_NAME#k8m2x, call me at PHONE_NUMBER#a9x7k")[A-Z_]+#[a-z0-9]{5}PERSON_NAME#k8m2x -> "John Smith", PHONE_NUMBER#a9x7k -> "+1-555-867-5309"type(element=5, text="Hi John Smith, call me at +1-555-867-5309")import re
PLACEHOLDER_PATTERN = re.compile(r"[A-Z_]+#[a-z0-9]{5}")
def resolve_action(action: dict, mapping: dict) -> dict:
"""De-anonymize textual action parameters before device execution."""
resolved = action.copy()
if action["type"] == "type" and "text" in action:
text = action["text"]
for match in PLACEHOLDER_PATTERN.finditer(text):
placeholder = match.group()
if placeholder in mapping:
text = text.replace(placeholder, mapping[placeholder])
resolved["text"] = text
# Spatial actions (tap, swipe) pass through unchanged
return resolved
# The cloud agent never sees "John Smith" -- only "PERSON_NAME#k8m2x"
Example 3: Privacy Gatekeeper evaluating a local computation request
User: "The agent needs to compare two prices to pick the cheaper flight. How does the gatekeeper handle this?"
Approach:
"ACCOUNT_BALANCE#f3g7h is the lower value" -- no raw prices cross the trust boundarydef gatekeeper_evaluate(request: str, user_goal: str) -> dict:
"""Evaluate whether local raw-value computation is permitted."""
return {
"relevant": True, # Comparison serves the booking goal
"necessary": True, # Cannot compare without numeric values
"minimal": True, # Result is a pointer, not the raw value
"approved": True,
"result_type": "categorical" # Returns placeholder reference only
}
PHONE_NUMBER#a1b2c_2) and logging a warning.PHONE_NUMBER placeholders). This metadata itself may be sensitive in some threat models.Anonymization-Enhanced Privacy Protection for Mobile GUI Agents: Available but Invisible -- Zhao et al., 2026. Focus on Section 3 (system architecture), Algorithm 1 (whitelist construction), Table 5 (proxy resolution rules), and Section 5 (experimental results showing 97% -> 19% leakage reduction with <1% utility loss on AndroidLab).
development
Audit LLM-based automatic short answer grading (ASAG) systems for adversarial vulnerabilities using token-level and prompt-level attack strategies from the GradingAttack framework. Triggers: 'test grading robustness', 'adversarial attack on grading', 'audit LLM grader', 'red-team answer grading', 'ASAG vulnerability assessment', 'grading fairness attack'
development
Build structured information-seeking agents that decompose complex queries into multi-turn search-and-browse workflows, aggregate results from multiple web sources, and return answers in typed structured formats (items, sets, lists, tables). Applies the GISA benchmark's ReAct-based agent architecture and evaluation methodology. Trigger phrases: "build an information-seeking agent", "search agent pipeline", "multi-turn web research agent", "structured web search workflow", "aggregate information from multiple sources", "web research with structured output"
data-ai
Optimize LLM prompts using GFlowPO's iterative generate-evaluate-refine loop with diversity-preserving exploration and dynamic memory. Use when: 'optimize this prompt', 'find a better prompt for this task', 'prompt engineering with examples', 'auto-tune my system prompt', 'improve prompt accuracy', 'generate prompt variations'.
development
Constrain LLM generation with executable Pydantic schemas and multi-agent pipelines to produce structurally valid, domain-rich artifacts. Uses ontology-as-grammar to eliminate hallucinated structures while preserving creative output. Trigger phrases: "generate a valid game design", "schema-constrained generation", "build a multi-agent pipeline with Pydantic validation", "ontology-driven content generation", "structured creative generation with DSPy", "generate artifacts that pass domain validation".