Back to skill

Security audit

tax-filing

Security checks for vulnerabilities and agentic risk

Overview

This tax-filing skill is mostly coherent and not deceptive, but it needs review because it handles sensitive tax data with broad activation and recommends an unsafe system-level Python package install.

Review this skill before installing. It appears tax-focused and does not show hidden exfiltration or destructive behavior, but users should avoid sharing full SSNs or unnecessary identifiers, confirm before processing tax documents, install dependencies only in an isolated virtual environment with pinned versions, and manually verify generated tax forms before filing.

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
SKILL.md:144
Finding

Unpinned dependency installation bypasses system package protections

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:144 and scripts/update_form.py:34-37
Vulnerability Type: Unpinned third-party dependency installed into a system-managed Python environment
Risk Level: Medium

Affected code in SKILL.md:

text
The script automatically verifies that fields survived the write and warns if the output looks corrupted. Ensure pypdf is available: `pip install pypdf --break-system-packages`.

Affected code in scripts/update_form.py:

python
try:
    from pypdf import PdfReader, PdfWriter
except ImportError:
    print("ERROR: pypdf is not installed. Run: pip install pypdf --break-system-packages")
    sys.exit(1)

Technical Analysis

The recommended installation command resolves and installs the latest available pypdf release without a pinned version or cryptographic integrity hash. This prevents users from reproducing a reviewed dependency set and exposes installation to future compromised, malicious, or behaviorally incompatible releases.

The --break-system-packages option explicitly bypasses protections designed to prevent pip from modifying a system-managed Python environment. Installing in that environment can overwrite or conflict with packages used by unrelated applications. Package installation also executes package build and installation logic with the privileges of the invoking user.

The project does not retrieve or execute a remote payload itself; the risk arises when a user follows the documented dependency-installation instruction.

Attack Path

  1. A user attempts to run scripts/update_form.py without pypdf installed.
  2. The script or documentation instructs the user to run pip install pypdf --break-system-packages.
  3. The package installer resolves an uncontrolled current release from the configured package index.
  4. If the index, account, release, or dependency chain is compromised, malicious installation code can e ...[truncated 843 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove --break-system-packages from all installation instructions and error messages.
  2. Require installation in an isolated virtual environment:
    bash
    python3 -m venv .venv
    . .venv/bin/activate
    python -m pip install --require-hashes -r requirements.txt
    
  3. Add a reviewed lock or requirements file that pins pypdf and all transitive dependencies to exact versions.
  4. Record cryptographic hashes and use pip install --require-hashes.
  5. Periodically review and update the pinned dependency after compatibility and security testing.
  6. Change the runtime error to refer users to the locked installation procedure rather than suggesting an unrestricted package installation.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/update_form.py:50
Finding

Critical same-path safety invariant is enforced only with a Python assertion

Content
View full analysis

Vulnerability Details

File Location: scripts/update_form.py:50-55
Vulnerability Type: Removable security check leading to input-file truncation or corruption
Risk Level: Low

Affected code:

python
input_path = str(Path(input_path).resolve())
output_path = str(Path(output_path).resolve())
assert input_path != output_path, (
    f"output_path must differ from input_path to prevent corruption. "
    f"Got: {input_path}"
)

Technical Analysis

The code relies on assert to enforce the documented rule that input and output paths must differ. Python removes assertion statements when optimization is enabled, such as when the program is run with python -O or when PYTHONOPTIMIZE is set.

Once the assertion is removed, the function can accept identical input and output paths. Later, the destination is opened in write-binary mode:

python
with open(output_path, "wb") as f:
    writer.write(f)

Opening the source file with "wb" truncates it while PdfReader may still rely on lazily loaded objects from that same file. This is precisely the corruption condition the function claims to prevent.

This issue is primarily an integrity and availability weakness. It does not independently provide privilege escalation or remote code execution.

Attack Path

  1. The script is invoked with optimization enabled, for example:
    bash
    python -O scripts/update_form.py Form1040NR.pdf Form1040NR.pdf --set "field=value"
    
  2. Python removes the assert input_path != output_path check.
  3. The reader opens the source PDF and the writer copies its logical structure.
  4. The script opens the same path using "wb", immediately truncating the source file.
  5. Subsequent lazy reads or serialization operate against the truncated source.
  6. The tax PDF is corrupted or loses form-field structures and data.

The same path can also be supplied by a wrapper that imports `update_form( ...[truncated 558 chars]

Remediation
View remediation

Remediation Suggestions

  1. Replace the assertion with an unconditional runtime check:
    python
    if input_path == output_path:
        raise ValueError(
            f"output_path must differ from input_path; got {input_path}"
        )
    
  2. Retain canonical path resolution before comparison.
  3. Consider checking whether the paths identify the same file through hard links by using os.path.samefile() when both paths exist.
  4. Write output to a securely created temporary file in the destination directory and atomically replace the destination only after verification.
  5. Preserve the original input until the output has been successfully parsed and all requested fields have been verified.
  6. Add automated tests that execute under python -O and confirm that identical or aliased paths are rejected.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/update_form.py:94
Finding

Substring-based field verification can validate the wrong PDF form field

Content
View full analysis

Vulnerability Details

File Location: scripts/update_form.py:94-102
Vulnerability Type: Ambiguous identifier matching in post-write integrity verification
Risk Level: Low

Affected code:

python
for name, value in field_updates.items():
    # Match by short name (last segment without [0])
    matched = [v for k, v in fields.items() if name in k]
    if matched and str(matched[0]) == str(value):
        print(f"  Verified: {name} = {value}")
    elif matched:
        print(f"  WARNING: {name} expected '{value}' but got '{matched[0]}'")
    else:
        print(f"  WARNING: {name} not found in output fields")

Technical Analysis

Verification treats any field key containing the requested name as a match and then examines only the first result. This does not establish that the exact intended field was written.

IRS form fields use similar identifiers such as f1_5, f1_50, and f1_53. A requested short identifier can therefore match multiple full field paths. Dictionary iteration order, rather than unique field identity, determines which value is checked.

If the first unrelated match already contains the expected value, the script prints Verified even when the intended field was not updated. If multiple intended widgets exist, inspecting only the first match can also leave inconsistent copies undetected.

The flaw affects the trustworthiness of the post-write verification control. It does not itself permit access beyond the files and values already supplied to the script.

Attack Path

  1. A caller supplies an abbreviated or overlapping field name, such as one that is a substring of several full field identifiers.
  2. The PDF contains multiple keys matching that substring.
  3. The update operation fails to modify the intended field, modifies a different field, or leaves one copy unchanged.
  4. During verification, the list comprehension collects all substring matches.
  5. The scri ...[truncated 798 chars]
Remediation
View remediation

Remediation Suggestions

  1. Require callers to provide exact full field names and verify them using direct dictionary lookup:
    python
    if name not in fields:
        raise KeyError(f"Field not found: {name}")
    if str(fields[name]) != str(value):
        raise ValueError(
            f"Verification failed for {name}: "
            f"expected {value!r}, got {fields[name]!r}"
        )
    
  2. If short names must be supported, parse and normalize only the terminal field component rather than performing arbitrary substring matching.
  3. Reject ambiguous short names whenever zero or more than one full field path matches.
  4. Verify every widget associated with a logical field when duplicate widgets are expected.
  5. Treat missing, ambiguous, or mismatched updates as fatal errors and return a nonzero process status instead of printing warnings.
  6. Add tests using overlapping names such as f1_5, f1_50, and f1_53 to ensure false-positive verification is impossible.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (3)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description promises a broad US federal tax preparation assistant with decision-making, calculations, form selection, and complete filing support for both 1040 and 1040-NR workflows. The supplied code only implements a narrow PDF form field updater for existing fillable forms. While it is tax-related in that it mentions IRS forms and can fill PDF fields, it lacks the core advertised capabilities: no tax logic, no user guidance, no document interpretation, no filer-type routing, and no return preparation workflow. This is a material description-versus-behavior mismatch.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The trigger condition is very broad and instructs use whenever the user mentions taxes or related terms, which can cause the skill to activate for vague or tangential requests. In this context, over-activation is risky because the skill handles highly sensitive financial and identity data and may steer users into detailed tax workflows when they did not intend to share that information.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill is designed to collect and process sensitive tax information, including W-2s, 1099s, travel history, visa status, and treaty claims, but it does not present a clear warning about handling confidential personal and financial data. Without an explicit notice, users may overshare SSNs, employer IDs, addresses, or other regulated information without understanding the privacy and security implications.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.