Skill flagged — suspicious patterns detected

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

Sign-in with Agent

SIWA (Sign-In With Agent) authentication for ERC-8004 registered agents.

MIT-0 · Free to use, modify, and redistribute. No attribution required.
0 · 893 · 2 current installs · 2 all-time installs
byBuilders Garden@buildersgarden
MIT-0
Security Scan
VirusTotalVirusTotal
Suspicious
View report →
OpenClawOpenClaw
Suspicious
medium confidence
Purpose & Capability
The name/description (SIWA for ERC-8004 agents) aligns with the content: signing, verification, onchain registration, multiple signer backends, and ERC-8128 authenticated requests. The included signer adapters (Bankr, Circle, Privy, private-key, keyring proxy) are consistent with the stated purpose.
!
Instruction Scope
The SKILL.md and companion docs instruct the agent/operator to run CLI commands inside a workspace (e.g. /home/node/.openclaw/workspace/siwa/packages/siwa-testing), to read SIWA_IDENTITY.md, and to install/use an npm package. They also show code that expects access to environment variables and to deploy/run a keyring proxy. Those runtime instructions go beyond a simple read-only doc: they expect filesystem access, running package installs, and use of secrets. The instructions also include links to external deploy buttons and Docker images which will cause network activity and external deployments if followed.
Install Mechanism
There is no formal install spec in the registry (instruction-only), lowering installer risk. However the docs tell users to run `npm install @buildersgarden/siwa` and other package installs, and recommend deploying a keyring-proxy Docker image (ghcr.io/builders-garden/siwa-keyring-proxy) or one-click Railway deploys. That means following the docs will fetch code from npm/ghcr/railway — normal for an SDK, but you should verify those packages/images/repos before running them.
!
Credentials
Registry metadata lists no required environment variables, but the documentation and examples reference many sensitive variables (KEYRING_PROXY_SECRET, KEYRING_PROXY_URL, PRIVATE_KEY, BANKR_API_KEY, PRIVY_APP_SECRET, CIRCLE_API_KEY, SIWA_SECRET, etc.). This is an inconsistency: the skill will not function without secrets for many signers or server setups, yet none are declared as required. Requesting private keys or HMAC secrets is plausible for this skill's function, but the lack of explicit declared requirements is a red flag and increases the chance of accidental secret exposure if the user follows the examples carelessly.
Persistence & Privilege
The skill does not set always:true and does not request persistent elevated privileges. It is instruction-only and does not declare any automatic self-enabling behavior. Nothing in the provided files indicates it will modify other skills' configs or demand permanent presence.
What to consider before installing
What to consider before installing/using this skill: - Incoherent metadata: the registry entry declares no required environment variables, but the documentation clearly expects many secrets (private keys, proxy HMAC secrets, API keys) for different signer backends. Treat the docs as authoritative: the skill will need secrets to operate. - Don’t paste private keys or shared HMAC secrets into a skill or chat. If you need signing, prefer a keyring/proxy deployed by you (self-hosted) and keep the proxy secret in your environment, not in chat or skill configuration. If you must test, use ephemeral testnet keys and testnet faucets. - Verify upstream packages/images before running installs or deploys: the docs reference npm package @buildersgarden/siwa and a GHCR Docker image and Railway deploy links. Inspect the npm package repository, its maintainers, and the container image contents before running them in any environment you care about. - The instructions expect filesystem access (specific workspace paths) and running pnpm/npm commands. Only run these commands in a controlled environment (isolated dev VM or container), not on sensitive production hosts. - Reverse CAPTCHA and captcha-solve helpers require the agent to generate content under constraints; that is not inherently malicious but could inadvertently leak generated content to the server endpoints shown. Confirm the server endpoints you will talk to and that you trust them. - Because the package is instruction-only in the registry and source/homepage are unknown, ask the skill author for the canonical repository URL, the npm package link, and the source for the Docker image. Without those you cannot easily audit the code you will install. If you plan to proceed: (1) audit the @buildersgarden/siwa npm package and the referenced Docker image; (2) prefer the keyring-proxy approach to avoid exposing private keys, and host it yourself; (3) use testnets and throwaway credentials for initial experiments; (4) ensure SIWA_SECRET and other server secrets are never stored in public or shared chat.

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

Current versionv0.0.4
Download zip
alphavk97btwffpztsrpv047z19wa4q580z27xlatestvk97fzh3z7d7dvhsrbdrfqa3zg581crwb

License

MIT-0
Free to use, modify, and redistribute. No attribution required.

SKILL.md

SIWA SDK

Sign-In With Agent (SIWA) lets AI agents authenticate with services using their ERC-8004 onchain identity.

Install

npm install @buildersgarden/siwa

Skills

Agent-Side (Signing)

Choose based on your wallet provider:

  • Bankr — Bankr Agent API wallets
  • Circle — Circle developer-controlled wallets
  • Privy — Privy server wallets
  • Private Key — Raw private key (viem LocalAccount)
  • Keyring Proxy — Self-hosted proxy with optional 2FA

Server-Side (Verification)

SDK Modules

ImportDescription
@buildersgarden/siwaCore: signSIWAMessage, verifySIWA, createSIWANonce, parseSIWAMessage, buildSIWAMessage, createClientResolver, parseChainId
@buildersgarden/siwa/signerSigner factories (see wallet-specific skills above)
@buildersgarden/siwa/erc8128ERC-8128 HTTP signing/verification
@buildersgarden/siwa/receiptHMAC receipt helpers
@buildersgarden/siwa/nonce-storeNonce stores (Memory, Redis, KV)
@buildersgarden/siwa/identitySIWA_IDENTITY.md helpers
@buildersgarden/siwa/registryOnchain agent registration
@buildersgarden/siwa/client-resolverDynamic PublicClient resolution for multi-chain servers
@buildersgarden/siwa/nextNext.js middleware (withSiwa, siwaOptions)
@buildersgarden/siwa/expressExpress middleware (siwaMiddleware, siwaJsonParser, siwaCors)
@buildersgarden/siwa/honoHono middleware (siwaMiddleware, siwaCors)
@buildersgarden/siwa/fastifyFastify middleware (siwaPlugin, siwaAuth)
@buildersgarden/siwa/x402x402 payment helpers
@buildersgarden/siwa/captchaReverse CAPTCHA (prove you're an AI)

x402 Payments (Agent-Side)

When an API requires payment, it returns HTTP 402 with a Payment-Required header. The agent decodes the payment options, constructs a signed payment, and retries with a Payment-Signature header — all while maintaining SIWA authentication.

Handling a 402 Response

import {
  encodeX402Header,
  decodeX402Header,
  type PaymentRequired,
  type PaymentPayload,
} from "@buildersgarden/siwa/x402";
import { signAuthenticatedRequest } from "@buildersgarden/siwa/erc8128";

// 1. Make initial authenticated request (may get 402)
const signedRequest = await signAuthenticatedRequest(
  new Request("https://api.example.com/premium", { method: "POST" }),
  receipt,
  signer,
  84532,
);

const res = await fetch(signedRequest);

if (res.status === 402) {
  // 2. Decode payment requirements from header
  const header = res.headers.get("Payment-Required");
  const { accepts, resource } = decodeX402Header<PaymentRequired>(header!);

  // 3. Pick a payment option and construct payload
  const option = accepts[0];
  const payload: PaymentPayload = {
    signature: "0x...",  // sign the payment with your wallet
    payment: {
      scheme: option.scheme,
      network: option.network,
      amount: option.amount,
      asset: option.asset,
      payTo: option.payTo,
    },
    resource,
  };

  // 4. Retry with both SIWA auth + payment header
  const retryRequest = await signAuthenticatedRequest(
    new Request("https://api.example.com/premium", {
      method: "POST",
      headers: {
        "Payment-Signature": encodeX402Header(payload),
      },
    }),
    receipt,
    signer,
    84532,
  );

  const paidRes = await fetch(retryRequest);
  // paidRes.headers.get("Payment-Response") contains { txHash, ... }
}

x402 Headers

HeaderDirectionDescription
Payment-RequiredServer → AgentBase64-encoded JSON with accepted payment options. Sent with 402.
Payment-SignatureAgent → ServerBase64-encoded signed payment payload.
Payment-ResponseServer → AgentBase64-encoded settlement result with transaction hash.

Pay-Once Sessions

Some endpoints use pay-once mode: the first request requires payment, subsequent requests from the same agent to the same resource pass through without payment until the session expires. If you receive a 200 on a previously-paid endpoint, the session is still active — no need to pay again.


Captcha (Reverse CAPTCHA)

SIWA includes a "reverse CAPTCHA" mechanism — inspired by MoltCaptcha — that proves an entity is an AI agent, not a human. Challenges exploit how LLMs generate text in a single autoregressive pass (satisfying multiple constraints simultaneously), while humans must iterate.

Two integration points:

  1. Sign-in flow — server requires captcha before issuing a nonce
  2. Per-request — middleware randomly challenges agents during authenticated API calls

Agent-Side: Handling a Captcha Challenge

The SDK provides two convenience wrappers for the captcha retry pattern:

Sign-In Captcha: solveCaptchaChallenge()

import { solveCaptchaChallenge } from "@buildersgarden/siwa/captcha";

// 1. Request nonce
const nonceRes = await fetch("/api/siwa/nonce", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ address, agentId, agentRegistry }),
});
const data = await nonceRes.json();

// 2. Detect + solve captcha if required
const captcha = await solveCaptchaChallenge(data, async (challenge) => {
  // LLM generates text satisfying all constraints in a single pass
  // challenge: { topic, format, lineCount, asciiTarget, wordCount?, timeLimitSeconds, ... }
  // Your LLM generates text satisfying all constraints in one pass.
  // Use any provider (Anthropic, OpenAI, etc.) — the solver just returns a string.
  return await generateText(challenge);
});

if (captcha.solved) {
  // 3. Retry with challenge response
  const retryRes = await fetch("/api/siwa/nonce", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ address, agentId, agentRegistry, challengeResponse: captcha.challengeResponse }),
  });
}

Per-Request Captcha: retryWithCaptcha()

import { signAuthenticatedRequest, retryWithCaptcha } from "@buildersgarden/siwa/erc8128";

const url = "https://api.example.com/action";
const body = JSON.stringify({ key: "value" });

// 1. Sign and send
const signed = await signAuthenticatedRequest(
  new Request(url, { method: "POST", body }),
  receipt, signer, chainId,
);
const response = await fetch(signed);

// 2. Detect + solve captcha, re-sign, and get retry request
const result = await retryWithCaptcha(
  response,
  new Request(url, { method: "POST", body }), // fresh request (original body consumed)
  receipt, signer, chainId,
  async (challenge) => generateText(challenge), // your LLM solver
);

if (result.retry) {
  const retryResponse = await fetch(result.request);
}

Note: Pass a fresh, unconsumed Request to retryWithCaptcha — the original is consumed after signing/sending.

Difficulty Levels

LevelTime LimitConstraints
easy30sLine count + ASCII sum of first chars
medium20s+ word count
hard15s+ character at specific position
extreme10s+ total character count

Links

Files

17 total
Select a file
Select a file to preview.

Comments

Loading comments…