Back to skill

Security audit

Data Anonymizer

Security checks for vulnerabilities and agentic risk

Overview

This skill is relevant to data anonymization, but it can expose sensitive matches and includes database update examples that could overwrite live records without enough safeguards.

Review before installing. Use this only with explicit input paths and isolated database copies, never directly against production. Require backups, transactions, dry runs, redacted detection output, and human confirmation before any data-changing command.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:18
Finding
PII Detection Commands Expose Sensitive Values in Output and Logs## Vulnerability Details **File Location**: `SKILL.md`, lines 18–30 **Vulnerability Type**: Plaintext sensitive-data exposure **Risk Level**: High ### Vulnerable Code ```bash # Scan files for common PII patterns rg -n "(\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z|a-z]{2,}\\b)" --type-not binary 2>/dev/null | head -20 echo "--- Emails found above ---" rg -n "\\b\\d{3}[-.]?\\d{2}[-.]?\\d{4}\\b" --type-not binary 2>/dev/null | head -20 echo "--- SSN-like patterns above ---" rg -n "\\b\\d{3}[-.]?\\d{3}[-.]?\\d{4}\\b" --type-not binary 2>/dev/null | head -20 echo "--- Phone numbers above ---" rg -n "\\b\\d{4}[- ]?\\d{4}[- ]?\\d{4}[- ]?\\d{4}\\b" --type-not binary 2>/dev/null | head -20 echo "--- Credit card-like patterns above ---" ``` ### Technical Analysis The `rg` commands do not specify an explicit input path, so they recursively scan the process's current working directory. Each matching line is printed without redaction, including the detected value and potentially other sensitive content from the same line. When these commands are executed by an AI agent, CI job, or administrative shell, the results may be copied into tool output, chat transcripts, terminal logs, CI artifacts, or centralized observability systems. The `head -20` limit reduces the number of exposed records but does not protect the records that are returned. ### Attack Path 1. Sensitive files containing emails, SSNs, phone numbers, or payment-card-like values are present under the current working directory. 2. A user or agent invokes the documented `detect` procedure. 3. `rg` recursively reads all accessible files in that directory tree. 4. Matching lines containing raw PII are emitted to standard output. 5. Tooling retains or forwards that output to agent transcripts, terminal logs, CI logs, or other systems not approved to store the underlying PII. ### Impact Assessment The issue does not grant additional operating-system privilege ...[truncated 412 chars]
Remediation
## Remediation Suggestions - Require an explicit, user-approved input path rather than implicitly scanning the current directory. - Validate that the selected path is within an allowlisted data directory. - Exclude sensitive metadata and unrelated locations such as `.git`, credential directories, backups, secret stores, and build artifacts. - Return only aggregate counts, classifications, and file names by default. - If samples are necessary, redact the matched values before displaying them and avoid printing the remainder of the source line. - Require explicit confirmation before scanning data that may originate from production. - Document that raw scan results must not be placed in agent context, CI logs, telemetry, or persistent transcripts. - Provide a secure output option that writes access-controlled findings to a designated local file rather than standard output.

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:84
Finding
Unsalted Deterministic Hashes Permit Re-identification and Cross-Dataset Linkage## Vulnerability Details **File Location**: `SKILL.md`, lines 84–88 and 130–138 **Vulnerability Type**: Weak pseudonymization of predictable personal data **Risk Level**: Medium ### Vulnerable Code ```python def anonymize_email(email): """Consistent fake email — same input always produces same output""" h = hashlib.sha256(email.encode()).hexdigest()[:8] domain = email.split('@')[1] if '@' in email else 'example.com' return f"user_{h}@test-{domain}" ``` ```sql UPDATE users SET email = 'user_' || md5(email) || '@example.com', first_name = 'User', last_name = 'Test_' || substring(md5(last_name) from 1 for 6), phone = '+1' || lpad(abs(hashtext(phone))::text, 10, '0'), address_line1 = floor(random() * 9999)::text || ' Test Street', city = 'Testville', zip_code = lpad(abs(hashtext(zip_code))::text, 5, '0'), date_of_birth = date_of_birth - (random() * 365)::int * interval '1 day', ssn = NULL WHERE true; ``` ### Technical Analysis SHA-256 and MD5 are applied directly to predictable personal values without a secret key or salt. An attacker can generate candidate hashes from known or likely email addresses and names, then compare them with the anonymized values. This makes the output deterministic pseudonymization rather than irreversible anonymization. The Python email function truncates the digest to eight hexadecimal characters, leaving only 32 bits of output and increasing collision risk. It also preserves the original email domain in `test-{domain}`, which can reveal an individual's employer, school, organization, or service provider. The SQL example exposes the full unsalted MD5 digest of each email and a truncated MD5 digest of each surname. Identical source values generate identical outputs across all datasets that use the same transformation, enabling cross-dataset correlation. ### Attack Path 1. An attacker obtains an anonymized export or gain ...[truncated 1095 chars]
Remediation
## Remediation Suggestions - Use HMAC-SHA-256 with a cryptographically random, dataset-specific secret key when stable pseudonyms are required. - Store the HMAC key separately from both source and anonymized datasets, using a secret manager with strict access controls. - Use different domain-separation labels or keys for different fields and datasets to prevent unintended cross-dataset correlation. - Prefer randomly generated identifiers backed by a protected mapping table when deterministic recomputation is unnecessary. - Do not retain the original email domain unless there is a documented analytical requirement; replace it or generalize it into an approved category. - Use sufficiently long output values to make collisions negligible and enforce uniqueness checks before committing transformed records. - Clearly classify deterministic transformations as pseudonymization rather than claiming that they produce anonymous data.

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:90
Finding
Process-Randomized Python Hashing Breaks Stable Synthetic Replacement## Vulnerability Details **File Location**: `SKILL.md`, lines 90–96 and 112–117 **Vulnerability Type**: Unstable anonymization seed and referential-integrity failure **Risk Level**: Medium ### Vulnerable Code ```python def anonymize_name(name): """Replace with consistent fake name""" from faker import Faker fake = Faker() fake.seed_instance(hash(name) % (2**32)) return fake.name() ``` ```python def anonymize_address(address): """Replace with fake address in same region""" from faker import Faker fake = Faker() fake.seed_instance(hash(address) % (2**32)) return fake.address() ``` ### Technical Analysis Python normally randomizes string hashing between interpreter processes. Consequently, `hash(name)` and `hash(address)` are not stable across separate runs unless hash randomization is deliberately disabled. The code claims to produce consistent replacements, but the same source value can receive different Faker seeds in separate processes. Related exports, tables, or batches processed independently may therefore receive inconsistent synthetic values. This can break joins, identity grouping, test reproducibility, and the stated preservation of data relationships. Disabling Python hash randomization would make the output stable but would not make the design cryptographically safe. A stable keyed derivation should be used instead. ### Attack Path 1. Related records are distributed across multiple files, tables, batches, or exports. 2. Each dataset is anonymized in a separate Python process. 3. Python assigns a different randomized hash secret to each process. 4. Identical names or addresses produce different integer hashes and different Faker seeds. 5. The generated replacements no longer match across related records. 6. Referential relationships, grouping logic, or test assumptions fail when the transformed datasets are combined. ### Impact Assessment ...[truncated 502 chars]
Remediation
## Remediation Suggestions - Replace Python's built-in `hash()` with a stable keyed derivation such as HMAC-SHA-256. - Convert a sufficiently large portion of the keyed digest into an integer when a deterministic Faker seed is required. - Use explicit field and dataset identifiers in the HMAC input to prevent unintended correlation. - Maintain an access-controlled source-to-synthetic mapping table for fields that must preserve relationships across independent jobs. - Process related tables under the same mapping context and verify cross-table consistency before releasing the dataset. - Add automated tests that execute anonymization in separate processes and confirm that identical inputs produce identical approved outputs. - Avoid presenting Faker output as preserving regional or statistical properties unless locale selection and distribution validation are explicitly implemented.

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:128
Finding
Destructive Full-Table Anonymization Lacks Transaction and Environment Safeguards## Vulnerability Details **File Location**: `SKILL.md`, lines 128–141 **Vulnerability Type**: Unsafe destructive database operation **Risk Level**: Medium ### Vulnerable Code ```sql -- PostgreSQL anonymization script UPDATE users SET email = 'user_' || md5(email) || '@example.com', first_name = 'User', last_name = 'Test_' || substring(md5(last_name) from 1 for 6), phone = '+1' || lpad(abs(hashtext(phone))::text, 10, '0'), address_line1 = floor(random() * 9999)::text || ' Test Street', city = 'Testville', zip_code = lpad(abs(hashtext(zip_code))::text, 5, '0'), date_of_birth = date_of_birth - (random() * 365)::int * interval '1 day', ssn = NULL WHERE true; -- Verify no real data remains SELECT email FROM users WHERE email NOT LIKE '%@example.com' LIMIT 5; ``` ### Technical Analysis The unconditional `WHERE true` clause modifies every row in the `users` table. The example does not include a transaction, rollback procedure, backup requirement, database identity check, environment restriction, dry-run mode, expected row-count validation, or explicit prohibition against executing against the source production database. The subsequent query only checks email formatting after the update. It cannot restore overwritten values and does not verify that the correct database was selected, that generated values satisfy all constraints, or that relationships remain valid. Because the Skill is intended to prepare production-derived data, an operator or agent could plausibly connect to the wrong database and execute the example against live data. ### Attack Path 1. An operator or agent obtains database credentials and connects to a PostgreSQL instance. 2. The connection points to the production database rather than an isolated copy, whether through configuration error, ambiguous naming, or an incorrect connection string. 3. The documented SQL block is executed without a protective ...[truncated 782 chars]
Remediation
## Remediation Suggestions - Explicitly require anonymization to run only against an isolated copy of the source database. - Require a verified backup or recoverable snapshot before any transformation. - Add database identity and environment checks that abort if the host, database name, or environment is not an approved non-production target. - Use a dedicated least-privilege database role that has access only to the copied dataset. - Wrap updates in `BEGIN` and perform all validation before an explicit `COMMIT`; default to `ROLLBACK`. - Add a dry-run stage that reports the target database, affected tables, expected row counts, constraint risks, and representative redacted transformations. - Require explicit human confirmation immediately before committing a full-table update. - Validate uniqueness constraints, foreign keys, nullability, field lengths, generated-value formats, and affected-row counts within the transaction. - Use staged tables or create a transformed copy rather than overwriting the only available dataset. - Document tested restoration procedures and prohibit execution through connections capable of modifying the production source.
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (2)

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The skill explicitly discusses anonymizing production data and provides destructive SQL update examples without a clear warning to operate only on backups, replicas, or non-production copies. If used directly against a live production database, it could irreversibly modify or null sensitive fields, causing data loss, service disruption, compliance issues, and corruption of operational records.

Vague Triggers

Medium
Confidence
84% confidence
Finding
The 'Use when' list includes broad natural-language triggers such as 'GDPR compliance' and 'remove personal data', plus a catch-all condition about preparing production data for non-production use. These phrases are not narrowly scoped to this skill's exact operation and could match many ordinary requests, increasing the chance of unintended invocation.

Static analysis

No suspicious patterns detected.