fix(secrets): EncryptLargeString fails on UTF-8 files (rune vs byte chunking)#320
Closed
simple-container-forge[bot] wants to merge 7 commits into
Conversation
…d-4c6d-86dd-da2c832417a6 init idempotency: 99171cbe-7c27-4976-a999-931b834b5d62:848b1368-5c8d-4c6d-86dd-da2c832417a6:init
idempotency: pm:run Co-authored-by: Max Warner (pm) <forge-agent+pm@simple-forge.com>
idempotency: architect:run Co-authored-by: Dan Johnson (architect) <forge-agent+architect@simple-forge.com>
…RSA-OAEP overflow on UTF-8 files lo.ChunkString splits by rune count but rsa.EncryptOAEP enforces a byte limit. A 128-rune chunk of 3-byte characters (e.g. box-drawing ─) is 384 bytes — well over the OAEP-SHA256 maximum of 190 bytes for a 2048-bit key — causing "crypto/rsa: message too long for RSA key size" on any secret file with dense multi-byte UTF-8 content. Fix: replace lo.ChunkString with a byte-slice loop sized to the exact OAEP limit (rsaKey.Size() - 2*sha256.Size - 2 = 190 for 2048-bit). Add a guard that returns a clear error for pathologically small keys. DecryptLargeString is unchanged; it joins raw bytes so split-mid-rune chunks reconstruct correctly. Add five regression tests covering box-drawing, emoji, mixed Cyrillic/ arrows, chunk-boundary-mid-rune, and the small-key guard path. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
simple-container-forge
Bot
requested review from
Cre-eD,
Laboratory,
smecsia and
universe-ops
as code owners
June 12, 2026 17:51
idempotency: developer:run Co-authored-by: David Black (developer) <forge-agent+developer@simple-forge.com>
Semgrep Scan ResultsRepository:
Scanned at 2026-06-12 17:55 UTC |
idempotency: qa:run Co-authored-by: Maria Currie (qa) <forge-agent+qa@simple-forge.com>
idempotency: devops:run Co-authored-by: William Smith (devops) <forge-agent+devops@simple-forge.com>
Security Scan ResultsRepository:
Scanned at 2026-06-12 17:55 UTC |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
EncryptLargeStringwas chunking by rune count (lo.ChunkString) butrsa.EncryptOAEPenforces a byte limit. A 128-rune window of 3-byte UTF-8 characters (e.g. box-drawing─) yields 384 bytes, exceeding the OAEP-SHA256 maximum of 190 bytes for a 2048-bit key, producingcrypto/rsa: message too long for RSA key size.lo.ChunkStringloop with a byte-slice loop sized to the exact OAEP limit:rsaKey.Size() - 2*sha256.Size - 2(190 bytes for 2048-bit keys).DecryptLargeStringis unchanged — it joins raw bytes so chunks split mid-rune reconstruct correctly. Backward-compatible with existing encrypted secrets.Files changed
pkg/api/secrets/ciphers/encryption.go—EncryptLargeStringRSA branch onlypkg/api/secrets/ciphers/encryption_extra_test.go— 5 new UTF-8 regression testsTest plan
go test ./pkg/api/secrets/ciphers/... -v -count=1— all 32 tests pass including 5 new UTF-8 testsTestEncryptLargeString_UTF8_BoxDrawing— 256×─(768 bytes) round-trips correctlyTestEncryptLargeString_UTF8_Emoji— 100×🔑(400 bytes) round-trips correctlyTestEncryptLargeString_UTF8_Mixed— real-world section header with box-drawing/arrows/CyrillicTestEncryptLargeString_UTF8_ChunkBoundaryMidRune— 64×─(192 bytes) splits mid-rune, verifies 2 chunks, reconstructs correctlyTestEncryptLargeString_SmallKey_TooSmall— synthetic 512-bit modulus triggers guard with "RSA key too small"Workflow run: https://app.simple-forge.com/agent-workflow-runs/848b1368-5c8d-4c6d-86dd-da2c832417a6
🤖 Generated with Claude Code