Skip to content

[Security][Medium] Private key memory exposure, source maps in npm, exception swallowing, and metadata injection #23

@numbers-official

Description

@numbers-official

Summary

Multiple medium-severity security findings across both SDKs related to secret handling, build artifacts, and input validation.

1. Private Key Retained in Memory Without Zeroing (Both SDKs)

Files:

  • python/numbersprotocol_capture/crypto.py:48-63
  • ts/src/crypto.ts:41

Both SDKs receive the Ethereum private key as an immutable string. The key persists in memory until garbage collected, appearing in heap dumps, core dumps, or memory inspection tools. Neither SDK attempts to minimize the lifetime of key material.

Suggested fix: Accept private key as Uint8Array/bytearray that can be zeroed after use. Alternatively, support a "bring your own signer" callback pattern: sign?: { signer: (message: string) => Promise<string>; address: string }.

2. API Token Exposed via Python __repr__ / Debugger Inspection

File: python/numbersprotocol_capture/client.py:131-158

The Capture class stores the token as self._token without a custom __repr__(). The token appears in vars(capture), capture.__dict__, and framework traceback reporters (e.g., Sentry, cgitb).

Suggested fix: Implement __repr__() that masks the token: Capture(token='***...abc', base_url='...').

3. Source Maps Included in Production npm Package

Files: ts/tsup.config.ts:8, ts/tsconfig.json:14

Both sourcemap: true settings cause .map files to be published to npm, exposing full original TypeScript source to anyone who installs the package. While the SDK is open source, this increases package size and aids vulnerability discovery.

Suggested fix: Set sourcemap: false or 'hidden' in tsup.config.ts. Exclude *.map from package.json files array.

4. customMetadata Accepts Arbitrary Unsanitized JSON (TypeScript)

Files: ts/src/client.ts:305-306, ts/src/types.ts:58

The update() method accepts customMetadata: Record<string, unknown> and serializes it directly via JSON.stringify. This allows deeply nested objects (JSON bomb DoS), excessively large strings, and potential stored XSS payloads if the server renders metadata in a web context.

Suggested fix: Add max serialized size check (e.g., 10KB). Restrict value types to Record<string, string | number | boolean>.

5. Overly Broad Exception Swallowing (Python)

Files: python/numbersprotocol_capture/client.py:213-217, 700-707, 759-766, python/numbersprotocol_capture/crypto.py:99-108

Multiple except Exception: pass blocks silently swallow errors during error response JSON parsing and crypto operations. This hides security-relevant errors like malformed responses, truncated data, or unexpected server behavior.

Suggested fix: Log caught exceptions at debug level instead of silently swallowing them. At minimum, preserve the original error context.

6. Client-Side fileUrl Scheme Validation Missing (TypeScript)

File: ts/src/client.ts:499-500

The searchAsset method forwards fileUrl to the backend without validating the URL scheme. While server-side SSRF is tracked in #15, adding client-side defense-in-depth (rejecting file://, metadata endpoints) would prevent misuse.

Suggested fix: Validate parsed.protocol is http: or https: before sending.


Generated by Health Monitor with Omni

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions