Back to skill

Security audit

deterministic-calc-skill

Security checks for vulnerabilities and agentic risk

Overview

This skill is advertised as a deterministic calculator but includes broad code, shell, and filesystem capabilities, including an unsafe calculator fallback that can execute Python code.

Review before installing. Only use this skill in a tightly sandboxed environment, and do not expose calculate(), run_python(), run_shell(), read_file(), or write_file() to untrusted user or model-generated input. The safest path is to use only safe_eval() after adding resource limits, or choose a calculator skill without arbitrary execution and filesystem access.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (5)

T09 · Insecure Skill Coding Practices

Error
Location
__init__.py:152
Finding

Arbitrary Python Code Execution Through calculate() Fallback

Content
View full analysis

Vulnerability Details

File Location: __init__.py:152-172
Vulnerability Type: Unsafe expression interpolation leading to arbitrary code execution
Risk Level: Critical

Vulnerable Code:

python
def calculate(expression: str) -> Dict[str, Any]:
    try:
        # First attempt safe evaluation
        result = safe_eval(expression)

        if result["success"]:
            return result

        # If safe evaluation fails, execute it with Python
        return run_python(f"print({expression})")

Technical Analysis

safe_eval() uses an AST allowlist, but calculate() does not reject expressions that fail that validation. Instead, it interpolates the original expression directly into Python source and passes it to run_python(), which executes it using python3 -c.

Consequently, the AST validation is only a preliminary attempt rather than a security boundary. Any valid Python expression rejected by the allowlist can reach unrestricted Python execution. For example:

python
calculate('__import__("os").system("id")')

The import expression is rejected by safe_eval(), after which the application constructs and executes:

python
print(__import__("os").system("id"))

No shell metacharacters are required because the injected value is executed directly as Python source.

Attack Path

  1. An attacker supplies a calculation expression containing non-allowlisted Python functionality.
  2. safe_eval() parses the input and returns a failure because the expression contains an unsupported AST node or function.
  3. calculate() inserts the unchanged input into print(...).
  4. run_python() invokes python3 -c with the generated source.
  5. The payload executes with the operating-system permissions of the skill process.
  6. The attacker can use Python modules to execute processes, access files, or communicate over the network.

Impact Assessment

Successful ...[truncated 509 chars]

Remediation
View remediation

Remediation Suggestions

  • Remove the fallback to run_python() completely. If safe_eval() rejects an expression, return the validation error.
  • Add required mathematical functions and operators individually to a strict AST allowlist rather than invoking a general-purpose interpreter.
  • Never interpolate user-controlled expressions into Python source.
  • Apply input-length, AST-depth, operand-size, result-size, memory, and execution-time limits.
  • Run calculation workers under a dedicated low-privilege account with no sensitive filesystem or network access.
  • Add regression tests proving that payloads involving __import__, attributes, comprehensions, lambdas, and other unsupported nodes cannot execute.

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:146
Finding

Security Documentation Incorrectly Describes calculate() as Sandbox-Safe

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:146-150; related guidance at README.md:151-163
Vulnerability Type: Misleading security documentation and unsafe deployment guidance
Risk Level: High

Relevant Documentation, translated into English from the source:

markdown
## Security Notes

- `calculate()` and `safe_eval()` are sandbox-safe.
- `run_python()` and `run_shell()` can execute arbitrary code and must be used carefully.
- In production, it is recommended to expose only `calculate()` and `safe_eval()`.

Contradicting Implementation:

python
result = safe_eval(expression)

if result["success"]:
    return result

# If safe_eval fails, try execution with Python
return run_python(f"print({expression})")

Technical Analysis

The documentation explicitly characterizes calculate() as sandbox-safe and recommends exposing it in production. The implementation contradicts that claim: an expression rejected by safe_eval() is passed to unrestricted Python execution.

This creates a dangerous trust-boundary failure. Administrators and integrating agents may reasonably expose calculate() to untrusted input because the project documentation identifies it as an approved production API.

Attack Path

  1. An operator follows the documented recommendation and exposes calculate() to users or an AI agent.
  2. The operator does not add an external execution sandbox because the function is documented as sandbox-safe.
  3. An attacker submits an expression such as __import__("os").system("id").
  4. The safe evaluator rejects the expression.
  5. The fallback executes the expression as unrestricted Python.
  6. The attacker obtains code execution in the deployment environment.

Impact Assessment

The misleading guidance makes the code-execution vulnerability substantially more likely to be exposed remotely. Exploitation can provide the same privileges as the hosting pro ...[truncated 92 chars]

Remediation
View remediation

Remediation Suggestions

  • Do not describe calculate() as sandbox-safe until its unrestricted execution fallback has been removed.
  • Clearly document the accepted expression grammar and all resource limits.
  • State that callers must treat every calculation expression as untrusted input.
  • Update both SKILL.md and README.md so their risk descriptions are consistent.
  • Add prominent migration guidance for deployments that may already expose calculate().
  • Document that process-level isolation remains necessary even after AST validation is corrected.

T05 · Unauthorized Access and Privilege Escalation

Error
Location
__init__.py:186
Finding

Unrestricted Shell, Python, and Filesystem Primitives Violate Least Privilege

Content
View full analysis

Vulnerability Details

File Location: __init__.py:186-203, __init__.py:235-254, __init__.py:286-326
Vulnerability Type: Excessive execution and filesystem capabilities without authorization or sandboxing
Risk Level: High

Vulnerable Code:

python
def run_python(code: str, timeout: int = 30) -> Dict[str, Any]:
    try:
        result = subprocess.run(
            ["python3", "-c", code],
            capture_output=True,
            text=True,
            timeout=timeout
        )
python
def run_shell(command: str, timeout: int = 30, shell: bool = True) -> Dict[str, Any]:
    try:
        result = subprocess.run(
            command,
            shell=shell,
            capture_output=True,
            text=True,
            timeout=timeout
        )
python
def read_file(path: str, max_bytes: int = 1024 * 1024) -> Dict[str, Any]:
    try:
        with open(path, 'r', encoding='utf-8') as f:
            content = f.read(max_bytes)
python
def write_file(path: str, content: str) -> Dict[str, Any]:
    try:
        with open(path, 'w', encoding='utf-8') as f:
            f.write(content)

Technical Analysis

The skill's stated purpose is deterministic calculation, but it exports primitives for arbitrary Python execution, shell execution, file reading, and file overwriting. These functions contain no authentication, authorization, command allowlist, path allowlist, canonical-path validation, privilege reduction, or operating-system sandbox.

run_shell() is especially hazardous because shell=True is enabled by default, causing the supplied string to be interpreted by a command shell. The timeout limits runtime but does not restrict what the command can access or change.

read_file() and write_file() accept arbitrary absolute or relative paths. They do not constrain access to a dedicated workspace and do not prevent path trav ...[truncated 1330 chars]

Remediation
View remediation

Remediation Suggestions

  • Remove shell, Python, and general filesystem APIs from the calculation skill unless they are essential.
  • Separate dangerous functionality into an explicitly privileged component with independent authorization.
  • Default shell execution to disabled; if commands are unavoidable, use argument arrays with shell=False and a strict executable and argument allowlist.
  • Run execution workers in a locked-down container or sandbox with a read-only root filesystem, no host mounts, no secrets, no unnecessary capabilities, and network access disabled by default.
  • Restrict filesystem operations to a dedicated workspace. Resolve paths canonically and verify that the resolved path remains beneath the authorized root.
  • Defend against symlink races using descriptor-based filesystem operations where supported.
  • Run under a dedicated low-privilege operating-system account.
  • Add explicit authorization checks and security logging around every privileged operation.

T08 · Insecure Dependencies

Warning
Location
README.md:31
Finding

Mutable npx Package Execution Is Not Version or Integrity Pinned

Content
View full analysis

Vulnerability Details

File Location: README.md:31-35; additional occurrences at SKILL.md:27-30 and publish.sh:60-71
Vulnerability Type: Unpinned executable package in installation and publishing workflows
Risk Level: Medium

Vulnerable Installation Command:

bash
npx clawhub install deterministic-calc

Vulnerable Publishing Commands:

bash
npx clawhub login
npx clawhub publish

Technical Analysis

The documented workflows invoke the clawhub package through npx without an exact version or integrity constraint. If the package is not already installed locally, npx can resolve and execute a mutable package version from the configured registry.

The effective code executed by these commands can therefore change after this skill has been reviewed. A compromised registry account, package takeover, or malicious future release could result in unintended code running on developer or user systems.

No malicious dependency is embedded in this project, and the finding concerns the unsafe mutability of the documented supply-chain execution path.

Attack Path

  1. A user or maintainer follows the installation or publishing instructions.
  2. npx resolves the current package version from the configured registry.
  3. An attacker has compromised the package, its maintainer account, or the registry resolution path.
  4. npx downloads and executes the attacker-controlled release.
  5. The payload runs with the invoking user's permissions and can access that user's files, credentials, and network environment.

Impact Assessment

A compromised package could execute code under the developer or installer account. For publishing users, this may expose repository credentials, package-registry tokens, source code, SSH material, and other local secrets. The exact scope depends on the invoking user's privileges.

Remediation
View remediation

Remediation Suggestions

  • Pin an audited exact package version in every npx command.
  • Use a lockfile and verify package integrity metadata where the workflow supports it.
  • Configure and document the expected trusted registry.
  • Install reviewed tooling as a development dependency and invoke the locked local binary rather than resolving a mutable package on demand.
  • Use multi-factor authentication and short-lived, narrowly scoped tokens for publishing.
  • Run publishing tools in an isolated environment with only the minimum credentials and filesystem access required.

T09 · Insecure Skill Coding Practices

Warning
Location
__init__.py:24
Finding

Resource-Exhaustion Controls Can Be Bypassed Through the Allowed pow() Function

Content
View full analysis

Vulnerability Details

File Location: __init__.py:24-45, __init__.py:60-78, __init__.py:91-104
Vulnerability Type: Incomplete computational resource controls
Risk Level: Medium

Relevant Code:

python
ALLOWED_OPERATORS = {
    ast.Add: operator.add,
    ast.Sub: operator.sub,
    ast.Mult: operator.mul,
    ast.Div: operator.truediv,
    ast.FloorDiv: operator.floordiv,
    ast.Mod: operator.mod,
    ast.Pow: operator.pow,
    ast.USub: operator.neg,
    ast.UAdd: operator.pos,
}

ALLOWED_FUNCTIONS = {
    'abs': abs,
    'round': round,
    'min': min,
    'max': max,
    'sum': sum,
    'len': len,
    'pow': pow,
}
python
if isinstance(node, ast.BinOp):
    left = _safe_eval_node(node.left)
    right = _safe_eval_node(node.right)
    op_type = type(node.op)

    if op_type not in ALLOWED_OPERATORS:
        raise ValueError(f"Unsupported operator: {op_type}")

    if op_type in (ast.Div, ast.FloorDiv, ast.Mod) and right == 0:
        raise ValueError("Division by zero")

    if op_type == ast.Pow and isinstance(right, (int, float)) and abs(right) > 1000:
        raise ValueError("Exponent is too large")

    op_func = ALLOWED_OPERATORS[op_type]
    return op_func(left, right)
python
if isinstance(node, ast.Call):
    if not isinstance(node.func, ast.Name):
        raise ValueError("Only simple function calls are supported")

    func_name = node.func.id

    if func_name not in ALLOWED_FUNCTIONS:
        raise ValueError(f"Unsupported function: {func_name}")

    func = ALLOWED_FUNCTIONS[func_name]
    args = [_safe_eval_node(arg) for arg in node.args]

    return func(*args)

Technical Analysis

The evaluator limits exponents greater than 1000 only when exponentiation is represented as an ast.BinOp using the ** operator. The independently allowed pow() function is invoked without equivalent argument ...[truncated 1142 chars]

Remediation
View remediation

Remediation Suggestions

  • Apply the same validated exponent bounds to pow() that are applied to the ** operator.
  • Prefer a wrapper around every allowed function rather than exposing Python built-ins directly.
  • Limit input length, AST node count, AST depth, numeric operand size, collection length, and estimated result size.
  • Execute calculations in an isolated worker with strict CPU, memory, and wall-clock limits.
  • Terminate and replace workers that exceed resource limits.
  • Add tests covering pow() and nested arithmetic designed to bypass each resource constraint.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (25)

Context-Inappropriate Capability

Critical
Category
Not specified by scanner
Confidence
100% confidence
Finding

Arbitrary Python execution is not justified by the stated purpose and gives this skill general code-execution capability. In an agent environment, that enables direct compromise of host data and system integrity if user or model-controlled input reaches this function.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Critical
Category
Not specified by scanner
Confidence
100% confidence
Finding

Arbitrary shell execution is unrelated to the advertised deterministic-calculation purpose and substantially broadens the attack surface. In an agent context, this can be invoked on attacker-influenced text, turning a calculation skill into a remote command-execution primitive.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documented run_python() function and related examples allow arbitrary Python code execution, which exceeds the needs of deterministic arithmetic. In an agent setting, this creates a direct arbitrary-code-execution primitive that can be abused to read secrets, modify files, spawn subprocesses, or pivot into further compromise if the model or user can influence inputs.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill is presented as a deterministic calculation utility, yet it documents arbitrary shell execution via run_shell() and CLI shell. That capability is far broader than the stated purpose and would allow command execution on the host if exposed to model-generated or user-controlled input, enabling file access, exfiltration, persistence, or system compromise.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill is framed as a deterministic calculator, but it also exposes run_python() and run_shell() that can execute arbitrary code and shell commands. This mismatch is dangerous because users or calling agents may trust the skill for narrow math operations while inadvertently granting a broad execution surface that can lead to command execution, data access, or system compromise if untrusted input reaches these functions.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill branding and description emphasize deterministic calculation, but the implementation also includes shell execution, Python execution, file read/write, and parsing helpers. This mismatch is dangerous because it can cause integrators, reviewers, or calling agents to trust the skill for low-risk math tasks while unknowingly exposing high-risk capabilities.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The safe_eval() docstring claims no code-injection risk, but the main exposed calculation path undermines that guarantee by delegating failures to arbitrary Python execution in calculate(). This creates a misleading safety model that can result in unsafe deployment assumptions.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The calculate() API presents itself as a calculator but silently falls back to run_python(f"print({expression})") when safe parsing fails. That means malformed or intentionally crafted 'expressions' can trigger arbitrary Python execution through an interface that appears much safer than it is, increasing the chance of unsafe use by downstream agents or users.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill exposes arbitrary Python execution without any warning or confirmation. Because this is embedded in a seemingly benign utility module, users or orchestrators may invoke it without appreciating that it grants full code execution.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill exposes shell-command execution with no user-facing warning, approval, or confirmation despite the severe consequences of misuse. In agent settings, absence of an interaction barrier increases the likelihood that prompt-influenced input is executed directly.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill documentation is written entirely in Chinese, including the core description, usage guidance, and safety notes, with no indication that users may choose another language. The policy requires flagging language or locale constraints when they are imposed without user opt-in or clear justification.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The README makes a strong safety claim that safe_eval has 'no code injection risk' and is sandboxed, while the same module exposes dangerous execution primitives and admits calculate() may invoke Python execution. This mismatch can mislead integrators into overtrusting the package, causing unsafe deployment patterns where hostile input is routed to broader execution paths under a false sense of safety.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This markdown file contains user-facing instructions and safety guidance only in Chinese, which effectively forces a specific language/locale for use of the skill. The policy allows locale constraints when the skill offers a choice or clearly documents a justified regional limitation, neither of which is present here.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding

The installation command uses npx clawhub install deterministic-calc without pinning a specific package or version, which can fetch whatever version is current at install time. This creates supply-chain risk because a compromised upstream package, typosquatted dependency, or malicious update could be executed during installation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The module-level natural-language description is written entirely in Chinese and does not offer any language or locale choice. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
98% confidence
Finding

This function executes arbitrary Python code via python3 -c with attacker-controlled input. Even though it avoids shell=True, it still provides full code-execution capability, enabling filesystem access, network calls, data exfiltration, and process spawning if exposed to untrusted input.

Content

Scanner excerpt · __init__.py (reported line 198)May include surrounding context.

python
dict: {"success": bool, "stdout": str, "stderr": str, "exit_code": int}
    """
    try:
        result = subprocess.run(
            ["python3", "-c", code],
            capture_output=True,
            text=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
100% confidence
Finding

This function executes arbitrary shell commands and uses shell=True, which is especially dangerous because any untrusted string is interpreted by the shell. That permits command injection, chaining, redirection, environment access, destructive system actions, and easy exfiltration of secrets.

Content

Scanner excerpt · __init__.py (reported line 248)May include surrounding context.

python
dict: {"success": bool, "stdout": str, "stderr": str, "exit_code": int}
    """
    try:
        result = subprocess.run(
            command,
            shell=shell,
            capture_output=True,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The write_file function opens paths in 'w' mode, which can overwrite existing files, making it a data-affecting operation. The code includes only an internal docstring and no user-facing warning, confirmation, or visible disclosure about potential overwrites.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This shell script contains user-facing comments and echo output entirely in Chinese, including operational publishing instructions. Because the file provides no opt-in, alternative locale, or justification for a Chinese-only experience, it violates the language/locale policy criterion for natural-language content.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
89% confidence
Finding

The script instructs users to run npx clawhub without pinning a specific package version, which can fetch and execute whatever version is current at execution time. This creates a supply-chain risk: a compromised, malicious, or incompatible newly published version could be executed during login or publish operations.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
89% confidence
Finding

The publish step uses npx clawhub without a pinned version, so the exact code executed depends on the latest package available from the registry at runtime. In a publishing workflow this is especially sensitive because the invoked tool may access credentials, modify package contents, or publish artifacts if the package supply chain is compromised.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
86% confidence
Finding

Using npx clawhub for search without pinning still causes untrusted package resolution at runtime and may execute unexpected code from the registry. Although the search operation is less privileged than publishing, it still expands the attack surface through arbitrary package execution on the user's machine.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
86% confidence
Finding

The installation instruction recommends npx clawhub install without version pinning, exposing users to registry-based supply-chain attacks or unexpected behavior changes over time. Because this is a user-facing install path, many users may follow it directly, amplifying impact if a malicious version is served.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The natural-language description is written entirely in Chinese, which imposes a specific language on users without indicating any language choice or region-specific justification. This can violate language/locale policy expectations for skills that should be usable without a forced locale assumption.

Content

No source excerpt is available for this finding.