Back to skill

Security audit

Python Sdk

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real inference.sh Python SDK documentation skill, but some examples could expose files, conversations, or local code execution if copied without extra safeguards.

Install or use this skill only when you specifically intend to work with inference.sh. Do not copy the eval() calculator examples into an agent or app; use a safe arithmetic parser instead. Treat local file paths, attachments, uploaded files, webhook payloads, and saved chat history as sensitive data that may leave the machine or persist on disk, and pin package or skill versions in controlled environments.

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

T09 · Insecure Skill Coding Practices

Error
Location
references/tool-builder.md:253
Finding
Agent-Controlled Expressions Are Executed with Python eval()## Vulnerability Details **File Location**: `references/tool-builder.md:253-260` and `references/tool-builder.md:362-369` **Vulnerability Type**: Arbitrary Python code execution through unsafe expression evaluation **Risk Level**: High ### Vulnerable Code ```python def handle_tool(call): if call.name == "greet": result = f"Hello, {call.args['name']}!" elif call.name == "calculate": result = eval(call.args['expression']) else: result = {"error": f"Unknown tool: {call.name}"} agent.submit_tool_result(call.id, result) ``` The complete example repeats the same unsafe pattern: ```python def handle_tool(call): if call.name == "calculate": try: result = eval(call.args["expression"]) agent.submit_tool_result(call.id, {"result": result}) except Exception as e: agent.submit_tool_result(call.id, {"error": str(e)}) ``` ### Technical Analysis The calculator tool passes an agent-generated string directly to Python's `eval()`. Tool arguments can be influenced by user messages, retrieved content, or indirect prompt injection. `eval()` does not restrict input to arithmetic: it can resolve Python names, invoke functions, import modules through built-ins, and interact with the local environment. Exception handling in the second example does not establish a security boundary. It only reports failures after the expression has already been evaluated. The calculator tool also does not require human approval in the complete example. Although this code appears in documentation rather than an automatically executed script, users who copy the documented handler would create an arbitrary-code-execution vulnerability in the host application. ### Attack Path 1. An attacker sends a malicious message to an application using the documented calculator tool, or places malicious instructions in content consumed by the agent. 2. The ...[truncated 887 chars]
Remediation
## Remediation Suggestions - Remove every use of `eval()` for agent- or user-controlled expressions. - Use a dedicated arithmetic parser or an allowlisted Abstract Syntax Tree evaluator. - If using `ast.parse`, permit only numeric constants and explicitly approved arithmetic operators. Reject calls, names, attributes, comprehensions, subscriptions, imports, and assignments. - Enforce expression length, numeric magnitude, recursion-depth, and execution-time limits to prevent denial of service. - Validate tool arguments independently of the model and return a structured validation error for unsupported syntax. - Consider requiring approval for high-impact client tools, but do not treat approval as a substitute for safe parsing. - Run tool handlers in a restricted process with minimal filesystem, environment, and network access.

T08 · Insecure Dependencies

Warning
Location
SKILL.md:14
Finding
Mutable Third-Party Packages Are Installed Without Version or Integrity Pinning## Vulnerability Details **File Location**: `SKILL.md:14-16`, `SKILL.md:34-39`, and `SKILL.md:462-473` **Vulnerability Type**: Unpinned dependency installation and supply-chain exposure **Risk Level**: Medium ### Vulnerable Code ```bash pip install inferencesh ``` ```bash # Standard installation pip install inferencesh # With async support pip install inferencesh[async] ``` The Skill also recommends mutable external Skill installations: ```bash # JavaScript SDK npx skills add inference-sh/skills@javascript-sdk # Full platform skill (all 150+ apps via CLI) npx skills add inference-sh/skills@inference-sh # LLM models npx skills add inference-sh/skills@llm-models # Image generation npx skills add inference-sh/skills@ai-image-generation ``` ### Technical Analysis These commands resolve and install the latest package or Skill version available at execution time. No exact version, lockfile, checksum, signature, or immutable commit is specified. Consequently, the code executed by a user can differ from the dependency state that existed when this Skill was audited. This is a supply-chain hardening deficiency rather than evidence that the named packages are currently malicious. The risk arises if a registry account, upstream repository, release process, or transitive dependency is compromised. ### Attack Path 1. An upstream package, Skill repository, maintainer account, or transitive dependency is compromised. 2. A malicious release is published under the expected package or Skill name. 3. A user follows the unpinned installation command. 4. The package manager resolves the compromised mutable release. 5. Malicious installation or runtime code executes with the user's permissions. ### Impact Assessment A compromised dependency can execute code with the privileges of the installing or running user. Potential impact includes credential theft, source-code modification, filesystem access, u ...[truncated 177 chars]
Remediation
## Remediation Suggestions - Pin the Python SDK to a reviewed exact version, for example `inferencesh==X.Y.Z`. - Provide a lockfile or requirements file containing hashes and install with hash verification where supported. - Pin external Skills to immutable reviewed versions, release tags, or commit identifiers rather than mutable aliases. - Document the canonical package registry and upstream repository so users can detect dependency confusion or spoofed sources. - Review transitive dependencies and use automated vulnerability and provenance scanning. - Test upgrades separately and update pins only after review. - Recommend installation in an isolated virtual environment under an unprivileged account.

T09 · Insecure Skill Coding Practices

Warning
Location
references/files.md:37
Finding
File Upload Example Enables Public Access Without a Security Warning## Vulnerability Details **File Location**: `references/files.md:37-50` **Vulnerability Type**: Unintended public disclosure of uploaded files **Risk Level**: Medium ### Vulnerable Code ```python from inferencesh import UploadFileOptions file = client.upload_file( "/path/to/document.pdf", UploadFileOptions( filename="custom_name.pdf", # Custom filename content_type="application/pdf", # MIME type path="/documents/reports", # Storage path public=True # Publicly accessible ) ) ``` A shortened version also appears in `SKILL.md:130-136`. ### Technical Analysis The upload-options example explicitly sets `public=True`, making the uploaded object publicly accessible, but does not explain the confidentiality, retention, indexing, or direct-link implications. Users frequently copy documentation examples unchanged. A user may therefore expose a confidential document while intending only to submit it to an inference application. Public upload capability is relevant to the declared file-management functionality, but enabling it in the primary example exceeds the minimum access needed for ordinary private processing. Public access should be an explicit opt-in demonstrated separately with a prominent warning. The base64 example at `references/files.md:67-74` is not itself a covert exfiltration mechanism. It reads a specifically selected image and converts it to a standard data URI for an explicitly documented remote inference request. The risk in this finding is the public access setting, not base64 encoding. ### Attack Path 1. A developer copies the documented upload-options example. 2. The developer changes the path to a sensitive report or other confidential file but leaves `public=True`. 3. The SDK uploads the file and creates a publicly accessible object or direct URL. 4. The URL is exposed through logs, application output, browser ...[truncated 553 chars]
Remediation
## Remediation Suggestions - Change the default example to `public=False` or omit the public option so that the secure SDK default applies. - Move public-upload behavior to a separate, explicitly labeled example. - Add a warning that public URLs may be accessible to anyone who obtains them. - Document access-control semantics, retention periods, deletion procedures, and whether links expire. - Recommend private uploads and short-lived signed URLs for confidential content. - Advise users not to place sensitive values in filenames or storage paths. - Add an explicit confirmation step in applications before changing an object from private to public.

T09 · Insecure Skill Coding Practices

Warning
Location
references/agent-patterns.md:151
Finding
Conversation History Is Persisted in Plaintext with Default File Permissions## Vulnerability Details **File Location**: `references/agent-patterns.md:151-168` **Vulnerability Type**: Insecure storage of potentially sensitive conversation data **Risk Level**: Medium ### Vulnerable Code ```python client = inference(api_key="inf_...") def save_chat(agent, filepath): chat = agent.get_chat() with open(filepath, 'w') as f: json.dump(chat, f) def load_chat(agent, filepath): try: with open(filepath, 'r') as f: chat = json.load(f) # Restore conversation by replaying messages for msg in chat['messages']: if msg['role'] == 'user': agent.send_message(msg['content']) except FileNotFoundError: pass ``` ### Technical Analysis The example writes the entire conversation history to an arbitrary plaintext file using process-default permissions. Conversations can contain personal data, credentials, proprietary material, or other secrets. The example provides no redaction, encryption, restrictive file mode, retention policy, integrity protection, or warning against committing the file to source control. The load routine also replays stored user messages into the remote agent. If the conversation file can be modified by another local process, attacker-controlled messages may be sent to the agent in a later session. The code does not directly persist system-level rules, so it does not establish confirmed agent-memory poisoning, but the absence of integrity controls creates a secondary local tampering risk. ### Attack Path 1. A user discusses confidential information with the agent. 2. `save_chat` serializes the complete chat to a plaintext JSON file. 3. The file inherits default permissions and may be included in backups, synchronization services, or source-control operations. 4. Another local user, compromised process, or unintended repository reader obtains the file. 5. The party ...[truncated 548 chars]
Remediation
## Remediation Suggestions - Store conversation data in a protected application-data directory rather than the working directory. - Create files with owner-only permissions, such as mode `0600`, and ensure parent directories are not shared. - Encrypt sensitive conversation history at rest using managed keys where the threat model requires it. - Redact credentials, tokens, personal data, and other secrets before persistence. - Implement explicit retention limits and secure deletion procedures. - Add conversation files to source-control ignore rules and warn against placing them in synchronized or publicly backed-up directories. - Authenticate or integrity-protect stored history before replaying it. - Validate the stored schema and require user confirmation before replaying messages that can cause external or privileged actions.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (28)

Memory Manipulation

High
Category
Memory Poisoning
Content
# Multi-turn conversation
response = agent.send_message("Tell me more")

# Reset conversation
agent.reset()

# Get chat history
Confidence
80% confidence
Finding
Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Missing User Warnings

High
Confidence
98% confidence
Finding
The example documents a `public=True` upload option without a strong warning that the resulting file may be publicly accessible to anyone with the URL or broader access scope, depending on backend behavior. Users may enable this for convenience and accidentally expose confidential documents.

Vague Triggers

Medium
Confidence
89% confidence
Finding
The manifest description contains very broad trigger phrases such as 'python integration', 'python api', and 'programmatic ai', which can cause the skill to activate for generic Python requests outside its intended scope. Over-broad routing increases the chance that users are steered into using this skill, its tools, or its external service patterns in contexts where they did not explicitly request inference.sh.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The file handling section demonstrates automatic and manual uploads of local files to a remote service without an explicit warning that local file contents will be transmitted off-host. In an agent setting, this omission can lead users to unintentionally expose sensitive local data, especially because the examples normalize passing filesystem paths directly.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The webhook example sends data to an external Slack webhook endpoint but does not clearly warn that messages and parameters may be transmitted to third-party services. In agent workflows, this can result in unintended disclosure of prompts, tool outputs, secrets-derived content, or other sensitive data to external systems.

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.

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.

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.

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.

Session Persistence

Medium
Category
Rogue Agent
Content
## Conversation Memory Pattern

Maintain context across sessions:

```python
import json
Confidence
82% confidence
Finding
The pattern explicitly encourages session persistence across runs, which increases exposure of sensitive conversational context beyond the active session. In this SDK documentation, that guidance is more dangerous because agent conversations often include credentials, user data, proprietary content, and prior tool results that may be stored and replayed later without adequate safeguards.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The conversation memory example persists the full chat history to a local JSON file and later reloads it without any warning, minimization, encryption, or access-control guidance. In an agent/SDK context, chats commonly contain secrets, personal data, internal prompts, or tool outputs, so this pattern can lead to unintended retention and disclosure of sensitive information.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The documentation shows that passing a local file path causes the SDK to automatically upload that file to a remote service, but it does not clearly warn users that file contents will leave the local machine. This can lead to unintentional disclosure of sensitive files if developers assume a path is only referenced locally rather than transmitted.

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Content
### Basic Upload

```python
file = client.upload_file("/path/to/image.png")
print(file["uri"])  # inf://files/abc123

result = client.run({
Confidence
55% confidence
Finding
Data is uploaded to cloud storage (S3 / GCS / Azure Blob). This may be a legitimate backup or exfiltration to an external bucket. Manual review is recommended.

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Content
### Basic Upload

```python
file = client.upload_file("/path/to/image.png")
print(file["uri"])  # inf://files/abc123

result = client.run({
Confidence
55% confidence
Finding
Data is uploaded to cloud storage (S3 / GCS / Azure Blob). This may be a legitimate backup or exfiltration to an external bucket. Manual review is recommended.

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Content
### Basic Upload

```python
file = client.upload_file("/path/to/image.png")
print(file["uri"])  # inf://files/abc123

result = client.run({
Confidence
55% confidence
Finding
Data is uploaded to cloud storage (S3 / GCS / Azure Blob). This may be a legitimate backup or exfiltration to an external bucket. Manual review is recommended.

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Content
### Basic Upload

```python
file = client.upload_file("/path/to/image.png")
print(file["uri"])  # inf://files/abc123

result = client.run({
Confidence
55% confidence
Finding
Data is uploaded to cloud storage (S3 / GCS / Azure Blob). This may be a legitimate backup or exfiltration to an external bucket. Manual review is recommended.

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Content
### Basic Upload

```python
file = client.upload_file("/path/to/image.png")
print(file["uri"])  # inf://files/abc123

result = client.run({
Confidence
55% confidence
Finding
Data is uploaded to cloud storage (S3 / GCS / Azure Blob). This may be a legitimate backup or exfiltration to an external bucket. Manual review is recommended.

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Content
### Basic Upload

```python
file = client.upload_file("/path/to/image.png")
print(file["uri"])  # inf://files/abc123

result = client.run({
Confidence
55% confidence
Finding
Data is uploaded to cloud storage (S3 / GCS / Azure Blob). This may be a legitimate backup or exfiltration to an external bucket. Manual review is recommended.

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Content
### Basic Upload

```python
file = client.upload_file("/path/to/image.png")
print(file["uri"])  # inf://files/abc123

result = client.run({
Confidence
55% confidence
Finding
Data is uploaded to cloud storage (S3 / GCS / Azure Blob). This may be a legitimate backup or exfiltration to an external bucket. Manual review is recommended.

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Content
### Basic Upload

```python
file = client.upload_file("/path/to/image.png")
print(file["uri"])  # inf://files/abc123

result = client.run({
Confidence
55% confidence
Finding
Data is uploaded to cloud storage (S3 / GCS / Azure Blob). This may be a legitimate backup or exfiltration to an external bucket. Manual review is recommended.

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Content
### Basic Upload

```python
file = client.upload_file("/path/to/image.png")
print(file["uri"])  # inf://files/abc123

result = client.run({
Confidence
55% confidence
Finding
Data is uploaded to cloud storage (S3 / GCS / Azure Blob). This may be a legitimate backup or exfiltration to an external bucket. Manual review is recommended.

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Content
### Basic Upload

```python
file = client.upload_file("/path/to/image.png")
print(file["uri"])  # inf://files/abc123

result = client.run({
Confidence
55% confidence
Finding
Data is uploaded to cloud storage (S3 / GCS / Azure Blob). This may be a legitimate backup or exfiltration to an external bucket. Manual review is recommended.

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Content
### Basic Upload

```python
file = client.upload_file("/path/to/image.png")
print(file["uri"])  # inf://files/abc123

result = client.run({
Confidence
55% confidence
Finding
Data is uploaded to cloud storage (S3 / GCS / Azure Blob). This may be a legitimate backup or exfiltration to an external bucket. Manual review is recommended.

Missing User Warnings

Medium
Confidence
85% confidence
Finding
The webhook examples show state-changing external actions such as Slack notifications and GitHub issue creation without accompanying approval, confirmation, or safety guidance. In agent contexts, this can normalize auto-executing network actions from model-driven tool calls, increasing the risk of prompt-injection-induced exfiltration, spam, or unauthorized API actions.

External Transmission

Medium
Category
Data Exfiltration
Content
# Webhook with secret
github = (
    webhook_tool("create_issue", "https://api.github.com/repos/org/repo/issues")
    .describe("Create a GitHub issue")
    .secret("GITHUB_TOKEN")  # Uses stored secret
    .param("title", string("Issue title"))
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Static analysis

No suspicious patterns detected.