fix: vault-import.sh: pipe-separator in ops_data/paths_to_write silently truncates secret values containing | (#898) #913
No reviewers
Labels
No labels
action
backlog
blocked
bug-report
cannot-reproduce
in-progress
in-triage
needs-triage
prediction/actioned
prediction/dismissed
prediction/unreviewed
priority
rejected
reproduced
tech-debt
underspecified
vision
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: disinto-admin/disinto#913
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/issue-898"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Fixes #898
Changes
Replace the `|`-delimited string accumulators with bash associative and indexed arrays so any byte may appear in a secret value. Two sites used `|` as a delimiter over data that includes user secrets: 1. ops_data["path:key"]="value|status" — extraction via `${data%%|*}` truncated values at the first `|` (silently corrupting writes). 2. paths_to_write["path"]="k1=v1|k2=v2|..." — split back via `IFS='|' read -ra` at write time, so a value containing `|` was shattered across kv pairs (silently misrouting writes). Fix: - Split ops_data into two assoc arrays (`ops_value`, `ops_status`) keyed on "vault_path:vault_key" — value and status are stored independently with no in-band delimiter. (`:` is safe because both vault_path and vault_key are identifier-safe.) - Track distinct paths in `path_seen` and, for each path, collect its kv pairs into a fresh indexed `pairs_array` by filtering ops_value. `_kv_put_secret` already splits each entry on the first `=` only, so `=` and `|` inside values are both preserved. Added a bats regression that imports values like `abc|xyz`, `p1|p2|p3`, and `admin|with|pipes` and asserts they round-trip through Vault unmodified. Values are single-quoted in the .env so they survive `source` — the accumulator is what this test exercises. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>AI Review
Summary
Root cause: the old accumulator packed secret values into
value|statusstrings and joined per-path pairs with|. Any secret value containing|was silently truncated.Fix shape (predicted from issue): split
ops_dataintoops_value/ops_status, drive the second pass from a separatepath_seenindex, buildpairs_arrayby iteratingops_valuekeys and filtering by path.Correctness verification
ops_value/ops_status): eliminates the delimiter collision entirely; values are stored verbatim in bash associative arrays. ✓vault_path:vault_key): all vault paths aredisinto/{segment}/{name}(slashes, no colons); all vault keys are identifiers (token,pass,admin_token,value).${ck%:*}/${ck#*:}round-trip correctly. ✓_kv_put_secretfirst-=-split (${kv%%=*}/${kv#*=}): values containing=are also preserved. ✓path_seen-driven second pass: all paths written, all keys included per path — KV v2 full-document semantics preserved. ✓token+passon same vault path) and a single-key path (admin_token), verifying round-trip equality viajq -e. ✓Pre-existing (not introduced by this PR)
createdandunchangedcounters are never incremented in the second pass; the summary log always prints 0 for both. Not a regression of this PR.Verdict
APPROVE — Correctly replaces delimited-string accumulator with separate associative arrays; all value characters now round-trip safely through _kv_put_secret.
Reviewed at
27baf49| AGENTS.mdAI Review: APPROVE — Correctly replaces delimited-string accumulator with separate associative arrays; all value characters now round-trip safely through _kv_put_secret.