Back to skill

Security audit

Permissions Broker

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent approval-gated broker integration, but it needs review because it asks users to paste a reusable API key into chat and does not firmly restrict where that key is sent.

Review before installing. Use this only if you trust the Permissions Broker service and understand that approved requests can read or modify linked provider data. Provide the key through a protected secret such as PB_API_KEY rather than chat, verify the broker URL is exactly the intended broker service before any request, and rotate the key if it has been pasted into a conversation.

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
SKILL.md:20
Finding

Broker API Key Exposure Through Chat and an Unconstrained Broker Origin

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:20, SKILL.md:58, and SKILL.md:168-183
Vulnerability Type: Credential exposure and insufficient destination validation
Risk Level: Medium

Vulnerable Code and Instructions

SKILL.md:20 directs the user to disclose a sent-once API key through the agent conversation:

text
2. Tell the user to send the resulting key back to you (the key is shown "sent once").

SKILL.md:58 permits the broker base URL and API key to be provided as runtime inputs:

text
- Ask for the minimum missing inputs (broker base URL + user API key) and then propose the exact upstream URL(s) you will request.

SKILL.md:168-183 sends the API key as a bearer credential to the supplied base URL:

ts
async function createBrokerRequest(params: {
  baseUrl: string;
  apiKey: string;
  upstreamUrl: string;
  method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
  headers?: Record<string, string>;
  body?: unknown;
  consentHint?: string;
  idempotencyKey?: string;
}): Promise<CreateRequestResponse> {
  const res = await fetch(`${params.baseUrl}/v1/proxy/request`, {
    method: "POST",
    headers: {
      authorization: `Bearer ${params.apiKey}`,
      "content-type": "application/json",
    },

This behavior conflicts with the secret-handling guidance in references/api_reference.md:149-152:

text
## Safety / Secret Handling

- Never paste API keys into chat logs or commit them.
- Do not log full upstream responses if they may contain sensitive data.

Technical Analysis

The Skill combines two unsafe design choices:

  1. It instructs the user to place a sensitive, sent-once bearer credential into the conversation. Conversation history, agent traces, telemetry, and error diagnostics may retain this value. This contradicts the project's own prohibition against pasting API keys into chat logs.
  2. It models baseUrl as an unconstrained runtime parameter while attaching the bearer credential to req ...[truncated 2779 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove conversational secret collection

    • Do not instruct users to paste API keys into chat.
    • Require the key to be provisioned through a protected secret manager or environment-variable mechanism such as PB_API_KEY.
    • If the runtime cannot accept secrets securely, stop and provide setup instructions rather than requesting the key in conversational text.
  2. Pin and validate the broker origin

    • Default to the documented origin https://permissions-broker.steer.fun.
    • Before attaching authorization, parse the URL and require:
      • The https: scheme.
      • An exact hostname match.
      • No embedded username or password.
      • The expected port, or no explicit port.
    • Do not use suffix or substring hostname checks.
    • If private broker deployments must be supported, require explicit out-of-band trusted configuration rather than a URL supplied during an ordinary task.
  3. Separate credentials from general request parameters

    • Build authenticated broker requests only through a dedicated client initialized with a validated origin and a secret-store reference.
    • Prevent upstream URLs, user content, or model-generated data from influencing the destination receiving the broker authorization header.
    • Disable automatic cross-origin redirects for authenticated calls, or strip authorization on every redirect and reject unexpected destinations.
  4. Reconcile the documentation

    • Replace SKILL.md:20 with secure secret-store provisioning instructions.
    • Replace the request for a “broker base URL + user API key” with a check for the pinned broker configuration and a protected PB_API_KEY reference.
    • Preserve the rule in references/api_reference.md that API keys must never be pasted into chat logs.
  5. Reduce the consequences of disclosure

    • Use short-lived, narrowly scoped credentials if the broker supports them.
    • Provide clear revocation and rotation instructions.
    • A ...[truncated 207 chars]
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (7)

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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 · SKILL.md (reported line 485)May include surrounding context.

md
def create_request(base_url, api_key, upstream_url, consent_hint=None, idempotency_key=None):
  # Optional: method/headers/body for non-GET requests.
  r = requests.post(
    f"{base_url}/v1/proxy/request",
    headers={"Authorization": f"Bearer {api_key}"},
    json={

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · SKILL.md (reported line 314)May include surrounding context.

md
Create pull request

- Upstream:
  - `POST https://api.github.com/repos/<owner>/<repo>/pulls`
- Body (via `body` + `content-type: application/json`):
  - `title` (string)
  - `head` (string): source branch (e.g. `feature-branch`)

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · SKILL.md (reported line 584)May include surrounding context.

md
Create pull request

- Upstream:
  - `POST https://api.github.com/repos/<owner>/<repo>/pulls`
- Body (via `body` + `content-type: application/json`):
  - `title` (string)
  - `head` (string): source branch (e.g. `feature-branch`)

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · SKILL.md (reported line 586)May include surrounding context.

md
Create pull request

- Upstream:
  - `POST https://api.github.com/repos/<owner>/<repo>/pulls`
- Body (via `body` + `content-type: application/json`):
  - `title` (string)
  - `head` (string): source branch (e.g. `feature-branch`)

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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/api_reference.md (reported line 183)May include surrounding context.

md
Create pull request

- Upstream:
  - `POST https://api.github.com/repos/<owner>/<repo>/pulls`
- Body (via `body` + `content-type: application/json`):
  - `title` (string)
  - `head` (string): source branch (e.g. `feature-branch`)

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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/api_reference.md (reported line 194)May include surrounding context.

md
Create pull request

- Upstream:
  - `POST https://api.github.com/repos/<owner>/<repo>/pulls`
- Body (via `body` + `content-type: application/json`):
  - `title` (string)
  - `head` (string): source branch (e.g. `feature-branch`)

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

The section labeled 'Example: Pull' explains that git pull should be used, but the final step shows git clone "<remote_url>" ./repo instead. This is an active contradiction in the documentation about what operation the user should perform, not merely an omitted detail.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.