Back to skill

Security audit

Blind Review Sanitizer

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent local blind-review sanitizer, but it can re-expose removed identifying information in console output and has under-scoped file/dependency safeguards.

Review before installing or running on sensitive manuscripts. Use only in a local, trusted workspace, avoid shared CI or agent logs, do not pass sensitive manuscripts through environments that capture stdout, and inspect output paths carefully because the script may overwrite existing writable files. The dependency should be corrected and pinned before normal use.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding
Incorrect and Unpinned DOCX Dependency Creates Supply-Chain Risk<![CDATA[ ## Vulnerability Details **File Location**: `requirements.txt:1` **Related Locations**: `SKILL.md:32`, `SKILL.md:122`, `scripts/main.py:197-201` **Vulnerability Type**: Dependency confusion and non-reproducible dependency resolution **Risk Level**: Medium ### Vulnerable Code ```text docx ``` The implementation and documentation instead expect `python-docx`: ```python try: from docx import Document except ImportError: print("Error: python-docx not installed. Run: pip install python-docx") sys.exit(1) ``` ### Technical Analysis The dependency manifest declares the distribution named `docx`, while the documentation identifies the required distribution as `python-docx`. Although both can relate to the `docx` import namespace, they are different package identities. This mismatch can cause installation of an unintended, obsolete, or incompatible package. The dependency is also unversioned and has no integrity hash. Consequently, installations are not reproducible and automatically trust whichever package version the configured package index resolves at installation time. Python package installation and import can execute package-controlled code with the permissions of the user running the skill. ### Attack Path 1. A user or automated agent follows the project setup process and runs `pip install -r requirements.txt`. 2. The package resolver requests the distribution named `docx`, rather than the documented `python-docx` dependency. 3. The resolver downloads the package from the configured package index without a version or integrity constraint. 4. Package-controlled installation or imported module code executes in the user's environment. 5. A compromised, substituted, or incompatible release can access data and resources available to the installing user. ### Impact Assessment Successful supply-chain exploitation would execute code with the privileges of the account installing or running the skill. This could expose manuscript conten ...[truncated 310 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace `docx` with the correct reviewed distribution: ```text python-docx==&lt;reviewed-version&gt; ``` 2. Pin all dependencies to explicitly reviewed versions. 3. Generate a lock file containing cryptographic hashes and install with hash verification, such as: ```bash pip install --require-hashes -r requirements.lock ``` 4. Use only trusted package indexes and disable unapproved extra indexes. 5. Add a CI check that verifies the manifest, documentation, and imported package names remain consistent. 6. Run dependency vulnerability and provenance scanning before releases. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/main.py:120
Finding
Sanitized Personal Information Is Disclosed in Console Output<![CDATA[ ## Vulnerability Details **File Location**: `scripts/main.py:120-128`, `scripts/main.py:350-356` **Vulnerability Type**: Plaintext sensitive-data logging **Risk Level**: Medium ### Vulnerable Code The original matched identifiers are retained verbatim: ```python # Remove email matches = re.finditer(EMAIL_PATTERN, result, re.IGNORECASE) for match in list(matches)[::-1]: self.removed_items.append(f"Email: {match.group()}") result = result[:match.start()] + '[EMAIL]' + result[match.end():] # Remove phone matches = re.finditer(PHONE_PATTERN, result) for match in list(matches)[::-1]: self.removed_items.append(f"Phone: {match.group()}") result = result[:match.start()] + '[PHONE]' + result[match.end():] ``` The retained values are subsequently printed: ```python if sanitizer.removed_items: print("Summary:") for item in set(sanitizer.removed_items): count = sanitizer.removed_items.count(item) if count > 1: print(f" - {item} (x{count})") else: print(f" - {item}") ``` Institution names are handled similarly at `scripts/main.py:120`: ```python self.removed_items.append(f"Institution: {match.group()}") ``` ### Technical Analysis The sanitizer removes identifying information from the generated manuscript but stores each original email address, telephone number, and institution name in `removed_items`. It then emits those raw values to standard output. Standard output is commonly retained by shell capture, CI systems, agent transcripts, orchestration platforms, job telemetry, and centralized logging services. Therefore, the output artifact may be sanitized while the same sensitive identifiers remain available in a separate and potentially more broadly accessible logging channel. This is a confidentiality flaw because the logged content directly conflicts with the purpose of removing identifying information for anonymous review. ### Attack Path 1. An operator processes a manuscr ...[truncated 1179 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Never store or print complete matched identifiers. 2. Replace `removed_items` entries with category counters: ```python self.removed_counts["email"] += 1 self.removed_counts["phone"] += 1 self.removed_counts["institution"] += 1 ``` 3. Report only aggregate information: ```text Emails removed: 2 Phone numbers removed: 1 Institutions removed: 3 ``` 4. If diagnostic output is necessary, make it explicitly opt-in and redact values so they cannot be reconstructed. 5. Ensure exception messages do not include manuscript contents. 6. Add automated tests that capture standard output and assert that known email addresses, phone numbers, author names, and affiliations never appear. 7. Document that execution logs may themselves be sensitive and should follow an appropriate retention policy. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/main.py:324
Finding
Unrestricted Output Path Allows Silent Overwrite of Arbitrary Writable Files<![CDATA[ ## Vulnerability Details **File Location**: `scripts/main.py:324-328` **Related Locations**: `scripts/main.py:220`, `scripts/main.py:286-288`, `scripts/main.py:343` **Vulnerability Type**: Unvalidated file output and unsafe overwrite **Risk Level**: Medium ### Vulnerable Code The caller can select an unrestricted output path: ```python # Determine output path if args.output: output_path = Path(args.output) else: output_path = input_path.parent / f"{input_path.stem}-blinded{input_path.suffix}" ``` Text output opens the selected path in truncating write mode: ```python with open(output_path, 'w', encoding='utf-8') as f: f.writelines(result_lines) ``` DOCX output also saves directly to the selected path: ```python # Save doc.save(output_path) ``` The process begins without an existence, collision, or symlink check: ```python print(f"Processing: {input_path}") processor.process(input_path, output_path) ``` ### Technical Analysis The `--output` argument is converted directly into a `Path` and used as a write target. The implementation does not: - Restrict output to an approved workspace. - Resolve and validate the canonical path. - Reject symbolic links. - Detect an existing destination. - Require explicit confirmation before overwriting. - Prevent the input and output paths from referring to the same file. For text files, mode `w` truncates an existing destination immediately. `doc.save()` can likewise replace an existing writable target. A maliciously chosen output path, or an attacker-created symlink at the expected default output location, can therefore redirect the generated content into another file accessible to the process. ### Attack Path 1. An attacker influences the command arguments or creates a symbolic link at the selected/default output location. 2. The user runs the sanitizer with an output path referring to an existing writable file, or to a symlink resolving to one. 3. The script performs no canonical-path, s ...[truncated 953 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Resolve the output path and require it to remain inside an explicitly approved workspace: ```python workspace = Path.cwd().resolve() output_path = Path(args.output).resolve() if output_path != workspace and workspace not in output_path.parents: raise ValueError("Output path must remain inside the approved workspace") ``` 2. Reject output paths that are symbolic links or whose existing parent traversal crosses an untrusted symlink. 3. Refuse to overwrite existing destinations by default. For text output, use exclusive creation mode (`'x'`) when practical. 4. Add an explicit `--force` option for intentional overwrites and clearly display the canonical target before writing. 5. Compare canonical input and output paths and reject attempts to overwrite the source manuscript. 6. Write to a securely created temporary file in the destination directory and atomically rename it only after successful processing. 7. Apply the same checks consistently to TXT, Markdown, and DOCX processing. 8. Add tests for existing targets, symlink targets, input/output collisions, traversal outside the workspace, and destinations without write permission. ]]>
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (5)

Tp4

High
Category
MCP Tool Poisoning
Confidence
88% confidence
Finding
The documented purpose and the described operational behavior are materially inconsistent: the skill claims bounded anonymization workflow properties while apparently performing broader file transformation and identifier removal behavior that is not clearly declared. This mismatch is dangerous because users and agent frameworks may trust the higher-level description, yet invoke code that handles sensitive manuscripts and alters content in ways that are under-specified, leading to confidentiality, integrity, and review-process risks.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill documents executable behavior that reads and writes local files but does not declare any tool scope or permissions boundaries. In an agent environment, this creates an authorization ambiguity where reviewers and orchestrators cannot reliably constrain file access, increasing the chance of unintended reads, overwrites, or use outside the intended workspace.

Intent-Code Divergence

Medium
Confidence
78% confidence
Finding
The skill documentation states that the script accepts `.docx`, `.md`, and `.txt` inputs and that `python-docx` is optionally required for `.docx` processing. In the provided file, these statements are presented as implemented behavior, but this file contains only manifest/documentation content and no executable logic to substantiate those claims, creating an intent-versus-implementation divergence within the available artifact.

Description-Behavior Mismatch

Medium
Confidence
97% confidence
Finding
This is a real information disclosure issue: after anonymizing the document, the tool prints the exact removed items such as author names, institutions, email addresses, phone numbers, and self-citation phrases to stdout. In academic workflows, CLI output may be captured in terminal history, CI logs, shared notebooks, or support transcripts, which can re-expose the very identifying information the tool is supposed to remove.

Unpinned Dependencies

Low
Category
Supply Chain
Content
docx
Confidence
95% confidence
Finding
The dependency is unpinned, so installations may resolve to different versions over time, including releases with breaking changes or newly introduced vulnerabilities. In a skill that processes academic writing artifacts, this creates a supply-chain risk and reduces build reproducibility, though the direct impact is limited by the small dependency surface shown here.

Static analysis

No suspicious patterns detected.