Back to skill

Security audit

Blinko Api

Security checks for vulnerabilities and agentic risk

Overview

This Blinko skill does what it claims, but it handles sensitive note data and destructive note deletion with weak safety boundaries.

Review this skill before installing if your Blinko notes are sensitive or hard to recover. Prefer a local or HTTPS-only BLINKO_HOST, provide the token through the environment rather than --token, use a least-privilege token if Blinko supports it, and require explicit confirmation before running delete commands.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/blinko_client.py:11
Finding

Bearer Token and Sensitive Note Data May Be Exposed Through Insecure Transport and Command-Line Arguments

Content
View full analysis

Vulnerability Details

File Location: scripts/blinko_client.py:11-25, scripts/blinko_client.py:105-106, and scripts/blinko_client.py:152
Vulnerability Type: Plaintext transmission of sensitive data and insecure command-line secret handling
Risk Level: Medium

Vulnerable Code

python
class Blinko:
    def __init__(self, base_url=None, api_token=None):
        host = base_url if base_url is not None else os.getenv("BLINKO_HOST", "http://127.0.0.1:1111")
        token = api_token if api_token is not None else os.getenv("BLINKO_TOKEN", "")
        self.base_url = (host or "").rstrip("/")
        self.api_token = token or ""

    def _headers(self):
        headers = {"Content-Type": "application/json"}
        if self.api_token:
            headers["Authorization"] = f"Bearer {self.api_token}"
        return headers

    def _request(self, path, method="GET", body=None):
        url = f"{self.base_url}{path}"
        data = None
        if body is not None:
            data = json.dumps(body).encode("utf-8")

        request = urllib.request.Request(url, data=data, headers=self._headers(), method=method)
python
parser.add_argument("--host", default=os.getenv("BLINKO_HOST", "http://127.0.0.1:1111"), help="Blinko host")
parser.add_argument("--token", default=os.getenv("BLINKO_TOKEN", ""), help="Blinko API token")
python
client = Blinko(base_url=args.host, api_token=args.token)

Technical Analysis

The client accepts an unrestricted API base URL and does not validate its scheme or destination before attaching the Blinko bearer token. Although the default endpoint is a loopback HTTP address, users may configure BLINKO_HOST or --host with a non-loopback http:// endpoint. In that case, the Authorization header and request bodies containing private note data are transmitted without transport encryption.

Authentication and transmission of note conte ...[truncated 2330 chars]

Remediation
View remediation

Remediation Suggestions

  1. Parse and validate the configured host before constructing requests.
  2. Require https:// for every non-loopback destination.
  3. Permit http:// only for explicit loopback addresses such as 127.0.0.1, ::1, or a carefully validated local development configuration.
  4. Reject unsupported URL schemes, missing hostnames, embedded credentials, and malformed endpoints.
  5. Remove the --token command-line option to prevent routine exposure through process listings and shell history.
  6. Prefer BLINKO_TOKEN or a dedicated credential store. If interactive use is needed, read the token through a non-echoing prompt or protected file descriptor.
  7. Document that environment variables can still be visible under some local privilege models and recommend short-lived, narrowly scoped API tokens.
  8. Ensure authorization credentials are not forwarded to a different origin during redirects; reject cross-origin redirects or strip the Authorization header before following them.
  9. Apply least privilege on the server by issuing tokens restricted to only the Blinko operations required by the user.
  10. Add tests confirming that remote HTTP endpoints are rejected, loopback development behavior is explicit, and credentials never appear in normal logs or error output.
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (8)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill invokes Python code that reads environment variables and performs network requests, but it does not declare any tool scope such as permissions or allowed-tools. This creates an authorization gap where the skill's effective capabilities are broader than what is transparently declared, increasing the chance of unintended secret access or outbound requests.

Content

No source excerpt is available for this finding.

Shadow Command Trigger

Medium
Category
Trigger Abuse
Confidence
70% confidence
Finding

Shadow Command Trigger: 'save blinko' conflicts with built-in command 'save'

Content

No source excerpt is available for this finding.

Shadow Command Trigger

Medium
Category
Trigger Abuse
Confidence
70% confidence
Finding

Shadow Command Trigger: 'get blinko' conflicts with built-in command 'get'

Content

No source excerpt is available for this finding.

Shadow Command Trigger

Medium
Category
Trigger Abuse
Confidence
70% confidence
Finding

Shadow Command Trigger: 'list blinkos' conflicts with built-in command 'list'

Content

No source excerpt is available for this finding.

Shadow Command Trigger

Medium
Category
Trigger Abuse
Confidence
70% confidence
Finding

Shadow Command Trigger: 'create blinko' conflicts with built-in command 'create'

Content

No source excerpt is available for this finding.

Shadow Command Trigger

Medium
Category
Trigger Abuse
Confidence
70% confidence
Finding

Shadow Command Trigger: 'update blinko' conflicts with built-in command 'update'

Content

No source excerpt is available for this finding.

Shadow Command Trigger

Medium
Category
Trigger Abuse
Confidence
70% confidence
Finding

Shadow Command Trigger: 'delete blinko' conflicts with built-in command 'delete'

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The client exposes delete-note/delete-blinko operations that immediately invoke the server-side batch-delete API with the supplied ID and no interactive confirmation, dry-run, or safety guard. In an agent skill context, this increases the chance of accidental or prompt-induced destructive actions, especially because note-management commands are high-trust operations that can permanently remove user data.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.