Skip to content

fix(cli): read files saved by Windows PowerShell's redirect - #687

Merged
DealAppSeo merged 1 commit into
mainfrom
fix/cc-2026-11-08-powershell-redirect
Nov 8, 2026
Merged

DealAppSeo merged 1 commit into
mainfrom
fix/cc-2026-11-08-powershell-redirect

Conversation

@DealAppSeo

Copy link
Copy Markdown
Owner

trustshell sign-receipt body.json > r.json, the command trustshell demo tells a new user to run, fails on Windows PowerShell 5.1. Its > writes UTF-16, and verify-receipt then says the file is "not valid JSON".

Found by running the same commands in each shell from a clean install of the tarball. Every file a person hands the CLI now decodes the same way: receipts, envelopes, saved check --json evidence and claims files.

Evidence: tests/decode-text.test.ts. Release E2E on a tarball with this change, Windows, PowerShell 5.1 and Git Bash: 21 of 21 steps passed, including shells.powershell-5.1.redirect, which failed before it.

🤖 Generated with Claude Code

`trustshell sign-receipt body.json > r.json`, the command demo prints,
wrote UTF-16 in Windows PowerShell 5.1, and verify-receipt then called the
file "not valid JSON". Found by running the same commands in each shell
from a clean install. Every file a person hands the CLI now decodes the
same way, including claims files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Nov 8, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
trustshell-landing Ready Ready Preview Nov 8, 2026 11:18pm UTC

Request Review

@strix-security

strix-security Bot commented Nov 8, 2026 •

Copy link
Copy Markdown

Strix Security Review

✅ No open security findings.

PR summary: Adds a `decodeText` helper that strips a byte-order mark and decodes UTF-16LE/BE, and uses it for every file the CLI reads from a person (receipts, envelopes, `report --evidence`, `--claims-file`), so files written by Windows PowerShell 5.1's `>` are read correctly.

Review summary

The PR adds a small decodeText helper that strips a UTF-8 byte-order mark and decodes UTF-16LE/BE, and routes the CLI's receipt, envelope, --evidence and claims-file reads through it. I traced every changed read to its sink: receipt and envelope integrity are computed over kernelCanonicalJson of the parsed object, so file encoding cannot influence a signature or hash decision (confirmed end-to-end, including a tampered UTF-16 receipt that still fails); the claims plain-ASCII gate runs on the decoded text, so UTF-16 cannot smuggle non-ASCII past it; and the claims byte cap is still measured on raw bytes. The committed dist/ matches the src/ change. No security vulnerabilities were found in the changed code.

Ruled out (3)
  • Does decoding UTF-16 before use let a file bypass a security-relevant validation (claims ASCII gate, size cap, receipt integrity)?
    The claims ASCII gate runs on the decoded string, the claims byte cap is measured on raw bytes, and receipt/envelope integrity is computed over canonical JSON of the parsed object, so encoding cannot change any trust decision.
  • Can a UTF-16 file exceed the 256 KiB limit because the guard now counts decoded characters?
    The discrepancy is real but pre-existing for non-ASCII UTF-8, the guard is post-read so it never bounded memory, and the decoded text only reaches JSON.parse and hash/signature verification.
  • Can an odd-length UTF-16BE file crash the CLI via swap16()?
    The throw is caught at every call site and mapped to a fail-closed usage exit code before any verification runs, and the input is a local file the operator names.

Review 1 on this PR · 064dffe · requested Nov 8 23:18 UTC when the PR was opened


Reviewed by Strix
Re-run review · Configure security review settings

@strix-security strix-security Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR adds a small decodeText helper that strips a UTF-8 byte-order mark and decodes UTF-16LE/BE, and routes the CLI's receipt, envelope, --evidence and claims-file reads through it. I traced every changed read to its sink: receipt and envelope integrity are computed over kernelCanonicalJson of the parsed object, so file encoding cannot influence a signature or hash decision (confirmed end-to-end, including a tampered UTF-16 receipt that still fails); the claims plain-ASCII gate runs on the decoded text, so UTF-16 cannot smuggle non-ASCII past it; and the claims byte cap is still measured on raw bytes. The committed dist/ matches the src/ change. No security vulnerabilities were found in the changed code.


Reviewed by Strix
Configure security review settings

@DealAppSeo
DealAppSeo merged commit ec2469a into main Nov 8, 2026
13 checks passed

This branch was successfully deployed

1 active deployment
Preview — 064dffe5 Deployed Nov 8, 2026 by vercel[bot]
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.

1 participant