feat(ci): real sealed-box action secrets + fix double-encryption#378
Conversation
🍊 Orange Codens レビュー密封ボックス化 (sealed box) の実装と double-encryption 修正の方向性は正しいです。テストも round-trip / 決定性 / 不正入力拒否を網羅しており、PR 本文の claims を裏付ける内容になっています。 修正推奨: 参考: 全体としてマージに問題ない水準ですが、silent error 部分だけを修正すると本番でのトラブル時に気づきにくい事故を防げます。 🔒 セキュリティ: 本PRは sealed-box の動作不全 (placeholder キー / 暗号化レイヤーの二重化) を修正する実装改善であり、diff に暗号誤用・認可漏れ・入力量の脆弱性パターンは見られない。nacl/box による sealed box 形式・決定論的鍵導出 (blake2b + curve25519) は正しく実装されており、テストも round-trip / ガベージ入力の拒否を含んでいる。修正として安全と判断し、findings は出さない。 🟡 medium: 1 / 🔵 low: 2 その他の指摘 (3 件)
head: |
The GitHub-compatible secrets API was non-functional: it advertised a
placeholder all-zeros public key (which libsodium refuses to seal against) and
"decrypted" the client's sealed box with the symmetric key, so no real client
could ever store a secret. Enabling it also surfaced a latent double-encryption
bug that corrupted every stored secret.
- Derive a real curve25519 keypair deterministically from the server secret
(shared across replicas, stable across restarts) and advertise the true
public key. DecryptSealedBox now opens the client's anonymous ("sealed") box
with the private key — the libsodium crypto_box_seal format GitHub uses.
- Fix double-encryption: the upsert usecase encrypted the value AND the
repository encrypted it again, while reads decrypt only once — so the CI
worker's single decrypt yielded ciphertext, not the secret (steps then failed
with a corrupt env var). The repository is now the single at-rest encryption
boundary; the usecase passes the plaintext through.
Verified live end-to-end: fetch the real public key, seal a value with
libsodium (pynacl), PUT it (201), then a workflow reads it via `$API_TOKEN`
and `${{ secrets.API_TOKEN }}` — both resolve to the correct plaintext
(shell sees the right length) and are masked to *** in the logs.
Unit tests cover the sealed-box round trip, that the public key is real and
deterministic, and that the usecase hands plaintext to the repository.
4e216e7 to
be00a7a
Compare
Final PR completing the Actions executor: make GitHub-compatible action secrets actually work.
The problem
The secrets API was non-functional end-to-end:
DecryptSealedBox"decrypted" the client's sealed box with the symmetric key, not the sealed-box private key.Enabling it also surfaced a latent double-encryption bug that corrupted every stored secret.
Fixes
DecryptSealedBoxnow opens the client's anonymous ("sealed") box — the libsodiumcrypto_box_sealformat GitHub uses.Verified live end-to-end
Unit tests: sealed-box round trip, public key is real + deterministic, usecase hands plaintext to the repo.
This closes the last known gap in the Actions executor.