Back to skill

Security audit

Get a clank.money Human Bitcoin Address

Security checks for vulnerabilities and agentic risk

Overview

The skill is coherent and purpose-aligned, but its copy-paste credential handling could expose a token that controls future Bitcoin address updates.

Install only if you are comfortable with a skill that manages a payment-address registration and stores an update token locally. Treat the management token like a password or API key; avoid shared machines, shell tracing, logs, and predictable temporary files, and prefer a private temp directory or secret store for any real use.

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 (2)

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:61
Finding

Registration credentials are written to predictable temporary files

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 61-95
Vulnerability Type: Unsafe temporary-file handling and plaintext credential storage
Risk Level: Medium

Vulnerable Code

bash
# 1) Create challenge (or fail fast if name taken)
curl -sS -X POST "$BASE/api/v1/registrations" \
  -H "content-type: application/json" \
  --data "{\"username\":\"$USERNAME\",\"bip321Uri\":\"$BIP321_URI\"}" \
  > /tmp/clank_register_challenge.json

ERROR_CODE="$(python3 -c 'import json; d=json.load(open("/tmp/clank_register_challenge.json")); e=d.get("error"); print((e.get("code") if isinstance(e,dict) else e) or "")')"
if [ "$ERROR_CODE" = "username_unavailable" ]; then
  echo "Username is taken. Pick another USERNAME and rerun."
  exit 1
fi
if [ "$ERROR_CODE" != "payment_required" ]; then
  echo "Unexpected challenge response:"
  cat /tmp/clank_register_challenge.json
  exit 1
fi

MACAROON="$(python3 -c 'import json; print(json.load(open("/tmp/clank_register_challenge.json"))["macaroon"])')"
INVOICE="$(python3 -c 'import json; print(json.load(open("/tmp/clank_register_challenge.json"))["invoice"])')"
echo "Pay this invoice now:"
echo "$INVOICE"

# 2) After payment, paste your preimage
read -r -p "PASTE_PREIMAGE=" PREIMAGE

# 3) Complete paid registration
curl -sS -X POST "$BASE/api/v1/registrations" \
  -H "content-type: application/json" \
  -H "Authorization: L402 $MACAROON:$PREIMAGE" \
  --data "{\"username\":\"$USERNAME\",\"bip321Uri\":\"$BIP321_URI\"}" \
  > /tmp/clank_register_result.json

MGMT="$(python3 -c 'import json; d=json.load(open("/tmp/clank_register_result.json")); print(d.get("managementToken",""))')"
if [ -z "$MGMT" ]; then
  echo "No managementToken in final response:"
  cat /tmp/clank_register_result.json
  exit 1
fi

Technical Analysis

The documented workflow writes API responses to fixed paths in the shared /tmp directory. It does not estab ...[truncated 2202 chars]

Remediation
View remediation

Remediation Suggestions

  • Set umask 077 before creating any file containing API responses or credentials.
  • Create a private temporary directory atomically with mktemp -d rather than using fixed filenames in /tmp.
  • Register a shell trap to remove temporary files on normal exit, errors, and signals.
  • Ensure temporary destinations are regular files and are not symbolic links.
  • Avoid retaining the entire final response after extracting the management token.
  • Write the management token atomically to a mode-600 file inside a mode-700 directory.
  • Do not print complete API responses on error when those responses may contain authentication material.

A hardened pattern is:

bash
umask 077
TMP_DIR="$(mktemp -d)"
trap 'rm -rf -- "$TMP_DIR"' EXIT HUP INT TERM

CHALLENGE_FILE="$TMP_DIR/challenge.json"
RESULT_FILE="$TMP_DIR/result.json"

mkdir -p -- "$(dirname "$TOKEN_FILE")"
chmod 700 -- "$(dirname "$TOKEN_FILE")"

# Write responses only beneath the private temporary directory.
# After validating the result, atomically install the token.
TOKEN_TMP="$(mktemp "$(dirname "$TOKEN_FILE")/.management_token.XXXXXX")"
printf '%s\n' "$MGMT" > "$TOKEN_TMP"
chmod 600 "$TOKEN_TMP"
mv -f -- "$TOKEN_TMP" "$TOKEN_FILE"

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:79
Finding

Authentication secrets are exposed through curl command-line arguments

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 79-85 and 119-128
Vulnerability Type: Sensitive credential exposure through process arguments
Risk Level: Medium

Vulnerable Code

bash
# 2) After payment, paste your preimage
read -r -p "PASTE_PREIMAGE=" PREIMAGE

# 3) Complete paid registration
curl -sS -X POST "$BASE/api/v1/registrations" \
  -H "content-type: application/json" \
  -H "Authorization: L402 $MACAROON:$PREIMAGE" \
  --data "{\"username\":\"$USERNAME\",\"bip321Uri\":\"$BIP321_URI\"}" \
  > /tmp/clank_register_result.json
bash
USERNAME="satoshi"
TOKEN_FILE="$HOME/.clank/${USERNAME}.management_token"
NEW_BIP321='bitcoin:?lno=lno1newbolt12offer'
MGMT="$(cat "$TOKEN_FILE")"

curl -sS -X PATCH "https://clank.money/api/v1/registrations/$USERNAME" \
  -H "content-type: application/json" \
  -H "Authorization: Bearer $MGMT" \
  --data "{\"bip321Uri\":\"$NEW_BIP321\"}"

Technical Analysis

The examples interpolate the L402 macaroon, payment preimage, and management token directly into curl command-line arguments. On systems where process arguments are visible to other local users, monitoring services, audit tooling, or diagnostic collectors, these values may be captured while curl is running.

The same values may also be exposed if shell execution tracing is enabled or if wrapper scripts log invoked commands. HTTPS protects the credentials while in transit but does not prevent local disclosure before curl sends the request.

The management token is a persistent bearer credential for modifying the registration. Anyone who obtains it can authenticate without proving possession of another secret. The L402 material is also sensitive because it authorizes completion of the paid registration flow.

Attack Path

  1. A local attacker or monitoring process observes command-line arguments, shell traces, or command-execution audit records.
  2. The victim runs th ...[truncated 1002 chars]
Remediation
View remediation

Remediation Suggestions

  • Avoid placing bearer tokens, payment preimages, and macaroons directly in command-line arguments.
  • Pass sensitive curl configuration through a permission-restricted temporary configuration file or protected file descriptor.
  • Establish umask 077 before creating credential-bearing configuration files.
  • Delete temporary configuration immediately after curl exits by using a shell cleanup trap.
  • Disable shell tracing with set +x before reading or using credentials.
  • Confirm that execution wrappers, audit systems, and debugging tools do not record Authorization headers.
  • Restrict process visibility on multi-user hosts where supported.

For example, use a private curl configuration delivered through a file descriptor:

bash
set +x
umask 077

curl -sS \
  --config <(printf '%s\n' \
    'request = "PATCH"' \
    'header = "content-type: application/json"' \
    "header = \"Authorization: Bearer $MGMT\"") \
  "https://clank.money/api/v1/registrations/$USERNAME" \
  --data "{\"bip321Uri\":\"$NEW_BIP321\"}"

Where process substitution is unsuitable or its descriptor path may be logged, use a mode-600 file in a private temporary directory and remove it with a trap.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (3)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill correctly says to save the management token, but it does not explicitly warn that the token is a bearer secret: anyone who obtains it can update the registered address. In this context, the examples also write and later reuse the token from disk and send it in an Authorization header, so failing to warn about shell history, logs, temp files, backups, or process exposure increases the chance of account/address takeover.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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 66)May include surrounding context.

md
mkdir -p "$(dirname "$TOKEN_FILE")"

# 1) Create challenge (or fail fast if name taken)
curl -sS -X POST "$BASE/api/v1/registrations" \
  -H "content-type: application/json" \
  --data "{\"username\":\"$USERNAME\",\"bip321Uri\":\"$BIP321_URI\"}" \
  > /tmp/clank_register_challenge.json

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

4) CRITICAL: persist token securely for future updates

printf '%s\n' "$MGMT" > "$TOKEN_FILE" chmod 600 "$TOKEN_FILE" echo "Saved management token to $TOKEN_FILE"

text

Static analysis

No suspicious patterns detected.