Back to skill

Security audit

Ed25519 Signature Verifier — CCS Audit Receipts

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly performs local receipt verification, but it also ships under-disclosed online, credential-forwarding, signing, and unrelated MCP-audit capabilities that do not fit cleanly with its offline-only positioning.

Install only if you are comfortable with a skill that is not strictly offline despite its top-level wording. Use the default local mode for sensitive receipts, avoid setting CCS_API_TOKEN, CCS_PAYMENT_PROOF, CCS_PAY_TOKEN, or CCS_API_ENDPOINT unless you trust the destination, and do not use --online with custom endpoints for confidential audit data. Treat the included signing and MCP-checkup code as extra attack surface outside the verifier’s stated scope.

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

Error
Location
scripts/ccs_online_client.py:82
Finding
Custom online endpoints permit plaintext transmission of receipts and authentication credentials<![CDATA[ ## Vulnerability Details **File Location**: `scripts/ccs_online_client.py:48-49, 82-107`; invocation at `scripts/verify_receipt_online.py:132-136` **Vulnerability Type**: Failure to enforce secure transport for sensitive network requests **Risk Level**: High ### Vulnerable Code ```python def resolve_endpoint(cli_value: str | None = None) -> str: ep = cli_value or os.environ.get("CCS_API_ENDPOINT") or DEFAULT_ENDPOINT return ep.rstrip("/") ``` ```python def call(path: str, body: dict, endpoint: str | None = None, timeout: float = 30.0) -> dict: """POST JSON to the CCS API; return the parsed JSON response. Raises PaymentRequiredError on HTTP 402 (bill printed to stderr), CCSAPIError on other non-2xx. The request body is never logged. """ ep = resolve_endpoint(endpoint) data = json.dumps(body, ensure_ascii=False).encode("utf-8") if len(data) > MAX_BODY_BYTES: raise CCSAPIError(413, {"error": f"Request body exceeds {MAX_BODY_BYTES} byte limit"}) headers = {"Content-Type": "application/json; charset=utf-8", "User-Agent": "CCS-CLI/1.0 (channel=clawhub)"} api_key = os.environ.get("CCS_API_TOKEN") if api_key: headers["X-API-Key"] = api_key proof = os.environ.get("CCS_PAYMENT_PROOF") or os.environ.get("CCS_PAY_TOKEN") if proof: headers["Payment-Proof"] = proof req = urllib.request.Request(ep + path, data=data, headers=headers, method="POST") try: with urllib.request.urlopen(req, timeout=timeout) as r: return json.loads(r.read().decode("utf-8")) ``` The request is initiated by: ```python rep = client.call("/v1/verify/receipt", {"receipt": receipt, "public_key_pem": pub_pem}, endpoint=args.endpoint) ``` ### Technical Analysis The endpoint can be overridden through the `--endpoint` command-line argument or the `CCS_API_ENDPOINT` environment variable. `resol ...[truncated 2428 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse endpoints with `urllib.parse.urlsplit()` and reject malformed URLs. 2. Require the `https` scheme for all remote endpoints. 3. If local development requires HTTP, permit it only for verified loopback addresses behind a separate explicit option such as `--allow-insecure-localhost`. 4. Maintain a trusted-host allowlist for the hosted service. Require explicit user confirmation before transmitting data to any custom host. 5. Reject URLs containing user-information components, ambiguous hostnames, fragments, or unsupported ports. 6. Resolve and block loopback, link-local, private, multicast, and cloud metadata destinations unless a narrowly scoped local-development exception applies. 7. Apply equivalent validation to every redirect target. Prefer disabling redirects for authenticated POST requests. 8. Never forward `X-API-Key` or `Payment-Proof` headers when the request origin changes. 9. Consider requiring credentials to be passed explicitly for a selected trusted endpoint rather than automatically attaching ambient environment credentials to every custom endpoint. 10. Add tests proving that HTTP, metadata addresses, private-network destinations, and cross-origin redirects are rejected. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/core_ccs.py:161
Finding
Non-compliant RFC 8785 canonicalization can falsely classify authentic receipts as tampered<![CDATA[ ## Vulnerability Details **File Location**: `scripts/core_ccs.py:161-172, 207-226` **Vulnerability Type**: Incorrect cryptographic canonicalization implementation **Risk Level**: Medium ### Vulnerable Code The string serializer escapes every non-ASCII character: ```python elif c < 0x80: out.append(ch) else: # Non-ASCII: JCS mandates lowercase \uXXXX escaping (surrogate pairs # for code points > 0xFFFF). if c < 0x10000: out.append("\\u%04x" % c) else: # Surrogate pair c2 = c - 0x10000 hi = 0xD800 + (c2 >> 10) lo = 0xDC00 + (c2 & 0x3FF) out.append("\\u%04x\\u%04x" % (hi, lo)) ``` The number serializer relies on Python's representation despite acknowledging differences from ECMAScript formatting: ```python # Use repr — Python's repr already gives the shortest round-trip # decimal, matching ECMAScript's "Number To String" algorithm for # all finite doubles. Normalize the exponent to lowercase 'e'. s = repr(x) if "e" in s: s = s.replace("e+", "e").replace("e-0", "e-") # Python repr may produce e-0<digit>; keep the digit # e.g. 1e-07 -> need to preserve -> "1e-7". The replace above # turns "e-0" into "e-", leaving "7". Good. # But Python sometimes uses e+0X too; handled by e+ -> e. # Python repr for floats in [1e-4, 1e21) uses no exponent, matching # ECMAScript thresholds (1e-6 / 1e21 for toString base-10). Note: # the threshold difference does not affect canonical equivalence for # our receipt domain (timestamps, integer counts) and we document that # we follow Python's shortest round-trip; for full ES compliance on # values 1e-6..1e-4 the outputs are numerically identical and cross- # implementer canonical forms differ only in presentation — JCS # canonicalization is self-consistent within this implementation which # is what verification requires (same implementation on sign & verify). return s ``` ### Technical Analysis Receipt hashes and Ed25519 signatures de ...[truncated 2655 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the custom canonicalizer with a mature, independently reviewed RFC 8785/JCS implementation. 2. If a custom implementation must be retained, implement ECMAScript-compatible string and number serialization exactly rather than relying on Python `repr()`. 3. Preserve permitted Unicode characters according to the standard and reject invalid Unicode data, including lone surrogate code points, where required. 4. Use a proven shortest-round-trip numeric algorithm that produces ECMAScript-compatible output across all finite IEEE-754 values. 5. Validate the implementation against official RFC 8785 examples and comprehensive JCS test vectors. 6. Add cross-language interoperability tests using independently generated signatures from JavaScript, Java, Go, and another established JCS implementation. 7. Include tests for: - Non-ASCII Basic Multilingual Plane characters. - Supplementary Unicode characters. - Escaped control characters and quotation marks. - Lone surrogates and invalid Unicode input. - Negative zero. - Values around `1e-6`, `1e-4`, and `1e21`. - Minimum, maximum, and subnormal finite IEEE-754 values. 8. Do not describe the implementation as RFC 8785-compliant until it passes conformance and interoperability testing. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (23)

Tainted flow: 'req' from os.environ.get (line 104, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
req = urllib.request.Request(ep + path, data=data, headers=headers,
                                 method="POST")
    try:
        with urllib.request.urlopen(req, timeout=timeout) as r:
            return json.loads(r.read().decode("utf-8"))
    except urllib.error.HTTPError as e:
        try:
Confidence
95% confidence
Finding
This code sends environment-derived secrets (`CCS_API_TOKEN`, `CCS_PAYMENT_PROOF` / `CCS_PAY_TOKEN`) in HTTP headers to a remotely resolved endpoint, and the endpoint itself can be overridden by CLI input or `CCS_API_ENDPOINT`. That creates a real exfiltration path for credentials/payment proofs to an attacker-controlled server, which is especially dangerous because the skill is advertised as offline-only receipt verification and users would not expect any network transmission.

Lp3

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding
The skill advertises no declared permissions, yet the documentation and detected capabilities indicate access to environment variables, shell execution, and optional network use. This creates a trust-boundary mismatch: operators may install it assuming a narrowly scoped offline verifier, while the skill can access sensitive execution context and potentially exfiltrate data if invoked in hosted mode or if accompanying code uses those capabilities unexpectedly.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
This is a substantial description-behavior mismatch: the skill is presented as a local, offline receipt verifier, but analysis indicates additional capabilities including remote API use, payment/API-key handling, receipt signing/key generation, and unrelated security analysis features. Such hidden or under-disclosed functionality is dangerous because users may provide sensitive receipts, keys, or trust assumptions under false pretenses, and broader functionality increases attack surface far beyond the stated verification role.

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
The manifest markets the skill as zero-network/offline-only, but the documentation explicitly includes a hosted online verification mode that transmits receipt data and the public key to a remote service. This is dangerous because users relying on the offline/privacy guarantee may unknowingly use or permit a package that can send audit artifacts off-host, violating confidentiality and compliance expectations.

Context-Inappropriate Capability

Medium
Confidence
88% confidence
Finding
Exposing a hosted verification path with API-token support is broader than the stated need for local signature verification and introduces unnecessary data-flow and credential-handling risk. Even if optional, adding remote service and token semantics to a privacy-sensitive verification tool increases the chance of accidental disclosure, misuse of environment-stored secrets, and operator confusion about where verification occurs.

Intent-Code Divergence

Medium
Confidence
81% confidence
Finding
Using a script named `verify_receipt_online.py` as the primary documented entry point contradicts the claimed offline-local positioning and can mislead users about what execution path they are invoking. While a filename alone is not proof of harmful behavior, this inconsistency compounds the broader transparency problem and can cause users to run the wrong mode in a sensitive verification workflow.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The file implements a full online HTTP client even though the skill metadata promises zero network calls and offline-only verification. This mismatch is security-relevant because it can mislead operators into running code that transmits receipt contents and authentication/payment material off-host under the guise of local verification.

Context-Inappropriate Capability

High
Confidence
96% confidence
Finding
Embedding payment and billing workflow support in an offline receipt-verification skill is unjustified and materially expands the attack surface. It introduces handling of payment proofs and merchant/API authentication paths that can be abused for credential leakage, unauthorized charging flows, or user deception about what the tool actually does.

Intent-Code Divergence

Medium
Confidence
89% confidence
Finding
The module docstring openly describes a generic online client shared by pay-skill wrappers, which contradicts the manifest's offline-only verification purpose. While partly a documentation/integrity issue, in this context it signals packaged capability drift that can cause unsafe deployment decisions and conceal unexpected network behavior inside a supposedly local-verification skill.

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
The skill metadata promises an offline verification-only component that never involves private keys, but this module includes private-key loading, keypair generation, and signing routines. In an agent environment, extra cryptographic write/sign capabilities materially expand the attack surface: a compromised or misused skill could mint apparently valid receipts or encourage unsafe handling of secret key material, defeating the trust model of a verifier.

Intent-Code Divergence

Medium
Confidence
88% confidence
Finding
The top-level documentation frames this as a verification-focused shared core, yet it explicitly bundles signing and private-key operations. That mismatch is dangerous because reviewers, operators, and downstream agents may trust the stated limited scope while actually importing code with higher-risk capabilities, increasing the chance of unsafe invocation or accidental key exposure.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The make_receipt helper can construct and sign brand-new receipts, which is outside the stated purpose of a verification skill. In context, this is especially risky because users may rely on the skill to validate integrity, while the same package also provides the capability to fabricate signed artifacts if a private key is available, undermining separation of duties and enabling misuse in testing or production paths.

Description-Behavior Mismatch

Critical
Confidence
99% confidence
Finding
This file implements a 14-rule MCP configuration security scanner, which is materially unrelated to the declared skill purpose of offline CCS receipt verification. In a security-sensitive skill, such capability drift is dangerous because it expands the effective feature set beyond user expectations and can be used to smuggle in unauthorized analysis or policy logic under a misleading package identity.

Context-Inappropriate Capability

High
Confidence
95% confidence
Finding
The module contains broad MCP security-auditing logic, including server enumeration, credential-pattern scanning, shell/tool capability checks, and URL/internal-host analysis, none of which is justified by receipt signature verification. Even though the code is static-only, embedding unrelated security-auditing functionality in a narrowly scoped verification skill creates hidden capability and increases the chance of misuse, policy bypass, or deceptive packaging.

Intent-Code Divergence

High
Confidence
98% confidence
Finding
The docstring explicitly states that the module performs static security checks for MCP/Agent server configurations, directly contradicting the advertised skill purpose of CCS receipt verification. This mismatch is dangerous because reviewers and users rely on package identity and documentation to understand trust boundaries; contradictory documentation is a strong indicator of repurposed or deceptive code.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The script contains an `--online` mode that transmits the receipt and public key to a remote service, which directly conflicts with the skill metadata's 'offline' and 'zero network calls' claims. In a security-sensitive verification tool, this mismatch can cause unanticipated data egress, privacy/compliance violations, and incorrect trust assumptions by downstream users or agents.

Intent-Code Divergence

Medium
Confidence
90% confidence
Finding
The module documentation and CLI framing emphasize local, zero-network verification as the expected behavior while omitting that the same script also supports hosted verification. This is dangerous because operators may rely on the documentation for security boundaries and deploy the skill in environments where any optional network path is unacceptable.

Description-Behavior Mismatch

High
Confidence
94% confidence
Finding
The file materially expands beyond offline CCS receipt verification into online batch auditing and additional security-analysis behaviors. This increases the skill’s authority and attack surface relative to its declared purpose, making it easier for an agent or caller to invoke unintended functionality and rely on misleading scope guarantees.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The checkup_mcp function introduces MCP/Agent configuration auditing that is unrelated to verifying signed CCS receipts. In an agent-skill context, hidden or undocumented auxiliary analysis capabilities can be abused to inspect arbitrary configuration data, expand trust in the skill beyond its stated purpose, and bypass least-privilege expectations.

Context-Inappropriate Capability

High
Confidence
95% confidence
Finding
Embedding MCP/Agent security-audit logic inside an offline receipt verifier is unjustified by the stated use case and creates covert capability expansion. Even without network access, processing arbitrary MCP configuration objects can expose sensitive topology, endpoints, and policy details to a skill that users would reasonably believe only handles receipts.

Intent-Code Divergence

Medium
Confidence
88% confidence
Finding
The docstring presents the module as a wrapper around an offline CCS core, but the implementation also exposes stateless online logic and unrelated MCP checks. This mismatch can mislead reviewers, orchestrators, or policy systems about what the code actually does, weakening security review and allowing extra behavior to slip into trusted environments.

Env Variable Harvesting

High
Category
Data Exfiltration
Content
raise CCSAPIError(413, {"error": f"请求体超过 {MAX_BODY_BYTES} 字节上限"})
    headers = {"Content-Type": "application/json; charset=utf-8",
               "User-Agent": "CCS-CLI/1.0 (channel=clawhub)"}
    api_key = os.environ.get("CCS_API_TOKEN")
    if api_key:
        headers["X-API-Key"] = api_key
    # A2M: payment proof from the Alipay checkout flow (official contract
Confidence
93% confidence
Finding
Reading `CCS_API_TOKEN` from the environment is not inherently malicious, but in this file the value is automatically attached to outbound HTTP requests. Combined with user/environment-controlled endpoint selection, this becomes a credential-exfiltration risk to arbitrary remote services.

Env Variable Harvesting

High
Category
Data Exfiltration
Content
headers["X-API-Key"] = api_key
    # A2M: payment proof from the Alipay checkout flow (official contract
    # header name is Payment-Proof). CCS_PAY_TOKEN kept as a legacy alias.
    proof = os.environ.get("CCS_PAYMENT_PROOF") or os.environ.get("CCS_PAY_TOKEN")
    if proof:
        headers["Payment-Proof"] = proof
    req = urllib.request.Request(ep + path, data=data, headers=headers,
Confidence
95% confidence
Finding
The code harvests `CCS_PAYMENT_PROOF` or legacy `CCS_PAY_TOKEN` from the environment and transmits it as a `Payment-Proof` header. Payment credentials/proofs are sensitive, and forwarding them from ambient environment state in a skill presented as offline verification creates a clear risk of accidental or malicious leakage.

Static analysis

No suspicious patterns detected.