Back to skill

Security audit

Math Worksheets

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its worksheet purpose, but it needs review because its math verifier has an unsafe parsing surface and its delivery instructions can send student materials through external channels without clear confirmation.

Review before installing. Use it only with trusted worksheet content, avoid including student names when possible, confirm the exact recipient before any messaging or email delivery, and prefer pinned dependencies or an isolated environment for SymPy and Tectonic. The verifier should be treated as code that processes user-influenced expressions, not as a sandboxed safety boundary.

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)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/verify.py:63
Finding

Unsafe SymPy parsing of JSON-controlled expressions

Content
View full analysis

Vulnerability Details

File Location: scripts/verify.py:63-103
Vulnerability Type: Unsafe expression evaluation
Risk Level: High

The verification file is generated from worksheet content and may therefore contain user-influenced values. Multiple fields from that file are passed directly to sympy.sympify or sympy.nsimplify without an allowlist, grammar validation, input-size limits, or process isolation.

python
elif ptype == "solve":
    x = symbols('x')
    expr = sympify(p["expr"])
    roots = sorted([nsimplify(r) for r in solve(expr, x)])
    expected = sorted([nsimplify(e) for e in p["expected"]])
    ok = roots == expected
    results.append((pid, "PASS" if ok else "FAIL",
        f"solve({p['expr']}) → {roots} (expected {expected})"))

elif ptype == "zeros":
    x = symbols('x')
    expr = sympify(p["expr"])
    roots = sorted(set([nsimplify(r) for r in solve(expr, x)]))
    expected = sorted(set([nsimplify(e) for e in p["expected"]]))
    ok = roots == expected
    results.append((pid, "PASS" if ok else "FAIL",
        f"zeros({p['expr']}) → {roots} (expected {expected})"))

elif ptype == "factor":
    x = symbols('x')
    expr = sympify(p["expr"])
    factored = str(factor(expr))
    expected = str(sympify(p["expected"]))
    ok = simplify(sympify(factored) - sympify(expected)) == 0
    results.append((pid, "PASS" if ok else "FAIL",
        f"factor({p['expr']}) → {factored} (expected {p['expected']})"))

elif ptype == "expand":
    x = symbols('x')
    expr = sympify(p["expr"])
    expanded = str(expand(expr))
    expected = str(sympify(p["expected"]))
    ok = simplify(sympify(expanded) - sympify(expected)) == 0
    results.append((pid, "PASS" if ok else "FAIL",
        f"expand({p['expr']}) → {expanded} (expected {p['expected']})"))

elif ptype == "eval":
    subs = {symbols(k): nsimplify(v) for k, v in p["at"].items()}
    expr = sympify(p["expr"])
...[truncated 2743 chars]
Remediation
View remediation

Remediation Suggestions

  1. Do not pass untrusted strings directly to sympify or nsimplify.
  2. Define and enforce a small arithmetic grammar supporting only required constructs, such as:
    • Integer and bounded rational literals
    • Explicitly approved variables such as x and y
    • Addition, subtraction, multiplication, division, and bounded exponentiation
    • A narrowly defined allowlist of mathematical functions
  3. Parse input into an abstract syntax tree and reject attribute access, indexing, comprehensions, imports, function definitions, unknown identifiers, and other Python constructs before creating SymPy objects.
  4. If SymPy parsing remains necessary, provide explicit restricted symbol and function dictionaries rather than relying on default parser namespaces.
  5. Validate the JSON schema before processing, including maximum limits for:
    • File size and problem count
    • Expression length and nesting depth
    • Integer digit count and exponent magnitude
    • Number of symbols and function calls
  6. Apply execution timeouts, memory limits, and CPU limits around each symbolic operation.
  7. Run verification in a sandboxed subprocess with no network access and access only to the verification file.
  8. Avoid exposing secrets or broad filesystem permissions to the verification process.
  9. Add adversarial tests covering parser injection, very large exponents, deeply nested expressions, expensive factorization, and symbolic equation-solving timeouts.
  10. Revise the documentation so that its security claims accurately describe the remaining parser risk.

T08 · Insecure Dependencies

Warning
Location
README.md:24
Finding

Unpinned third-party dependencies and mutable runtime package retrieval

Content
View full analysis

Vulnerability Details

File Location: README.md:24-33; scripts/compile.sh:22-33
Vulnerability Type: Dependency supply-chain weakness
Risk Level: Medium

The installation instructions retrieve current package-manager versions of Tectonic and SymPy without version constraints or integrity hashes:

bash
**Prerequisites:**
```bash
brew install tectonic   # LaTeX compiler — auto-downloads packages on first use

Python 3 is also required (standard on macOS). The skill uses it for model detection and answer verification.

sympy is required for answer verification:

bash
pip3 install sympy
text

The compilation wrapper then executes the discovered Tectonic binary, which may download missing LaTeX packages during compilation:

```bash
# Locate tectonic
TECTONIC=$(command -v tectonic 2>/dev/null || echo "/opt/homebrew/bin/tectonic")
if [[ ! -x "$TECTONIC" ]]; then
  echo "Error: tectonic not found. Install with: brew install tectonic" >&2
  exit 1
fi

mkdir -p "$OUT_DIR"

echo "Compiling: $(basename "$TEX_FILE") → $OUT_DIR/"
"$TECTONIC" "$TEX_FILE" --outdir "$OUT_DIR" 2>&1 | grep -v "^note: downloading"

Technical Analysis

brew install tectonic and pip3 install sympy resolve mutable package versions at installation time. The project provides no lock file, tested version range, package hash, signed artifact reference, or reproducible environment specification.

Tectonic additionally retrieves LaTeX resources on demand. Consequently, the effective dependency set can change after this Skill has been reviewed. The project does not pin a Tectonic bundle or document an integrity-verification policy for the downloaded resources.

This does not establish that the current upstream packages are malicious. It creates a supply-chain exposure in which compromise of an upstream release, package repository, mirror, maintainer account, or transitive dependency could introduce ...[truncated 1616 chars]

Remediation
View remediation

Remediation Suggestions

  1. Pin tested versions of Tectonic, Python, and SymPy instead of installing unconstrained latest releases.
  2. Provide a locked dependency specification, such as a requirements file containing hashes for Python packages.
  3. Recommend installing Python dependencies in an isolated virtual environment rather than into the global interpreter.
  4. Document the expected package repositories and require TLS and package-signature verification where supported.
  5. Publish checksums or signatures for prebuilt dependency artifacts used by the Skill.
  6. Pin or vendor a tested Tectonic resource bundle so compilation does not depend on mutable package retrieval.
  7. If runtime retrieval is unavoidable, restrict it to explicitly trusted endpoints and verify downloaded artifacts against pinned cryptographic hashes.
  8. Test dependency updates in a controlled build pipeline before changing the pinned versions.
  9. Add automated dependency vulnerability and provenance scanning to the release process.
  10. Run Tectonic with filesystem, network, CPU, and memory restrictions appropriate for processing generated LaTeX.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (13)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is about creating professional math worksheets and answer keys as PDFs using LaTeX/tectonic for K-12 topics. The supplied code does none of that. Instead, it is a utility script for checking locally configured AI model IDs in OpenClaw config files and classifying them as reasoning, strong non-reasoning, or none. This is a materially different primary purpose and involves undeclared local file access to configuration data. There is no worksheet generation, no PDF compilation, no LaTeX handling, and no math-content production in the code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description says the skill generates math worksheets and answer keys as PDFs using LaTeX compiled with tectonic. The supplied code chunk does something materially different: it runs an answer-verification pipeline over a JSON file using Python and sympy. This is not just an implementation detail of PDF generation; its explicit purpose, usage, dependencies, and exit codes are centered on validating answers before compilation. There is no evidence in this code of worksheet generation, LaTeX creation, or tectonic/PDF compilation. Therefore the code’s actual behavior does not accurately match the declared primary purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The description claims a worksheet-generation skill that compiles LaTeX into professional PDF worksheets and answer keys across many K-12 math topics with layout features like coordinate grids and geometric figures. The actual code chunk instead implements a verifier: it consumes a structured JSON file, checks expected answers using SymPy, prints PASS/FAIL/MANUAL statuses, and exits with status codes indicating whether compilation would be safe. That verification step may be related to a larger worksheet pipeline, but on its own it materially differs from the declared purpose and omits the headline capabilities (generation, formatting, LaTeX, PDF compilation). Therefore this is a clear description-behavior mismatch.

Content

No source excerpt is available for this finding.

Anti-Refusal Statement

High
Category
Anti-Refusal
Confidence
80% confidence
Finding

Skill instructs the agent to omit warnings, disclaimers, or ethical commentary. Stripping safety caveats hides risk from the user and is a common jailbreak preamble.

Content

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

md
No warning needed. Sub-agent writes the .tex files + verify script, announces completion.

Anti-Refusal Statement

High
Category
Anti-Refusal
Confidence
80% confidence
Finding

Skill instructs the agent to omit warnings, disclaimers, or ethical commentary. Stripping safety caveats hides risk from the user and is a common jailbreak preamble.

Content

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

md
| Status | Model examples | Action |
|---|---|---|
| `FOUND_REASONING` | DeepThink, o1, o3, R1 | Spawn silently, no warning |
| `FOUND_STRONG` | Claude Opus 4.x | Spawn silently, optional quiet note |
| `NONE` | Sonnet, Flash, GPT-4o | Use current model + show recommendation |

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The usage section invites very broad natural-language requests such as homework help, worksheets, and using a student's homework photo as guidance, without clearly constraining when the skill should activate or what inputs are acceptable. In an agent environment, vague triggers can cause accidental invocation on unrelated conversations or sensitive educational content, increasing the chance of unintended data handling or inappropriate autonomous actions.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill explicitly depends on fetching hosted JSON from GitHub and auto-downloading TeX packages, but it does not declare any tool scope or permissions. Undeclared network behavior weakens operator visibility and policy enforcement, making it easier for a skill to exfiltrate data or pull unreviewed remote content under the guise of normal execution.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The description says to use the skill when a user asks for 'homework help sheet' or 'answer key for any K-12 math topic,' alongside other broad phrasing. These triggers are not tightly constrained and may overlap with common educational requests that do not necessarily mean the user wants this specific PDF-generation workflow.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Line L119 states that no generated code is executed, yet the workflow explicitly requires writing /tmp/verify_TOPIC_DATE.json and then running verification against that generated file. Even if the file is data rather than executable code, the wording is contradictory because a generated artifact is in fact consumed by an execution step.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill extends from local worksheet generation into outbound transmission over Telegram, SMS/iMessage, and email, including student names and educational materials. That increases privacy and data-leakage risk because files may be sent through external channels without clear consent, destination validation, or data-minimization controls.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill instructs sending PDFs through messaging and email channels without explicit warning, consent flow, or privacy guidance, even though files may contain student names and educational records. This creates a realistic risk of accidental disclosure to the wrong recipient or unnecessary transmission of minors' information through third-party platforms.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The manifest scope is generation of math worksheets and answer keys as PDFs, but the instructions also permit printing via lpr. Printing is a separate real-world side effect beyond PDF generation and is not disclosed in the manifest description.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The manifest describes generating math worksheets as PDFs via LaTeX compilation, which makes local compilation expected. However, the script documentation explicitly states that Tectonic auto-downloads missing LaTeX packages on first use, introducing network access not mentioned in the skill description.

Content

No source excerpt is available for this finding.