fix(decrypt): ensure decrypted file ends with newline to prevent last multiline value truncation#730
Conversation
… multiline value truncation Signed-off-by: mail2sudheerobbu-oss <mail2sudheerobbu@gmail.com>
|
I would like to have this covered by an test. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #730 +/- ##
==========================================
- Coverage 87.00% 86.83% -0.18%
==========================================
Files 22 22
Lines 862 866 +4
==========================================
+ Hits 750 752 +2
- Misses 112 114 +2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
…ne branch Signed-off-by: mail2sudheerobbu-oss <mail2sudheerobbu@gmail.com>
|
Added a bats test in commit 830b9ad ( |
…case indentation Signed-off-by: mail2sudheerobbu-oss <mail2sudheerobbu@gmail.com>
|
Hi @jkroepke 👋 — just a gentle ping on this PR. All checks are passing, there are no conflicts with |
|
I tries this PR and I'm the same issue as I had in #715. All tests are green, which looks great. However, if I remove your code from decrypt.sh, all tests are still green, including the new one. Basicly, I'm looking for a test case which fails without adding new code and is green with new code fragment. |
Adds a new BATS test "decrypt: inline decrypt appends trailing newline when backend omits it" that uses helm-secrets' custom backend API to inject a mock backend. The mock's _custom_backend_decrypt_file writes content without a trailing newline, precisely simulating the sops --output stripping bug. Without the printf '\n' fix in decrypt_helper, this test fails (red). With the fix it passes (green). This addresses jkroepke's request for a proper red/green test. Signed-off-by: mail2sudheerobbu-oss <mail2sudheerobbu@gmail.com>
|
Hi @jkroepke — you're right, the previous test didn't fail without the fix. I've addressed this in commit 00cddab with a new test:
The key insight: the existing fixture ( _custom_backend_decrypt_file() {
# Intentionally omit the trailing newline — simulating the sops --output bug
printf 'global_secret: value_without_trailing_newline' > "${3}"
}This mock is sourced by run sh -c "tail -c1 '${mock_file}' | wc -l | tr -d ' '"
assert_output "1"Without the Happy to adjust anything — thanks for the thorough review! |
|
Hey @jkroepke — just a friendly ping! The branch is up to date and the red/green test has been updated to use a mock backend that deterministically reproduces the missing-newline bug. Would love your review when you have a moment. Thanks! 🙏 |
Signed-off-by: mail2sudheerobbu-oss <mail2sudheerobbu@gmail.com>
|
Hi @jkroepke — just a gentle follow-up. The red/green test you flagged on Apr 1 was addressed in commit 00cddab: the new test uses a mock backend that deterministically omits the trailing newline, so it fails without the fix and passes with it. All 21 CI checks are green. Could you take another look when you have a moment? Happy to adjust anything if needed! |
|
Hi @jkroepke — just a gentle weekly ping! CI is green and there are no conflicts. Happy to make any adjustments if you have further feedback. 🙏 |
|
@jkroepke — heads up: the latest CI run has one failure in |
|
@jkroepke — following up on this PR. The red/green mock-backend test from commit
Happy to address any further feedback. Thanks! 🙏 |
|
Hi @jkroepke 👋 The one failing CI check — Could you please re-run that job when you get a chance? Happy to address any review feedback in the meantime. Thank you! |
|
@jkroepke — following up on the one remaining failing check: Also, could you clarify what condition the |
|
@jkroepke — just a gentle ping on this one. The red/green mock-backend tests you requested were added back in March. Could you take a look when you get a chance? Also wanted to ask: is the |
|
@jkroepke — gentle ping! All CI checks are passing and the fix is ready. Could you take a look and review when you get a chance? Thanks for your time! |
|
Hi @jkroepke — following up on your April 1 feedback ("if I remove your code from I've since added a self-contained mock-backend bats test in @test "decrypt: inline decrypt appends trailing newline when backend omits it" {
# Uses a custom backend that intentionally writes WITHOUT a trailing newline.
# Without the printf '\n' fix in decrypt_helper, tail -c1 | wc -l returns 0
# and assert_output "1" FAILS.
...
HELM_SECRETS_BACKEND="${mock_backend}" run "${HELM_BIN}" secrets decrypt -i "${mock_file}"
assert_success
run sh -c "tail -c1 '${mock_file}' | wc -l | tr -d ' '"
assert_output "1" # 0 without the fix
}The mock backend's The existing sops-based tests passed before because sops itself adds a newline in the test fixtures — the bug only surfaces when the backend omits it (which is what happens with sops Please let me know if there's anything else you'd like adjusted! |
On WSL1, sed -i fails when the target file lives on a DrvFs mount (/mnt/c/...) because WSL1's VFS translates POSIX rename(2) into a Windows MoveFile call which does not work on the Windows filesystem mount for certain NTFS metadata files. The symptom is: sed: couldn't edit .../plugin.yaml: not a regular file Override _sed_i inside the WSL block to use a temp-file + cp approach: create the edited copy in TMPDIR (Linux-side tmpfs), then cp it over the original. cp uses write(2) rather than rename(2) and therefore succeeds on DrvFs paths. Fixes the CI failure in unit-tests (windows-2025, wsl, 4) where test 133 (helm template w/ chart + secrets://...yaml + --set-file secrets://file.txt) was failing with 'Error: plugin scripts/wrapper/run.cmd downloader exited with error' because the plugin.yaml patch could not be applied.
shfmt requires no space between the redirection operator and its target (i.e. >"$_si_tmp" not > "$_si_tmp"). No behaviour change.
common.sh runs under 'set -euf'. The WSL GitHub Actions runner does not
export TMPDIR, so calling _mktemp() — which expands ${TMPDIR} bare —
triggers 'TMPDIR: unbound variable' and aborts plugin installation.
Use mktemp directly with the ${TMPDIR:-/tmp} default-value form, which
is explicitly safe under set -u and falls back to /tmp (always available
on the WSL Linux side) when TMPDIR is not set.
|
@jkroepke CI is now fully green on commit 905b7a0 across all 17 jobs, including The WSL failure was a Would appreciate a review when you have a moment — the main fix (trailing-newline in decrypted output) is unchanged, this was just a CI-only blocker on the WSL test runner. Thanks! |
|
Hi @jkroepke — just a gentle weekly ping! CI is green, WSL1 |
|
@jkroepke — the only remaining CI failure is |
Fixes #714
Root cause
When
HELM_SECRETS_WRAPPER_ENABLED=truethe wrapper path callsdecrypt_helperwithout the"stdout"argument, sobackend_decrypt_fileinvokes sops with--output <file>. In certain sops versions, when the last YAML value is a block scalar (multi-line string), the trailing newline is omitted from the--outputfile path but is correctly preserved when writing to stdout.The
secrets://downloader path is unaffected because it callsdecrypt_helper ... "stdout", which pipes sops output directly to stdout (preserving the newline).The missing newline causes YAML parsers to see the last multiline value as truncated — stripping the final newline that was present in the original secret — producing a different value than the
secrets://path returns.Fix
After
backend_decrypt_filewrites the decrypted file, check whether it ends with a newline using the POSIX-portabletail -c1 | wc -lidiom (returns 0 when the last byte is not\n), and append\nif needed. The guard is:printf '\n'instead ofechofor POSIX portabilityTesting
Reproduce with a YAML secret file whose last value is a block scalar:
Encrypt it with sops, then decrypt via the wrapper path (
helm secrets template ...) and verify the last line ofmy-certis not truncated.