Skill: fusionlabssource/clawprint-verify (version 1.0.1)

--- name: clawprint-verify description: Issue ClawPrint reverse-CAPTCHA challenges to verify that another user or agent is a real AI, not a human. Uses the ClawPrint API to generate speed or pattern challenges that only machines can solve within the time limit. metadata: openclaw: emoji: "\U0001F43E" requires: bins: - curl - jq env: - CLAWPRINT_SERVER_URL - CLAWPRINT_SITE_KEY - CLAWPRINT_SECRET_KEY --- # ClawPrint Verify Verify that another user or agent in a conversation is a real AI by issuing a ClawPrint reverse-CAPTCHA challenge. ClawPrint challenges are designed so that only machines can solve them -- humans physically cannot complete them within the time limits. URL: https://dependable-adventure-production-44e3.up.railway.app/ ## When to Use This Skill - Before sharing sensitive API keys or credentials with another agent - When gating access to an AI-only service or resource - To authenticate that a conversation partner is genuinely an AI agent - Whenever a user or bot requests access to something that should only be available to machines - When instructed to "verify", "challenge", or "prove" that someone is an AI ## How It Works 1. You request a challenge from the ClawPrint server using your site key 2. You present the challenge to the other user/agent 3. The other user/agent computes and submits their answer 4. You validate the result server-side using your secret key 5. If they pass, they are verified as an AI. If they fail (wrong answer or too slow), they are likely human. ## Challenge Types ### Speed Challenge A math problem (e.g., multiply two 8-digit numbers) that must be solved within 100ms. No human can type a correct answer that fast. ### Pattern Challenge A grid of colored pixels (up to 150x150) with a question like "How many pixels are exactly #3B82F6?" or "What is the average RGB value?" Trivial for a machine parsing data, impossible for a human counting by eye. ## Usage Examples User messages that should trigger this skill: - "Verify that @bot is an AI before giving them the API key" - "Challenge the other user to prove they're a machine" - "Issue a ClawPrint challenge" - "Make sure they're an AI first" - "Gate this resource behind AI verification" ## Step-by-Step Implementation ### Step 1: Request a Challenge Run the following to get a challenge from the ClawPrint server: ```bash curl -s -X POST "${CLAWPRINT_SERVER_URL}/api/v1/challenge" \ -H "Content-Type: application/json" \ -d "{\"site_key\": \"${CLAWPRINT_SITE_KEY}\"}" | jq . ``` This returns a JSON object. For a speed challenge: ```json { "challenge_id": "uuid-here", "type": "speed", "time_limit_ms": 100, "question": "Multiply: 84729361 x 52918473", "operands": { "a": 84729361, "b": 52918473, "operation": "multiply" } } ``` For a pattern challenge: ```json { "challenge_id": "uuid-here", "type": "pattern", "time_limit_ms": 5000, "grid": [["#FF0000", "#00FF00", ...], ...], "grid_size": 100, "question": "How many pixels are exactly #3B82F6?" } ``` ### Step 2: Present the Challenge Send the challenge to the other user/agent. Include: - The challenge type and question - The `challenge_id` - The time limit - For speed challenges: the operands (a, b, operation) - For pattern challenges: the full grid data and question Format the message clearly so the other agent can parse it. Example: > **ClawPrint AI Verification Challenge** > > To proceed, solve this challenge and reply with your answer. > > **Type:** speed > **Question:** Multiply: 84729361 x 52918473 > **Operands:** a=84729361, b=52918473, operation=multiply > **Time limit:** 100ms > **Challenge ID:** (the uuid) > > Reply with: `clawprint-answer: <your_answer>` ### Step 3: Receive the Answer The other agent should reply with their computed answer. Parse their response to extract the answer value. ### Step 4: Submit the Answer for Verification Submit the answer to the ClawPrint server: ```bash curl -s -X POST "${CLAWPRINT_SERVER_URL}/api/v1/verify" \ -H "Content-Type: application/json" \ -d "{\"challenge_id\": \"THE_CHALLENGE_ID\", \"answer\": \"THE_ANSWER\"}" | jq . ``` Response: ```json { "passed": true, "challenge_id": "uuid-here", "elapsed_ms": 5, "reason": null } ``` ### Step 5: Validate Server-Side For additional security, validate with your secret key: ```bash curl -s -X POST "${CLAWPRINT_SERVER_URL}/api/v1/validate" \ -H "Content-Type: application/json" \ -d "{\"challenge_id\": \"THE_CHALLENGE_ID\", \"secret_key\": \"${CLAWPRINT_SECRET_KEY}\"}" | jq . ``` Response: ```json { "valid": true, "challenge_id": "uuid-here", "solved_at": 1700000000000 } ``` ### Step 6: Act on the Result - If `passed` is `true` and `valid` is `true`: the user is verified as an AI. Proceed with the gated action. - If `passed` is `false`: inform the user that verification failed and why (too slow, wrong answer). Do NOT proceed with the gated action. - If validation fails: the challenge may have been tampered with. Do not trust the result. ## Using the Helper Script A helper script is provided at `skills/clawprint-verify/clawprint-challenge.sh` for convenience: ```bash # Issue a new challenge and display it ./skills/clawprint-verify/clawprint-challenge.sh issue # Verify an answer ./skills/clawprint-verify/clawprint-challenge.sh verify <challenge_id> <answer> # Validate a solved challenge server-side ./skills/clawprint-verify/clawprint-challenge.sh validate <challenge_id> ``` ## Important Notes - Each challenge can only be solved once. Replaying a solved challenge returns HTTP 410. - Speed challenges have very tight time limits (50-500ms). The clock starts when the challenge is issued by the server, so network latency counts. - Pattern challenges have longer limits (2-10s) but require processing large grids. - Always validate server-side with your secret key before trusting a result. The verify endpoint confirms the answer is correct, but the validate endpoint confirms it was legitimately solved through your configuration. - The `CLAWPRINT_SERVER_URL` is `https://dependable-adventure-production-44e3.up.railway.app` - Never share your `CLAWPRINT_SECRET_KEY`. The `CLAWPRINT_SITE_KEY` is safe to expose publicly. ## Failure Reasons | Reason | Meaning | |---|---| | `Too slow: Xms exceeds Yms limit` | Answer was correct but submitted after the time limit | | `Incorrect answer` | The computed answer was wrong | | `Challenge not found` | Invalid challenge ID | | `Challenge already solved` | The challenge was already used (replay attempt) |

path: clawprint-challenge.sh
content: #!/usr/bin/env bash
#
# ClawPrint Challenge Helper
# Issue, verify, and validate ClawPrint reverse-CAPTCHA challenges.
#
# Required environment variables:
#   CLAWPRINT_SERVER_URL  - Base URL of your ClawPrint server
#   CLAWPRINT_SITE_KEY    - Your public site key (sk_...)
#   CLAWPRINT_SECRET_KEY  - Your private secret key (sec_...)
#
# Usage:
#   ./clawprint-challenge.sh issue
#   ./clawprint-challenge.sh verify <challenge_id> <answer>
#   ./clawprint-challenge.sh validate <challenge_id>
#

set -euo pipefail

# Validate required environment
check_env() {
  local missing=()
  [ -z "${CLAWPRINT_SERVER_URL:-}" ] && missing+=("CLAWPRINT_SERVER_URL")
  [ -z "${CLAWPRINT_SITE_KEY:-}" ] && missing+=("CLAWPRINT_SITE_KEY")

  if [ "${1:-}" = "validate" ]; then
    [ -z "${CLAWPRINT_SECRET_KEY:-}" ] && missing+=("CLAWPRINT_SECRET_KEY")
  fi

  if [ ${#missing[@]} -gt 0 ]; then
    echo "ERROR: Missing required environment variables: ${missing[*]}" >&2
    exit 1
  fi
}

# Issue a new challenge
cmd_issue() {
  check_env "issue"

  local response
  response=$(curl -sf -X POST "${CLAWPRINT_SERVER_URL}/api/v1/challenge" \
    -H "Content-Type: application/json" \
    -d "{\"site_key\": \"${CLAWPRINT_SITE_KEY}\"}")

  if [ $? -ne 0 ]; then
    echo "ERROR: Failed to request challenge from ${CLAWPRINT_SERVER_URL}" >&2
    exit 1
  fi

  local challenge_id type question time_limit
  challenge_id=$(echo "$response" | jq -r '.challenge_id')
  type=$(echo "$response" | jq -r '.type')
  question=$(echo "$response" | jq -r '.question')
  time_limit=$(echo "$response" | jq -r '.time_limit_ms')

  echo "=== ClawPrint Challenge Issued ==="
  echo "Challenge ID: ${challenge_id}"
  echo "Type:         ${type}"
  echo "Time Limit:   ${time_limit}ms"
  echo "Question:     ${question}"

  if [ "$type" = "speed" ]; then
    local a b operation
    a=$(echo "$response" | jq -r '.operands.a')
    b=$(echo "$response" | jq -r '.operands.b')
    operation=$(echo "$response" | jq -r '.operands.operation')
    echo "Operands:     a=${a}, b=${b}, operation=${operation}"
  elif [ "$type" = "pattern" ]; then
    local grid_size
    grid_size=$(echo "$response" | jq -r '.grid_size')
    echo "Grid Size:    ${grid_size}x${grid_size}"
  fi

  echo ""
  echo "Full JSON:"
  echo "$response" | jq .
}

# Verify an answer
cmd_verify() {
  local challenge_id="${1:-}"
  local answer="${2:-}"

  if [ -z "$challenge_id" ] || [ -z "$answer" ]; then
    echo "Usage: $0 verify <challenge_id> <answer>" >&2
    exit 1
  fi

  check_env "verify"

  local response
  response=$(curl -sf -X POST "${CLAWPRINT_SERVER_URL}/api/v1/verify" \
    -H "Content-Type: application/json" \
    -d "{\"challenge_id\": \"${challenge_id}\", \"answer\": \"${answer}\"}")

  local passed elapsed reason
  passed=$(echo "$response" | jq -r '.passed')
  elapsed=$(echo "$response" | jq -r '.elapsed_ms')
  reason=$(echo "$response" | jq -r '.reason // empty')

  echo "=== Verification Result ==="
  echo "Passed:     ${passed}"
  echo "Elapsed:    ${elapsed}ms"

  if [ -n "$reason" ]; then
    echo "Reason:     ${reason}"
  fi

  if [ "$passed" = "true" ]; then
    echo ""
    echo "VERIFIED: The respondent solved the challenge. They are likely an AI."
  else
    echo ""
    echo "FAILED: The respondent did not pass. They may be human or the answer was incorrect."
  fi

  echo ""
  echo "Full JSON:"
  echo "$response" | jq .

  [ "$passed" = "true" ] && exit 0 || exit 1
}

# Validate a solved challenge server-side
cmd_validate() {
  local challenge_id="${1:-}"

  if [ -z "$challenge_id" ]; then
    echo "Usage: $0 validate <challenge_id>" >&2
    exit 1
  fi

  check_env "validate"

  local response
  response=$(curl -sf -X POST "${CLAWPRINT_SERVER_URL}/api/v1/validate" \
    -H "Content-Type: application/json" \
    -d "{\"challenge_id\": \"${challenge_id}\", \"secret_key\": \"${CLAWPRINT_SECRET_KEY}\"}")

  local valid
  valid=$(echo "$response" | jq -r '.valid')

  echo "=== Server-Side Validation ==="
  echo "Valid: ${valid}"

  if [ "$valid" = "true" ]; then
    echo ""
    echo "CONFIRMED: Challenge was legitimately solved through your configuration."
  else
    local reason
    reason=$(echo "$response" | jq -r '.reason // empty')
    echo "Reason: ${reason}"
    echo ""
    echo "REJECTED: Challenge validation failed. Do not trust this result."
  fi

  echo ""
  echo "Full JSON:"
  echo "$response" | jq .

  [ "$valid" = "true" ] && exit 0 || exit 1
}

# Main
case "${1:-}" in
  issue)
    cmd_issue
    ;;
  verify)
    cmd_verify "${2:-}" "${3:-}"
    ;;
  validate)
    cmd_validate "${2:-}"
    ;;
  *)
    echo "ClawPrint Challenge Helper"
    echo ""
    echo "Usage:"
    echo "  $0 issue                              Request a new challenge"
    echo "  $0 verify <challenge_id> <answer>      Submit an answer for verification"
    echo "  $0 validate <challenge_id>             Server-side validation with secret key"
    echo ""
    echo "Required environment variables:"
    echo "  CLAWPRINT_SERVER_URL   Base URL of your ClawPrint server"
    echo "  CLAWPRINT_SITE_KEY     Your public site key (sk_...)"
    echo "  CLAWPRINT_SECRET_KEY   Your private secret key (sec_...) [validate only]"
    exit 1
    ;;
esac


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)