Skill flagged — suspicious patterns detected

ClawHub Security flagged this skill as suspicious. Review the scan results before using.

Zulip

v1.0.2

Interact with Zulip chat platform via REST API and Python client. Use when you need to read messages from streams/topics, send messages to channels or users,...

0· 726·4 current·4 all-time
Security Scan
VirusTotalVirusTotal
Suspicious
View report →
OpenClawOpenClaw
Benign
medium confidence
Purpose & Capability
Name/description match the included helper script and reference docs. The script uses the official zulip.Client and implements listing streams, reading/sending messages, and listing users — all aligned with the stated purpose.
Instruction Scope
SKILL.md confines runtime actions to installing the zulip Python package, creating the standard ~/.config/zulip/zuliprc config with a Zulip API key, and invoking the included script or the zulip client directly. It does not instruct reading unrelated files or exfiltrating data to external endpoints beyond the Zulip site configured by the user.
Install Mechanism
There is no formal install spec (instruction-only), and the README tells users to pip install zulip. The skill includes a Python script (which will be present on disk when the skill is installed). This is reasonable for a client helper, but users should ensure they install the official 'zulip' package from PyPI and inspect the included script before running.
Credentials
The registry metadata declares no required env vars or primary credential, but the instructions legitimately require a local zuliprc file containing an email, API key, and site URL. Requesting a Zulip API key is proportionate to the stated functionality; however, the skill will need access to that local config file (containing credentials).
Persistence & Privilege
The skill is not forced-always, does not request elevated agent privileges, and does not modify other skill/system configurations. Autonomous invocation is allowed (platform default) but not coupled with any additional privileged access in this package.
Assessment
This skill appears to do what it claims: it wraps the official Zulip Python client. Before installing or running: 1) confirm you obtained the 'zulip' PyPI package from the official source and verify its integrity; 2) inspect the included scripts (scripts/zulip_client.py) yourself — it is small and readable; 3) create the ~/.config/zulip/zuliprc file securely and limit its file permissions (it contains an API key); 4) only supply a bot account/API key with the minimal permissions needed; and 5) if you do not trust the skill publisher (no homepage/source listed), consider running it in a restricted environment or container and revoke the API key if you detect unexpected behavior.

Like a lobster shell, security has layers — review code before you run it.

latestvk979brh72dak4e7qsk5p25f0a5819wbd
726downloads
0stars
3versions
Updated 3h ago
v1.0.2
MIT-0

Zulip Integration

Interact with Zulip chat platform for team communication.

Setup

1. Install Python Client

pip install zulip

2. Create Configuration File

Create ~/.config/zulip/zuliprc:

[api]
email=bot@example.zulipchat.com
key=YOUR_API_KEY_HERE
site=https://example.zulipchat.com

Get credentials from Zulip admin panel (Settings → Bots).

3. Verify Connection

python scripts/zulip_client.py streams

Quick Start

Using the Helper Script

The scripts/zulip_client.py provides common operations:

List streams:

python scripts/zulip_client.py streams
python scripts/zulip_client.py streams --json

Read messages:

# Recent stream messages (by name)
python scripts/zulip_client.py messages --stream "General" --num 10

# By stream ID (more reliable, use 'streams' to find IDs)
python scripts/zulip_client.py messages --stream-id 42 --num 10

# Specific topic
python scripts/zulip_client.py messages --stream "General" --topic "Updates"

# Private messages
python scripts/zulip_client.py messages --type private --num 5

# Mentions
python scripts/zulip_client.py messages --type mentioned

Note: Stream names may have descriptions that look like part of the name. Use --stream-id for unambiguous identification.

Send messages:

# To stream
python scripts/zulip_client.py send --type stream --to "General" --topic "Updates" --content "Hello!"

# Private message (user_id)
python scripts/zulip_client.py send --type private --to 123 --content "Hi there"

List users:

python scripts/zulip_client.py users
python scripts/zulip_client.py users --json

Using Python Client Directly

import zulip

client = zulip.Client(config_file="~/.config/zulip/zuliprc")

# Read messages
result = client.get_messages({
    "anchor": "newest",
    "num_before": 10,
    "num_after": 0,
    "narrow": [{"operator": "stream", "operand": "General"}]
})

# Send to stream
client.send_message({
    "type": "stream",
    "to": "General",
    "topic": "Updates",
    "content": "Message text"
})

# Send DM
client.send_message({
    "type": "private",
    "to": [user_id],
    "content": "Private message"
})

Using curl

# List streams
curl -u "bot@example.com:KEY" https://example.zulipchat.com/api/v1/streams

# Get messages
curl -u "bot@example.com:KEY" -G \
  "https://example.zulipchat.com/api/v1/messages" \
  --data-urlencode 'anchor=newest' \
  --data-urlencode 'num_before=20' \
  --data-urlencode 'num_after=0' \
  --data-urlencode 'narrow=[{"operator":"stream","operand":"General"}]'

# Send message
curl -X POST "https://example.zulipchat.com/api/v1/messages" \
  -u "bot@example.com:KEY" \
  --data-urlencode 'type=stream' \
  --data-urlencode 'to=General' \
  --data-urlencode 'topic=Updates' \
  --data-urlencode 'content=Hello!'

Common Workflows

Monitor Stream for New Messages

def get_latest_messages(client, stream_name, last_seen_id=None):
    narrow = [{"operator": "stream", "operand": stream_name}]
    
    if last_seen_id:
        # Get only messages after last seen
        request = {
            "anchor": last_seen_id,
            "num_before": 0,
            "num_after": 100,
            "narrow": narrow
        }
    else:
        # Get recent messages
        request = {
            "anchor": "newest",
            "num_before": 20,
            "num_after": 0,
            "narrow": narrow
        }
    
    result = client.get_messages(request)
    return result["messages"]

Reply to Topic

def reply_to_message(client, original_message, reply_text):
    """Reply in the same stream/topic as original message."""
    client.send_message({
        "type": "stream",
        "to": original_message["display_recipient"],
        "topic": original_message["subject"],
        "content": reply_text
    })

Search Messages

def search_messages(client, keyword, stream=None):
    narrow = [{"operator": "search", "operand": keyword}]
    
    if stream:
        narrow.append({"operator": "stream", "operand": stream})
    
    result = client.get_messages({
        "anchor": "newest",
        "num_before": 50,
        "num_after": 0,
        "narrow": narrow
    })
    
    return result["messages"]

Get User ID by Email

def get_user_id(client, email):
    """Find user_id by email address."""
    result = client.get_members()
    
    for user in result["members"]:
        if user["email"] == email:
            return user["user_id"]
    
    return None

Message Formatting

Zulip uses Markdown:

  • Bold: **text**
  • Italic: *text*
  • Code: `code`
  • Code block: ```language\ncode\n```
  • Quote: > quoted text
  • Mention user: @**Full Name**
  • Link stream: #**stream-name**
  • Link: [text](url)

Advanced Features

Upload and Share Files

with open("file.pdf", "rb") as f:
    result = client.upload_file(f)
    file_url = result["uri"]

# Share in message
client.send_message({
    "type": "stream",
    "to": "General",
    "topic": "Files",
    "content": f"Check out [this file]({file_url})"
})

React to Messages

# Add reaction
client.add_reaction({
    "message_id": 123,
    "emoji_name": "thumbs_up"
})

# Remove reaction
client.remove_reaction({
    "message_id": 123,
    "emoji_name": "thumbs_up"
})

Reference

See references/api-quick-reference.md for complete API documentation, endpoints, and examples.

Troubleshooting

Config file not found:

  • Ensure ~/.config/zulip/zuliprc exists with correct format
  • Check file permissions (should be readable)

Authentication failed:

  • Verify API key is correct
  • Check bot is active in Zulip admin panel
  • Ensure site URL matches organization URL

Empty messages array:

  • Bot might not be subscribed to the stream
  • Use client.get_subscriptions() to check subscriptions
  • Admin may need to add bot to private streams

Rate limit errors:

  • Standard limit: 200 requests/minute
  • Message limit: ~20-30/minute
  • Add delays between bulk operations
  • Check Retry-After header on 429 responses

Comments

Loading comments...