Back to skill

Security audit

Orderly Api Authentication

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent Orderly authentication guide, but its examples include unsafe private-key handling and live trading or asset-moving flows that require review before use.

Review carefully before installing or copying code. Use testnet first, remove any private-key logging, store keys only in a secret manager or protected local store, restrict signing helpers to approved Orderly API origins, use the minimum API key scopes, and treat withdrawal or trading examples as real financial actions when pointed at mainnet.

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
SKILL.md:267
Finding
Generated Ed25519 Private Key Disclosed Through Standard Output<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 267–269; repeated at lines 695–698 **Vulnerability Type**: Private key exposure through application logs **Risk Level**: High ### Vulnerable Code ```typescript console.log('Orderly Key:', orderlyKey); console.log('Private Key (hex):', bytesToHex(privateKey)); // STORE PRIVATE KEY SECURELY - NEVER SHARE IT ``` The same insecure pattern appears again later: ```typescript console.log('Private Key (hex):', bytesToHex(privateKey)); console.log('Public Key (base58):', orderlyKey); // STORE PRIVATE KEY SECURELY - NEVER SHARE IT ``` ### Technical Analysis The example converts a newly generated Ed25519 private key into hexadecimal and prints the complete value to standard output. The warning to store the key securely does not mitigate the disclosure performed by the preceding executable statement. Standard output is frequently captured by agent runtimes, CI/CD systems, container logging drivers, hosted notebooks, terminal history collectors, or centralized logging platforms. In an agent environment, output may also be returned directly to the invoking user or service. The private key is the credential used to create valid Orderly API signatures. Unlike the public Orderly key and protocol signatures, disclosure of the private key is not required for the declared authentication functionality. ### Attack Path 1. A user copies and executes the documented key-generation example. 2. The code generates a valid Ed25519 private key and registers or prepares it for registration with an Orderly account. 3. The example converts the private key to hexadecimal and writes it to standard output. 4. An attacker obtains access to captured console output, agent execution results, CI logs, shared terminal records, or centralized logging infrastructure. 5. The attacker imports the exposed key and derives its associated public Orderly key. 6. If the key has been registered and remains valid, the attacker gene ...[truncated 670 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove every statement that prints, serializes, or otherwise exposes private key material: ```typescript console.log('Orderly Key:', orderlyKey); // Never print privateKey or bytesToHex(privateKey). ``` - Send generated keys directly to a protected secret-management workflow rather than passing them through standard output. - Use a managed secret store such as HashiCorp Vault, AWS Secrets Manager, or an equivalent platform with encryption, access control, and audit logging. - If local storage is unavoidable, create the file with owner-only permissions and encrypt the key at rest. - Configure logging systems to redact credential-like hexadecimal values and prevent debug logs from reaching untrusted users. - Add automated secret-scanning or linting rules that reject logging calls containing private keys, seeds, mnemonic phrases, or signing credentials. - Revoke and rotate any key that may already have been exposed through execution of these examples. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:759
Finding
Authentication Helper Sends Signed Credentials to Arbitrary Caller-Supplied Origins<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 759–790 **Vulnerability Type**: Unrestricted destination for authenticated network requests **Risk Level**: Medium ### Vulnerable Code ```typescript import { getPublicKeyAsync, signAsync } from '@noble/ed25519'; import { encodeBase58 } from 'ethers'; export async function signAndSendRequest( orderlyAccountId: string, privateKey: Uint8Array | string, input: URL | string, init?: RequestInit | undefined ): Promise<Response> { const timestamp = Date.now(); const encoder = new TextEncoder(); const url = new URL(input); let message = `${String(timestamp)}${init?.method ?? 'GET'}${url.pathname}${url.search}`; if (init?.body) { message += init.body; } const orderlySignature = await signAsync(encoder.encode(message), privateKey); return fetch(input, { headers: { 'Content-Type': init?.method !== 'GET' && init?.method !== 'DELETE' ? 'application/json' : 'application/x-www-form-urlencoded', 'orderly-timestamp': String(timestamp), 'orderly-account-id': orderlyAccountId, 'orderly-key': `ed25519:${encodeBase58(await getPublicKeyAsync(privateKey))}`, 'orderly-signature': Buffer.from(orderlySignature).toString('base64url'), ...(init?.headers ?? {}), }, ...(init ?? {}), }); } ``` ### Technical Analysis The helper accepts an unrestricted absolute URL through `input` and sends Orderly authentication headers to that destination without validating its scheme, hostname, or port. The private key itself is used locally and is not transmitted. Base64url encoding is applied only to the Ed25519 signature, as required by the documented protocol. However, the destination receives the account ID, public key, timestamp, and a valid signature for the selected HTTP method, path, query string, and body. Because the signature message does not bind the destination hostname, a signature collected by an attacker-co ...[truncated 1978 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Parse the destination before signing and enforce an exact allowlist of approved HTTPS origins. - Keep mainnet and testnet selection explicit rather than accepting arbitrary absolute URLs. - Reject non-HTTPS schemes, embedded credentials, unexpected ports, fragments, and unrecognized hostnames. - Prefer accepting validated relative API paths and combining them with an internally selected fixed base URL. - Perform validation before generating a signature so rejected destinations cannot use the function as a signing oracle. - Do not allow caller-provided headers to overwrite authentication headers after they have been generated. - Consider adding a narrowly scoped endpoint allowlist for high-impact operations. - Use the shortest practical key lifetime, assign only required scopes, and configure IP restrictions where available. Example hardening pattern: ```typescript const ALLOWED_ORIGINS = new Set([ 'https://api.orderly.org', 'https://testnet-api.orderly.org', ]); const url = new URL(input); if ( url.protocol !== 'https:' || !ALLOWED_ORIGINS.has(url.origin) || url.username || url.password || url.hash ) { throw new Error('Unapproved Orderly API destination'); } // Only sign and send after destination validation. ``` ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (10)

External Transmission

Medium
Category
Data Exfiltration
Content
```typescript
// Get supported chains for your broker
const response = await fetch(`https://api.orderly.org/v1/public/chain_info?broker_id=${BROKER_ID}`);

const { data } = await response.json();
// data.chains contains supported chain_ids
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
```typescript
// Get supported chains for your broker
const response = await fetch(`https://api.orderly.org/v1/public/chain_info?broker_id=${BROKER_ID}`);

const { data } = await response.json();
// data.chains contains supported chain_ids
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
```typescript
// Get supported chains for your broker
const response = await fetch(`https://api.orderly.org/v1/public/chain_info?broker_id=${BROKER_ID}`);

const { data } = await response.json();
// data.chains contains supported chain_ids
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
```typescript
// Get supported chains for your broker
const response = await fetch(`https://api.orderly.org/v1/public/chain_info?broker_id=${BROKER_ID}`);

const { data } = await response.json();
// data.chains contains supported chain_ids
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
Send the signed payload to create the Orderly Account ID:

```typescript
const registerResponse = await fetch('https://testnet-api.orderly.org/v1/register_account', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
Send the signed payload to create the Orderly Account ID:

```typescript
const registerResponse = await fetch('https://testnet-api.orderly.org/v1/register_account', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
Register the API key:

```typescript
const keyResponse = await fetch('https://testnet-api.orderly.org/v1/orderly_key', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
Register the API key:

```typescript
const keyResponse = await fetch('https://testnet-api.orderly.org/v1/orderly_key', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The withdrawal section provides ready-to-use instructions that initiate a funds-moving operation but does not clearly and explicitly warn the reader that executing the example can move real assets. In an authentication-focused skill, this omission increases the risk of accidental fund transfer, especially because the example includes concrete request construction and signing steps that a user may copy with production credentials.

External Transmission

Medium
Category
Data Exfiltration
Content
message: addKeyMessage,
});

const registerResponse = await fetch('https://api.orderly.org/v1/orderly_key', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Static analysis

No suspicious patterns detected.