Skip to content

fix(security): path traversal via unsanitized nid + integrity proof serialization mismatch#18

Draft
Copilot wants to merge 2 commits intomainfrom
copilot/fix-path-traversal-issue
Draft

fix(security): path traversal via unsanitized nid + integrity proof serialization mismatch#18
Copilot wants to merge 2 commits intomainfrom
copilot/fix-path-traversal-issue

Conversation

Copy link

Copilot AI commented Mar 1, 2026

Two high-severity security/correctness issues: nid was interpolated directly into URL path segments with only an emptiness check, enabling path traversal attacks; and TypeScript's signIntegrityProof used JSON.stringify(proof) (serializing the full object) while Python explicitly constructed a three-key dict, causing cross-SDK integrity hash divergence.

Path traversal fix (client.ts, client.py)

Added alphanumeric-only format validation (^[a-zA-Z0-9]+$) matching the IPFS CID format, plus encodeURIComponent/quote() as defense-in-depth on URL path segments:

// Before — any string passes
`${this.baseUrl}/assets/${nid}/`

// After — rejects ../../admin, bafybei?x=1, etc.
validateNidFormat(nid)  // throws ValidationError on non-alphanumeric
`${this.baseUrl}/assets/${encodeURIComponent(nid)}/`

Applies to both update() and get() in TypeScript and Python.

Integrity proof serialization fix (crypto.ts)

TypeScript now explicitly constructs the proof JSON with only the three canonical keys in insertion order, matching Python's behavior:

// Before — serializes entire proof object (extra runtime props leak in)
const proofJson = JSON.stringify(proof)

// After — deterministic, matches Python's explicit dict construction
const proofJson = JSON.stringify({
  proof_hash: proof.proof_hash,
  asset_mime_type: proof.asset_mime_type,
  created_at: proof.created_at,
})

Tests

  • NID format validation tests (path traversal, URL special chars, valid CID) added to both client.test.ts and test_client.py
  • Integrity proof serialization consistency tests added to test_crypto.py

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • api.numbersprotocol.io
    • Triggering command: /home/REDACTED/.local/bin/pytest pytest tests/test_client.py tests/test_crypto.py -v (dns block)
    • Triggering command: /opt/hostedtoolcache/node/24.13.1/x64/bin/node /opt/hostedtoolcache/node/24.13.1/x64/bin/node --conditions node --conditions development --experimental-import-meta-resolve --require /home/REDACTED/work/capture-sdk/capture-sdk/ts/node_modules/vitest/suppress-warnings.cjs /home/REDACTED/work/capture-sdk/capture-sdk/ts/node_modules/vitest/dist/workers/forks.js (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>[Security][High] Path traversal via unsanitized nid and integrity proof serialization mismatch</issue_title>
<issue_description>## Security Findings — High Severity

1. Path Traversal via Unsanitized nid in URL Construction

Files:

  • ts/src/client.ts lines 311, 339
  • python/numbersprotocol_capture/client.py lines 391, 418

Description:
The nid parameter is interpolated directly into URL paths without validation or encoding:

// TypeScript
`${this.baseUrl}/assets/${nid}/`
# Python
f"{self._base_url}/assets/{nid}/"

The only validation is a truthiness check (if (!nid) / if not nid), which accepts any non-empty string. A malicious nid value containing path traversal characters (e.g., ../../admin/users) or URL-special characters (?, #, @) can alter the target URL, potentially directing authenticated requests (with the Authorization header) to unintended API endpoints.

Impact:
An attacker who controls the nid parameter can craft values like ../../other-endpoint to make the SDK send authenticated requests to arbitrary paths on the API server, or with carefully crafted values containing @ or #, potentially redirect to different hosts entirely. This is a server-side request manipulation vector.

Suggested fix:
Validate that nid matches the expected format (IPFS CIDs typically match ^[a-zA-Z0-9]+$) and/or use encodeURIComponent() / urllib.parse.quote() when embedding it in URL paths. Note that verify.ts already uses encodeURIComponent(nid) for query parameters — the same treatment should be applied in client.ts.


2. Integrity Proof JSON Serialization Mismatch Between TypeScript and Python

Files:

  • ts/src/crypto.ts line 44
  • python/numbersprotocol_capture/crypto.py line 71

Description:
The TypeScript signIntegrityProof uses JSON.stringify(proof) which serializes the entire proof object as-is (including any extra properties that may be attached at runtime). The Python sign_integrity_proof explicitly constructs a new dict with exactly three keys in a specific order.

This asymmetry means that if the proof object ever carries additional fields, the TypeScript SDK will silently produce a different integrity hash. The SDKs must produce identical JSON for the same input to ensure cross-language signature interoperability.

Impact:
Cross-language signature verification failures. An asset registered with one SDK could produce mismatched integrity hashes when verified with the other SDK, undermining the core provenance guarantee.

Suggested fix:
In TypeScript, change JSON.stringify(proof) to explicitly construct the object with only the three expected keys in the same order as the Python version:

const proofJson = JSON.stringify({
  proof_hash: proof.proof_hash,
  asset_mime_type: proof.asset_mime_type,
  created_at: proof.created_at,
});

Add a cross-SDK test that verifies both SDKs produce the same integritySha for identical input.</issue_description>

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

…tion mismatch

Co-authored-by: numbers-official <181934381+numbers-official@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix path traversal vulnerability via unsanitized nid fix(security): path traversal via unsanitized nid + integrity proof serialization mismatch Mar 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Security][High] Path traversal via unsanitized nid and integrity proof serialization mismatch

2 participants