Back to skill

Security audit

Fword Skill

Security checks for vulnerabilities and agentic risk

Overview

This skill does the advertised Word and LaTeX conversion work, but it can send document contents to external AI services, retains a local copy of the original document, and its setup script may make privileged system changes without enough warning.

Install only if you are comfortable with these data flows. Use --raw for confidential documents, choose only trusted AI providers or endpoints, avoid passing real API keys on the command line, and delete the .fword workspace when you no longer need the retained original document. Review setup.sh before running it, especially on systems where sudo package installation or unpinned pip installs are not acceptable.

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 (2)

T08 · Insecure Dependencies

Warning
Location
scripts/requirements.txt:1
Finding

Unpinned Third-Party Dependencies Create a Supply-Chain Risk

Content
View full analysis

Vulnerability Details

File Location: scripts/requirements.txt:1-5 and scripts/setup.sh:27-33
Vulnerability Type: Unpinned dependency installation without integrity verification
Risk Level: Medium

Vulnerable Code

scripts/requirements.txt:1-5:

text
pypandoc>=1.13
anthropic>=0.40.0
openai>=1.0.0
python-docx>=1.1.0
rich>=13.0.0

scripts/setup.sh:27-33:

bash
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
REQ_FILE="$SCRIPT_DIR/requirements.txt"

if [ -f "$REQ_FILE" ]; then
    pip3 install -q -r "$REQ_FILE"
else
    pip3 install -q pypandoc anthropic python-docx rich
fi

Technical Analysis

Every Python dependency is specified with an open-ended minimum version. The setup process consequently installs the newest version accepted by the constraints from the user's configured package index. There is no lock file, package hash verification, trusted-index enforcement, or upper version constraint.

Python packages can execute code during installation and whenever imported. A compromised future release, package-index compromise, or malicious package supplied through an untrusted configured index could therefore introduce code that was not present during this audit. The fallback installation path is also entirely unpinned.

This does not establish that any currently named package is malicious. The issue is that the effective dependency set can change after review without integrity validation.

Attack Path

  1. An attacker compromises a future release of one of the listed dependencies, compromises the package index, or controls a package index configured in the victim's pip environment.
  2. The victim follows the documented setup process and runs scripts/setup.sh.
  3. pip3 resolves the open-ended requirement to the attacker-controlled release.
  4. Malicious code executes during package installation or when the installed module is imported by the conversion scripts.

...[truncated 729 chars]

Remediation
View remediation

Remediation Suggestions

  1. Pin every direct and transitive dependency to an exact reviewed version.
  2. Generate a lock file using a dependency-management tool such as pip-tools, Poetry, or uv.
  3. Record and enforce package hashes, for example by using pip install --require-hashes.
  4. Apply the same exact version constraints to the fallback installation branch, or remove that branch.
  5. Install dependencies in a dedicated virtual environment rather than the global Python environment.
  6. Explicitly configure a trusted package index and prevent unexpected pip configuration from redirecting dependency resolution.
  7. Add automated dependency scanning and controlled update review before changing locked versions.
  8. Pin or otherwise control the Pandoc package version installed through operating-system package managers where reproducibility is required.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/convert.py:59
Finding

API Keys Can Be Exposed Through Command-Line Arguments

Content
View full analysis

Vulnerability Details

File Location: scripts/convert.py:59 and references/usage.md:31
Vulnerability Type: Sensitive credential exposure through process arguments and shell history
Risk Level: Low

Vulnerable Code

scripts/convert.py:57-60:

python
)
parser.add_argument("--model", default=None, help="AI model (default: provider's default)")
parser.add_argument("--api-key", default=None, help="API key (or set provider's env var)")
parser.add_argument("--base-url", default=None, help="Custom API base URL")

references/usage.md:29-31:

bash
# Any OpenAI-compatible API
python scripts/convert.py document.docx -p openai --base-url http://localhost:8080/v1 --api-key your-key

The supplied value is subsequently passed to the refinement client in scripts/convert.py:102-109:

python
result = refine_latex(
    raw_latex,
    metadata,
    provider=args.provider,
    model=args.model,
    api_key=args.api_key,
    base_url=args.base_url,
)

Technical Analysis

The CLI permits API credentials to be provided as ordinary command-line arguments, and the usage documentation demonstrates this method. Command-line values may be retained in shell history, terminal logs, command auditing systems, support bundles, or process-monitoring telemetry. Depending on the operating system and process visibility configuration, another local user may also be able to inspect the process argument vector while conversion is running.

The code does not print the API key directly, and it also supports environment-variable credentials. Nevertheless, explicitly supporting and documenting a command-line secret creates an avoidable local disclosure path.

Attack Path

  1. A user follows the documented example and invokes convert.py with a real provider credential through --api-key.
  2. The shell stores the complete command in its history, or a process-monitoring or audit system ca ...[truncated 851 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove the --api-key option or mark it as deprecated and reject its use by default.
  2. Read credentials from the provider-specific environment variables already supported by ai_refiner.py.
  3. For interactive use, provide a hidden prompt based on getpass.getpass() so the key is not echoed or stored in shell history.
  4. Consider integration with operating-system credential stores or a protected configuration file with restrictive permissions.
  5. Replace the command-line credential example in references/usage.md with an environment-variable example.
  6. Warn users not to place credentials in command histories, scripts, logs, or shared configuration.
  7. Recommend revocation and rotation of any key that has already been supplied through a command line on a shared or monitored system.
Vulnerability Patterns
  • 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
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
Findings (27)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The declared description presents the skill as a full bidirectional Word/LaTeX converter. However, the supplied code chunk is specifically an AI refiner for raw LaTeX that was already produced elsewhere (apparently by Pandoc). Its primary function is to send LaTeX chunks to an LLM and return cleaned LaTeX. While the listed AI providers align with the description, the core behavior shown here is materially narrower than the declared purpose: there is no parsing of Word documents, no conversion pipeline from Word to LaTeX, and no reverse conversion from LaTeX back to Word with style preservation. Therefore the description overstates what this code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The supplied code only performs one direction of conversion: LaTeX to Word. It validates input paths, discovers a local .fword workspace, optionally uses a reference DOCX for style preservation, calls pypandoc to produce a .docx, and records the conversion. There is no evidence of Word-to-LaTeX conversion, no AI refinement, and no support for any of the listed AI providers in this chunk. While style preservation on back-conversion is consistent with part of the description, the declared purpose materially overstates the behavior shown here, so this is a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The code is clearly focused on one direction: Word to LaTeX. It accepts a .docx/.doc input, uses pypandoc to generate raw LaTeX, optionally sends that LaTeX to an AI refinement function with provider/model/API options, and saves a .tex file. While the overall skill description claims bidirectional Word ↔ LaTeX conversion and style-preserving reverse conversion, none of that reverse-conversion behavior appears in this supplied code chunk. The final console message mentions a separate back.py script, which suggests reverse conversion may exist elsewhere, but based only on this code chunk the declared description overstates the implemented behavior. There is no evidence of unrelated malicious or undeclared capabilities beyond the conversion pipeline and AI API usage.

Content

No source excerpt is available for this finding.

External Model or Provider Selection

High
Category
Excessive Agency
Confidence
97% confidence
Finding

The skill explicitly supports selecting arbitrary external model providers and custom endpoints for processing document contents, which can route sensitive files to third parties or attacker-controlled OpenAI-compatible base URLs. In this skill's context, the risk is elevated because the data being transmitted is the full content of user documents, and provider switching can bypass enterprise-approved data boundaries.

Content

Scanner excerpt · SKILL.md (reported line 67)May include surrounding context.

md
cd {SKILL_DIR}/scripts && python3 convert.py /path/to/doc.docx -p qwen

# Use DeepSeek with specific model
cd {SKILL_DIR}/scripts && python3 convert.py /path/to/doc.docx -p deepseek --model deepseek-chat

# Pandoc only (no AI)
cd {SKILL_DIR}/scripts && python3 convert.py /path/to/doc.docx --raw

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
94% confidence
Finding

The --noconfirm parameter suppresses pacman's interactive safety check, and when paired with sudo it creates a high-trust, low-friction path to immediate system changes. This is especially concerning in a skill installer because it reduces opportunities for the user to notice or stop unexpected behavior before privileged actions occur.

Content

Scanner excerpt · scripts/setup.sh (reported line 21)May include surrounding context.

sh
elif command -v brew &>/dev/null; then
        brew install pandoc
    elif command -v pacman &>/dev/null; then
        sudo pacman -S --noconfirm pandoc
    else
        echo "ERROR: Cannot auto-install Pandoc. Please install it manually:"
        echo "  https://pandoc.org/installing.html"

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill instructs the agent to access environment variables, read arbitrary input files, and write output files, but it declares no explicit tool scope or permissions. This creates an authorization gap where the runtime may grant broader file/env access than users expect, increasing the chance of unintended disclosure or misuse when handling sensitive documents and API keys.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill promotes sending document content to external AI providers during conversion but does not prominently warn that potentially sensitive document contents may leave the local environment. In a document-conversion skill, this context makes the issue more dangerous because users may process confidential contracts, research, HR, or legal files and assume conversion is local unless explicitly told otherwise.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The usage guide explicitly encourages sending document content to multiple external AI providers and even arbitrary OpenAI-compatible endpoints via --base-url, but it gives no warning that document contents may be transmitted off-device to third parties. Users may unknowingly upload sensitive, regulated, or proprietary Word documents to external services, creating confidentiality, compliance, and data residency risks.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The documentation states that .fword/ automatically stores a copy of the original document and metadata, including style and layout information, but it does not warn users that these local artifacts persist after conversion. This can expose sensitive content or metadata to other local users, backups, source control, or later accidental disclosure if users do not realize retention is occurring.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/ai_refiner.py (reported line 19)May include surrounding context.

python
"env_key": "ANTHROPIC_API_KEY",
    },
    "openai": {
        "base_url": "https://api.openai.com/v1",
        "default_model": "gpt-4o",
        "env_key": "OPENAI_API_KEY",
    },

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/ai_refiner.py (reported line 29)May include surrounding context.

python
"env_key": "DASHSCOPE_API_KEY",
    },
    "kimi": {
        "base_url": "https://api.moonshot.cn/v1",
        "default_model": "moonshot-v1-8k",
        "env_key": "MOONSHOT_API_KEY",
    },

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/ai_refiner.py (reported line 34)May include surrounding context.

python
"env_key": "MOONSHOT_API_KEY",
    },
    "minimax": {
        "base_url": "https://api.minimax.chat/v1",
        "default_model": "MiniMax-Text-01",
        "env_key": "MINIMAX_API_KEY",
    },

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/ai_refiner.py (reported line 39)May include surrounding context.

python
"env_key": "MINIMAX_API_KEY",
    },
    "deepseek": {
        "base_url": "https://api.deepseek.com/v1",
        "default_model": "deepseek-chat",
        "env_key": "DEEPSEEK_API_KEY",
    },

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The function sends raw LaTeX chunks, plus document metadata such as title and author, to third-party LLM providers without any explicit consent flow, warning, or data-classification check. Because converted documents may contain sensitive or proprietary content, this creates a real confidentiality risk through external transmission to multiple vendors.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

When AI refinement is enabled, the script sends the converted document text and metadata to a selectable external AI provider, but it does not provide an explicit warning or confirmation that document contents may leave the local environment. This is dangerous because users may process sensitive Word documents under the assumption that conversion is local, resulting in unintended disclosure of confidential content to third-party services.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
92% confidence
Finding

The script invokes sudo to install pandoc via apt, which performs privileged system modification during setup. Even though the command itself is straightforward, embedding sudo in a skill setup script increases risk because users may run it without fully realizing it will request elevated privileges and alter the base system.

Content

Scanner excerpt · scripts/setup.sh (reported line 17)May include surrounding context.

sh
if ! command -v pandoc &>/dev/null; then
    echo "Pandoc not found. Attempting to install..."
    if command -v apt &>/dev/null; then
        sudo apt install -y pandoc
    elif command -v brew &>/dev/null; then
        brew install pandoc
    elif command -v pacman &>/dev/null; then

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The setup script automatically installs a system package using privileged package-manager commands without a clear opt-in prompt or explicit warning that it will invoke sudo and modify the host system. In a skill installation context, this can surprise users, expand the trust boundary to system-level changes, and increase the chance of unintended package installation on the wrong host or environment.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
89% confidence
Finding

Using pacman with --noconfirm removes an important user review step and allows package installation to proceed non-interactively. In combination with sudo, this increases the risk of unintended system changes and makes the script more dangerous if run in an automated or mis-targeted environment.

Content

Scanner excerpt · scripts/setup.sh (reported line 21)May include surrounding context.

sh
elif command -v brew &>/dev/null; then
        brew install pandoc
    elif command -v pacman &>/dev/null; then
        sudo pacman -S --noconfirm pandoc
    else
        echo "ERROR: Cannot auto-install Pandoc. Please install it manually:"
        echo "  https://pandoc.org/installing.html"

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
93% confidence
Finding

The script invokes sudo for pacman-based installation, causing privileged package installation as part of skill setup. This is risky in shared, production, or tightly managed environments because a convenience script should not silently cross into root-level system administration.

Content

Scanner excerpt · scripts/setup.sh (reported line 21)May include surrounding context.

sh
elif command -v brew &>/dev/null; then
        brew install pandoc
    elif command -v pacman &>/dev/null; then
        sudo pacman -S --noconfirm pandoc
    else
        echo "ERROR: Cannot auto-install Pandoc. Please install it manually:"
        echo "  https://pandoc.org/installing.html"

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The dependency is specified with only a lower bound, which allows future installs to resolve to different upstream versions over time. This weakens build reproducibility and can unintentionally introduce vulnerable or breaking releases through normal dependency updates or supply-chain compromise.

Content

Scanner excerpt · scripts/requirements.txt (reported line 1)May include surrounding context.

text
pypandoc>=1.13
anthropic>=0.40.0
openai>=1.0.0
python-docx>=1.1.0

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
98% confidence
Finding

Using an unpinned version for the anthropic package means the installed version is not deterministic and may drift to a release with newly introduced security issues. In a skill that integrates external AI providers, supply-chain exposure is more relevant because this library likely handles API access and local processing.

Content

Scanner excerpt · scripts/requirements.txt (reported line 2)May include surrounding context.

text
pypandoc>=1.13
anthropic>=0.40.0
openai>=1.0.0
python-docx>=1.1.0
rich>=13.0.0

Unverifiable Dependency: anthropic has 4 known advisory(ies) (CVE-2026-34450 (Claude SDK for Python has Insecure Default File Permissions in Local Filesystem ); CVE-2026-34452 (Claude SDK for Python: Memory Tool Path Validation Race Condition Allows Sandbox); CVE-2026-34450 (The Claude SDK for Python provides access to the Claude API from Python applicat) +1 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The manifest does not pin anthropic, and the package has known advisories, so it is impossible to determine from this file whether deployments are using a fixed, non-affected release. This is more concerning in this skill because the SDK may interact with local files and external services, increasing the blast radius if an affected version is installed.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The openai package is not pinned to an exact version, so installations may pull different releases at different times. This creates avoidable supply-chain and stability risk, especially for a tool that depends on third-party SDK behavior for document conversion workflows.

Content

Scanner excerpt · scripts/requirements.txt (reported line 3)May include surrounding context.

text
pypandoc>=1.13
anthropic>=0.40.0
openai>=1.0.0
python-docx>=1.1.0
rich>=13.0.0

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
98% confidence
Finding

An unpinned python-docx dependency can resolve to varying versions across environments, making it harder to guarantee that known parser-related issues are avoided. Because this skill processes Word documents, the document-parsing library sits in a more security-sensitive path than a purely optional package.

Content

Scanner excerpt · scripts/requirements.txt (reported line 4)May include surrounding context.

text
pypandoc>=1.13
anthropic>=0.40.0
openai>=1.0.0
python-docx>=1.1.0
rich>=13.0.0

Unverifiable Dependency: python-docx has 2 known advisory(ies) (CVE-2016-5851 (Improper Restriction of XML External Entity Reference in python-docx); CVE-2016-5851 (python-docx before 0.8.6 allows context-dependent attackers to conduct XML Exter)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
97% confidence
Finding

python-docx has known historical XXE-related advisories, and without an exact version pin the installed release may be vulnerable or at least unverifiable from the manifest alone. Since this skill converts Word documents, a vulnerable parser could be exposed to attacker-controlled document input, making the context more dangerous than a generic utility.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.