Versioned security assessment

Report ID: SA-3F6E026A

7/19/2026, 10:42:12 AM

kleros-ipfs-upload security assessment v2

Skill Security Certification Report

Audit History
Scanner version 3.0.0 Audit model: codex Latest published report
Skill name
kleros-ipfs-upload
Version
v2
Maintainer
internet-court
Coverage
4 Files scanned · 557 Lines analyzed
Policy version
skillstore-security-audit-policy-v1

Highest confirmed finding severity

High

10 confirmed security findings require attention.

Installation context

Check the current Skill page

This page summarizes report evidence only. The Skill page provides the canonical install advisory.

Open current Skill page

This report does not block or authorize the manifest or ZIP.

Most static alerts are false positives caused by Markdown backticks, TypeScript templates, documented URLs, and URL path text. Confirmed risks involve payment credentials, configurable paid endpoints, unpinned dependencies, and public evidence uploads. No prompt injection attempt was found.

Report position

Latest published report

Latest refers to the report sequence, not to artifact currentness.

Audit attestation

Attestation unavailable

No public attestation is available for this report.

Human verification

Not verified

No human verification is recorded for this report.

Coverage

4 Files scanned · 557 Lines analyzed

36 items shown for review

Limitations

This report does not claim runtime or sandbox execution and does not prove the absence of side effects.

Evidence chain

Follow the evidence from source binding to the install contract. Available evidence supports verification; it is not a safety guarantee.

  1. Source

    Commit and path bound

  2. Artifact

    Content and tree hashes bound

  3. Audit

    Complete

  4. Install contract

    Open manifest to verify

    Open manifest

Capabilities observed

Observed means this report recorded supporting evidence. Not recorded does not prove that a capability is absent.

Contains scripts

May execute code included with the Skill.

Observed in 1 evidence location

Network access

May connect to external services.

Observed in 18 evidence locations

Filesystem access

May read or write local files.

Observed in 11 evidence locations

Env variables

May read values from the process environment.

Observed in 30 evidence locations

External commands

May invoke commands or programs outside the Skill.

Observed in 50 evidence locations

Capability review items (26)
High
Generic API/secret keys
* CDP_API_KEY_ID=... CDP_API_KEY_SECRET=... CDP_WALLET_SECRET=... \
The documented invocation places CDP API and wallet secrets directly in a shell command. Real substitutions can persist in shell history or process inspection.
High
Generic API/secret keys
apiKeyId: creds.CDP_API_KEY_ID!,
The CDP API key identifier is loaded into a client that controls a server wallet. It is part of the credential set used for paid requests.
High
Generic API/secret keys
apiKeySecret: creds.CDP_API_KEY_SECRET!,
The script passes the CDP API secret into the wallet client. Compromise of this runtime or dependency can expose a payment credential.
High
Generic API/secret keys
* EVM_PRIVATE_KEY=0x... npx tsx pay-and-upload.ts ./somefile.txt
The documented invocation places an EVM private key directly in a shell command. A real key can persist in shell history or process inspection.
High
Generic API/secret keys
const rawKey = process.env.EVM_PRIVATE_KEY;
The script directly reads the payer private key and later creates a signer from it. This grants the process authority to authorize USDC payments.
High
Generic API/secret keys
EVM_PRIVATE_KEY=0xYourPayerKey npx tsx pay-and-upload.ts /path/to/file.json
The quickstart instructs users to place a payer private key directly in a shell command. Real keys can be retained in command history.
High
Generic API/secret keys
CDP_API_KEY_SECRET=... \
The command template places the CDP API secret directly on the command line. Replacing the placeholder can expose it through shell history.
High
Generic API/secret keys
If you'd rather not pass four env vars on the command line, point `CDP_CREDS_PATH` at a `.env`-style
The skill recommends a file containing CDP API and wallet secrets without requiring restrictive permissions. Weak file permissions could disclose wallet credentials.
High
Generic API/secret keys
EVM_PRIVATE_KEY=0x... npx tsx pay-and-upload.ts hello-world.txt
The paid smoke-test template places the private key in the command line. A real value can be retained in shell history.
High
Generic API/secret keys
CDP_API_KEY_ID=... CDP_API_KEY_SECRET=... CDP_WALLET_SECRET=... \
The CDP smoke-test template places multiple wallet credentials in one shell command. Real values can leak through history or process inspection.
High
Generic API/secret keys
2. Run the bundled script: `EVM_PRIVATE_KEY=0x... npx tsx pay-and-upload.ts /tmp/exhibit-a.png`.
The evidence-upload example places an EVM private key in an inline command. A real key can be retained in shell history.
High
Generic API/secret keys
1. `OPERATION=meta-evidence EVM_PRIVATE_KEY=0x... npx tsx pay-and-upload.ts ./case-42.json`.
The meta-evidence example places an EVM private key in an inline command. A real key can be retained in shell history.
Low
Hardcoded URL
process.env.GATEWAY_URL ?? "https://kleros-ipfs-gateway.fly.dev";
The executable defaults to this external host and later sends file data through a payment-enabled fetch. The network exposure is intentional but real.
Low
Environment variable access (bracket notation)
for (const key of required) creds[key] = process.env[key];
The loop reads named CDP credentials from the process environment. This is required functionality, but it gives the script access to payment secrets.
Low
Environment variable access (dot notation)
if (process.env.CDP_CREDS_PATH && required.some((k) => !creds[k])) {
CDP_CREDS_PATH controls whether the script loads credentials from a local file. A modified environment can redirect secret loading to another readable path.
Low
Environment variable access (dot notation)
const fromFile = await loadEnvFile(process.env.CDP_CREDS_PATH);
The environment value is passed directly to the credential-file loader. This is intentional, but it selects a local file containing payment secrets.
Low
Environment variable access (dot notation)
process.env.GATEWAY_URL ?? "https://kleros-ipfs-gateway.fly.dev";
GATEWAY_URL can redirect both the uploaded file and the payment-enabled request. The script does not constrain the configured origin.
Low
Environment variable object
for (const key of required) creds[key] = process.env[key];
The loop reads named CDP credentials from the process environment. This is required functionality, but it gives the script access to payment secrets.
Low
Environment variable object
if (process.env.CDP_CREDS_PATH && required.some((k) => !creds[k])) {
CDP_CREDS_PATH controls whether the script loads credentials from a local file. A modified environment can redirect secret loading to another readable path.
Low
Environment variable object
const fromFile = await loadEnvFile(process.env.CDP_CREDS_PATH);
The environment value is passed directly to the credential-file loader. This is intentional, but it selects a local file containing payment secrets.
Low
Environment variable object
process.env.GATEWAY_URL ?? "https://kleros-ipfs-gateway.fly.dev";
GATEWAY_URL can redirect both the uploaded file and the payment-enabled request. The script does not constrain the configured origin.
Low
Hardcoded URL
process.env.GATEWAY_URL ?? "https://kleros-ipfs-gateway.fly.dev";
The executable defaults to this external host and later sends file data through a payment-enabled fetch. The network exposure is intentional but real.
Low
Environment variable access (dot notation)
const rawKey = process.env.EVM_PRIVATE_KEY;
The script reads EVM_PRIVATE_KEY from the environment and later uses it to create a payment signer. This is direct access to a spending credential.
Low
Environment variable access (dot notation)
process.env.GATEWAY_URL ?? "https://kleros-ipfs-gateway.fly.dev";
GATEWAY_URL can redirect both the uploaded file and the payment-enabled request. The script does not constrain the configured origin.
Low
Environment variable object
const rawKey = process.env.EVM_PRIVATE_KEY;
The script reads EVM_PRIVATE_KEY from the environment and later uses it to create a payment signer. This is direct access to a spending credential.
Low
Environment variable object
process.env.GATEWAY_URL ?? "https://kleros-ipfs-gateway.fly.dev";
GATEWAY_URL can redirect both the uploaded file and the payment-enabled request. The script does not constrain the configured origin.

Risk findings

Confirmed security concerns are separated from items that still need review.

Confirmed security concerns (10)

RISK-001 High
Environment file access
if (process.env.CDP_CREDS_PATH && required.some((k) => !creds[k])) {
This condition enables credential loading from the path in CDP_CREDS_PATH. The following line reads sensitive wallet credentials from that file.
RISK-002 High
Environment file access
const fromFile = await loadEnvFile(process.env.CDP_CREDS_PATH);
The script reads the environment-selected file and parses CDP API and wallet secrets. This is direct access to a sensitive credential file.
RISK-003 High
Crypto seed/private key mention
const privateKey = (
This code normalizes the payer private key for signer construction. The value grants authority to authorize USDC payments.
RISK-004 High
Crypto seed/private key mention
const signer = await createSigner("base", privateKey);
The private key is passed to createSigner for Base payments. This is legitimate functionality with direct financial authority.
RISK-005 High
Environment file access
If you'd rather not pass four env vars on the command line, point `CDP_CREDS_PATH` at a `.env`-style
The instructions recommend storing CDP API and wallet secrets in an environment-style file. No restrictive permission requirement is provided.
RISK-006 High
Crypto seed/private key mention
const signer = await createSigner("base", privateKey);
The example creates a Base signer from a private key. Any process following it receives direct access to a spending credential.
RISK-007 High
Crypto seed/private key mention
node -e "import('viem/accounts').then(m => console.log(m.generatePrivateKey()))"
The command generates a private key and prints it to standard output. Agent logs or terminal capture can retain the secret.
RISK-008 High
Payment Terms Are Not Bounded
Both runners accept GATEWAY_URL and pass its challenge to a payment-enabled fetch. They enforce no origin, amount, token, network, or payee limit before signing.
The source shows an environment-controlled endpoint entering wrapFetchWithPayment without script-side validation. The documented wrapper automatically signs the server challenge.
RISK-009 High
No Sensitive Evidence Review
The skill encourages dispute screenshots and documents without requiring a sensitivity review. Uploads go to externally retrievable IPFS and third-party pinning infrastructure.
The documented use cases include evidence files, and the response section provides public gateway URLs. No redaction or confidentiality check is required before upload.
RISK-010 Medium
Unpinned Payment Dependencies
The skill instructs npm install while dependency versions use caret ranges and no lockfile. Future installs can change code that receives wallet credentials and signs payments.
The package manifest contains caret ranges, and SKILL.md explicitly says the lockfile is omitted so versions stay fresh.

Remediation

Suggested fixes recorded by this audit. Applying them is the maintainer’s responsibility.

  1. FIX-001
    High
    The payment wrapper trusts terms from an environment-controlled gateway.
    Allowlist the gateway origin and verify amount, token, network, and payee before signing. Reject any terms above the documented price.
  2. FIX-002
    High
    Examples place private keys and CDP secrets in shell commands.
    Use a protected secret manager or preconfigured environment. Use a dedicated low-balance payer and never print generated keys.
  3. FIX-003
    High
    Credential files can be selected without permission checks.
    Require an explicit trusted path, reject symlinks, and require owner-only file permissions before reading CDP credentials.
  4. FIX-004
    High
    Dispute evidence can contain confidential or personal information.
    Require a redaction and consent check before upload. Warn that public IPFS content can remain retrievable after publication.
  5. FIX-005
    Medium
    Payment dependencies use mutable version ranges without a lockfile.
    Pin exact versions, commit a reviewed lockfile, and verify dependency integrity before running code with wallet credentials.

Expert evidence

Immutable subject identity, scanner metadata, dismissed matches, and source-level evidence.

Artifact subject

Marketplace commit
3f6e026a3363e0954ede7bef0cfe88d4475de137
Content hash
ffbe871570e5225c4eb0c3587a3db3e3e5ce4fec32645fb10213c09883a8625e
Tree hash
9ac461a6d62dd477d1314d0708af584ee496702ebdabc5b3c6823bc47fe26c10
Skill path
skills/internet-court/kleros-ipfs-upload
Audit payload hash
233b4ba8bcb4c8410c8ae3749e98f2e9

Analysis metadata

Audit model: codex

Analysis state: Complete

Scope is limited to the recorded files, lines, methods, and evidence. No runtime or sandbox execution is claimed.

Verify and export

The manifest and lockfile bind install artifacts to cryptographic hashes. This integrity claim is separate from the security assessment.

Audit attestation: unavailable