Back to skill

Security audit

A2A Exposed: setup

Security checks for vulnerabilities and agentic risk

Overview

ClawScan marks this skill suspicious because it reports mutable package execution and undeclared destructive or unrelated capabilities, despite its stated deployment and configuration purpose.

The verdict is suspicious, not malicious: the scanners report security weaknesses and mismatches, not clear proof of harmful intent. Consider the unpinned package commands and the reported teardown and other undisclosed actions before installing; scan coverage was partial because several local references could not be resolved.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (162)

Description-Behavior Mismatch

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The command invokes the feedback subcommand rather than performing deployment or configuration. Although the report concerns an initialization problem, submitting feedback is a distinct capability not disclosed by the description. The supplied diagnostic values are placeholders; the chunk does not demonstrate collection of real logs or secrets.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The description covers deployment and configuration, but does not disclose destructive teardown or database deletion. The supplied commands explicitly delete both resources with --force. These are consequential capabilities beyond supporting deployment or configuration details.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The declared purpose covers deployment and configuration, but the supplied chunk performs teardown and irreversible local deletion. These are distinct destructive lifecycle operations not disclosed by the description, rather than merely implementation details of deployment. The exact remote effects of the package's uninstall command cannot be established from this chunk.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding

The supplied command performs peer connection setup, a capability not described by the hosting and deployment scope. Nothing in the snippet indicates that this connection is a supporting step for deploying or configuring the declared infrastructure. It does not itself show reading or replying to messages.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding

The supplied commands perform destructive infrastructure teardown rather than the declared deployment or configuration operations. Although these resources could support a public façade, deleting tunnels, access controls, credentials, and DNS records is a substantial lifecycle capability not disclosed in the description. The chunk contains no deployment or configuration commands establishing these deletions as incidental cleanup during a redeployment.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 102)May include surrounding context.

md
; `status --json` includes `runtime.node` / `runtime.execPath`. Pin scheduled jobs with mise: [prerequisites](references/prerequisites.md).

## Workflow
Human handoffs: [delivery preflight](references/wake.md#human-handoffs). **Ordinary webhook or existing native A2A service:** Only offer this path to callers able to set its dedicated ingress-secret header; native discovery is invited access, not URL-only public discovery. Confirm the owner-approved local service and who may hold that transport-access secret. HTTP create/status/revoke always print JSON; run is silent/foreground-only and needs a compatible Worker. Before enrollment, enabled:false/empty capabilities with protocolVersion 2 is normal; distinguish definite config/rejection cleanup from uncertain enrollment, and never auto-rotate. Retire old files only after an approved replacement is verified. The separate opt-in [HTTP/native A2A relay](https://github.com/telegraphic-dev/a2a-exposed/blob/main/docs/http-relay.md) offers fixe

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/deploy.md (reported line 145)May include surrounding context.

existing deployment: npx -y a2a-exposed@latest deploy --upstream https://agent-upstream.example.com/a2a

card elsewhere: --upstream-card-url https://agent-upstream.example.com/.well-known/agent-card.json # same origin as --upstream (credentials ride with the fetch)

back to the A2A endpoint: deploy --upstream none

npx -y a2a-exposed@latest status # upstream card ok; Access credential and upstream bearer configured; upstream check OK; next step

text

The two credentials do different jobs: the **Access service token** only gets the Worker through the tunnel; the **`UPSTREAM_TOKEN`** is what the agent itself checks. Setup reads the upstream's agent card and, unless it declares no bearer auth, needs `UPSTREAM_TOKEN`. Not exported? On a terminal it asks (hidden input); otherwise it exits 1 and says what to do. Other ways to pass it (never as an argument): `<command that prints it> | npx -y a2a-exposed@latest deploy --upstream-token-stdin`. An agent

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/deploy.md (reported line 152)May include surrounding context.

md
3. **Pairing** is unchanged and stays on the façade: set the approval password ([pairing](pairing.md)), then peers run `connect https://agent.example.com`. A wake webhook is optional (it only announces pairing requests); messages go to the upstream, so `inbox` stays empty.

**Agent card rewrite (always on in proxy mode).** The façade fetches the upstream's card (cached 5 minutes, with the Access token and `UPSTREAM_TOKEN`; so `--upstream-card-url` must be on the `--upstream` origin, anything else is refused by `deploy` and by the Worker), and serves a rewritten copy at `/.well-known/agent-card.json` (A2A 1.0) and `/.well-known/agent.json` (0.3 shape):

- `supportedInterfaces`: one JSONRPC interface per version the upstream advertises (1.0 and/or 0.3), every one at `https://agent.example.com/`. Upstream interface URLs, gRPC / HTTP+JSON interfaces, `url`, `additionalInterfaces` and `preferredTransport` are never copied.
- `securitySchemes` / `securityRequirements`: the façade's (per-pee

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · references/troubleshooting.md (reported line 33)May include surrounding context.

md
LOUDFLARE_ACCOUNT_ID` is used anyway |
| Card not reachable right after deploy (`status`: `agent card: FAILED`) | A new custom domain takes 1–5 minutes for DNS and the certificate. Check that the hostname is on a zone in this account and has no conflicting DNS record. A newly registered workers.dev subdomain can also take a few minutes |
| `status`: `this machine's resolver does not` | Public DNS has the hostname and this machine does not. On macOS, flush the cache: `sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder`. The other layers are still checked |
| `status`: `no public DNS record` | That hostname has no public DNS record yet. For the Worker, check the custom domain under Workers → Settings → Domains. For the wake host, run `tunnel status` |
| `status`: local webhook is HTTP 401 or 403 and does not say Cloudflare Access | The service-token probe reached the webhook. That GET does not send the webhook's bearer or HMAC, so the webhook's own check can refuse it. The lay

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/troubleshooting.md (reported line 62)May include surrounding context.

md
a web UI, the card URL, a wrong path): `deploy --upstream <endpoint URL>` |
| `init`/`deploy --upstream`: `the upstream's agent card asks for a bearer token ..., and no UPSTREAM_TOKEN is set` | Export `UPSTREAM_TOKEN` and re-run, or pipe it with `--upstream-token-stdin`. Only if the agent really accepts calls without a bearer: `--no-upstream-token` |
| `init`/`deploy --upstream`: `the upstream's agent card could not be read from here` | The CLI reads the card from this machine with the exported Access token: export `UPSTREAM_ACCESS_CLIENT_ID` / `_SECRET` (a 302 to the Access login means they are missing), or provide `UPSTREAM_TOKEN` / `--no-upstream-token` explicitly |
| `status`: `PEER_<ALIAS>_TOKEN is set in the environment and overrides the different peer token saved` | A stale variable shadows the token `connect` just saved: unset it where it is set (shell profile, service unit) |
| Proxy mode, `status`: `can't fetch the upstream's agent card (HTTP 530 ...)` | The upstream tunnel h

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/troubleshooting.md (reported line 75)May include surrounding context.

md
). "Unknown client": remove the connector in the client and add it again |
| Connector consent: "No approval password is set yet" | `npx -y a2a-exposed@latest pair set-password --web`, open the link, then add the connector again |
| Connector: `send` says the peer isn't synced, or the stored token can't be read | `npx -y a2a-exposed@latest peers sync <alias>` on the machine with your peers (again after `connect`, a token change or an owner-token rotation) |
| Connector stops working (401) | Its access token expired and refresh failed, or it was revoked (`token list` shows `REVOKED`). Reconnect it in the client and approve again |
| Claude Code run: skill not found / doesn't use the skill | The routine clones the **default branch** of its repository sources: add the repo as a source and merge `.claude/skills/` there (a `claude/...` branch isn't cloned) |
| Claude Code run: `403` with `x-deny-reason: host_not_allowed` | The environment's network access (Trusted by default) doesn't allow

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/wake.md (reported line 245)May include surrounding context.

md
ount (choose with `--tunnel-zone` or `--tunnel-hostname`), proxied CNAME to the tunnel; the tunnel, the Access app, and the service token are all named `a2a-exposed wake <worker>`; the tunnel routes only the wake path to your origin (other paths: 404);
- a self-hosted **Access application** on that hostname with exactly **one policy: Service Auth (`non_identity`) for one new service token** (policy name `a2a-exposed wake: service token only`), 15-minute sessions; `cloudflared` also verifies the Access token itself;
- the Worker stores the service token (`WAKE_ACCESS_CLIENT_ID` / `WAKE_ACCESS_CLIENT_SECRET`) and sends `CF-Access-Client-Id` / `CF-Access-Client-Secret` on every wake, **in addition** to the preset's own bearer token or HMAC signature. Keep that agent-side auth enabled.

Requirements: a **Cloudflare zone anywhere on the account**, for the wake hostname and its Access app. The A2A endpoint URL doesn't matter: a workers.dev A2A endpoint works the same as a custom hostname. `t

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/wake.md (reported line 462)May include surrounding context.

md
Keys use `--key-file`, `--key-env` or `--key-stdin`. Signing secrets use
`--hmac-secret-file` or `--hmac-secret-env`. Hosted wakes do not accept hand-typed
Access credentials. Run `hosted capabilities --json`, then use **Import your existing
tunnel** or **Create secure link** in dashboard Wake settings to authorize Access.
Facade upstream Access options remain available. Never pass secret values in argv.
Hosted `wake prepare`, `wake test`, `wake set` and `relay wake test` never read ambient

MCP server referenced without pinned version: 'npx -y a2a-exposed'.

Medium
Category
MCP Rug Pull
Confidence
98% confidence
Finding

The compatibility instructions explicitly use npx -y a2a-exposed@latest, which executes a mutable package release rather than a reviewed, fixed version. A compromised future release or dependency could execute with the user's privileges and access deployment credentials; this is a CLI supply-chain risk, not specifically an MCP-server issue.

Content

No source excerpt is available for this finding.

MCP server referenced without pinned version: 'npx -y a2a-exposed'.

Medium
Category
MCP Rug Pull
Confidence
98% confidence
Finding

The instruction to run every command through a2a-exposed@latest repeatedly exposes setup operations to mutable npm code. Because these operations handle owner tokens and Cloudflare configuration, a malicious release could steal secrets or modify infrastructure despite the skill's human-consent requirements.

Content

No source excerpt is available for this finding.

MCP server referenced without pinned version: 'npx cf'.

Medium
Category
MCP Rug Pull
Confidence
91% confidence
Finding

The npx cf auth whoami command does not establish a fixed version or provenance for the executable that npx resolves. Although the intended operation only reads account identity, the resolved package executes locally and could access credentials if its release or dependency chain were compromised.

Content

No source excerpt is available for this finding.

MCP server referenced without pinned version: 'npx -y a2a-exposed'.

Medium
Category
MCP Rug Pull
Confidence
98% confidence
Finding

The owner-token rotation example executes a2a-exposed@latest without pinning the code being trusted. Token rotation is particularly sensitive because a compromised executable could capture replacement credentials or alter the deployment during the operation.

Content

No source excerpt is available for this finding.

MCP server referenced without pinned version: 'npx -y a2a-exposed'.

Medium
Category
MCP Rug Pull
Confidence
98% confidence
Finding

The feedback instructions execute the mutable @latest package even though reporting a problem does not require changing trusted software. A compromised release could bypass the documented redaction and approval controls or read local credentials before submitting anything.

Content

No source excerpt is available for this finding.

MCP server referenced without pinned version: 'npx -y a2a-exposed'.

Medium
Category
MCP Rug Pull
Confidence
98% confidence
Finding

The runnable feedback example repeats the unpinned a2a-exposed@latest execution pattern. The risk comes from executing potentially changed package code with local privileges, not from evidence that this particular report command maliciously collects data.

Content

No source excerpt is available for this finding.

MCP server referenced without pinned version: 'npx -y a2a-exposed'.

Medium
Category
MCP Rug Pull
Confidence
99% confidence
Finding

The actual command uses a2a-exposed@latest, which is a mutable release tag rather than a pinned version. Although this is a CLI rather than an MCP server, npx -y can download and execute a compromised future release with the agent's permissions, even for a capabilities check.

Content

No source excerpt is available for this finding.

MCP server referenced without pinned version: 'npx -y a2a-exposed'.

Medium
Category
MCP Rug Pull
Confidence
99% confidence
Finding

The relay status command executes a package selected through the mutable @latest tag. Its nominally read-only purpose does not constrain the downloaded JavaScript, which could access local files, credentials, or deployment configuration if the release is compromised.

Content

No source excerpt is available for this finding.

MCP server referenced without pinned version: 'npx -y a2a-exposed'.

Medium
Category
MCP Rug Pull
Confidence
99% confidence
Finding

The cron prompt instructs recurring agent runs to execute npx -y a2a-exposed@latest inbox, allowing later package releases to become executable code without a corresponding skill review. This is more dangerous than a one-time check because future unattended runs may resolve a compromised release in an environment with inbox credentials.

Content

No source excerpt is available for this finding.

MCP server referenced without pinned version: 'npx -y a2a-exposed'.

Medium
Category
MCP Rug Pull
Confidence
99% confidence
Finding

The relay status example executes a2a-exposed@latest without pinning the code being trusted. A malicious release could execute arbitrary code with the invoking user's permissions before or instead of reporting status; calling it a status check provides no isolation.

Content

No source excerpt is available for this finding.

MCP server referenced without pinned version: 'npx -y a2a-exposed'.

Medium
Category
MCP Rug Pull
Confidence
99% confidence
Finding

The connector-enrollment command resolves executable code through @latest while creating a relay token. A compromised release could steal that token or alter enrollment behavior; mode-600 storage does not protect credentials from malicious code running as the file owner.

Content

No source excerpt is available for this finding.

MCP server referenced without pinned version: 'npx -y a2a-exposed'.

Medium
Category
MCP Rug Pull
Confidence
99% confidence
Finding

The foreground relay command executes an unpinned release and explicitly gives it access to the relay token and a local webhook endpoint. If the selected release is compromised, it could steal credentials or misuse local access; the statement that the relay installs nothing does not prevent npx from fetching and executing package code.

Content

No source excerpt is available for this finding.