Problem
Found while writing a customer-runnable test script for #752 against mw-prod-us: a plain (in-memory) CREATE SECRET issued in session A is still visible in session B whenever B reuses the same hot-idle worker — empirically reproduced on a prod duckling. Since hot-idle reuse spans users of the same org, user A's in-memory secret (with live credential material) is readable by user B via duckdb_secrets() and usable by scope match.
This is pre-existing behavior, not a #752 regression: DuckDB secrets are instance-global, and the #752 session-start hygiene wipe deliberately clears only persistent-storage secrets, because the system catalog secrets (ducklake_s3, iceberg_sigv4, iceberg_oauth) are in-memory and must survive. Before #752 the same lingering applied to persistent secrets too (worse); the in-memory half of the gap remains.
Reproduce
psql ... -c "CREATE SECRET t1 (TYPE s3, KEY_ID 'x', SECRET 'y')"
psql ... -c "SELECT name FROM duckdb_secrets() WHERE name='t1'" # new session, reused worker → t1
Proposed fix
Extend wipeUserPersistentSecrets (duckdbservice/user_secrets.go) into a full user-secret wipe at session create: drop all secrets — any storage — whose name is not reserved (usersecrets.IsReservedName covers the system set + __default_*/duckgres_* prefixes). The reserved-name guard already exists and is already load-bearing for CREATE interception; reusing it here keeps one source of truth. Same one-session-per-worker precondition assertion applies.
Caveat to check: unnamed user secrets get DuckDB default names (__default_s3), which collide with the reserved prefix — wiping them is correct (they're user-created), so the wipe predicate should be "not a system secret name" rather than IsReservedName verbatim; may need to split the reserved set (system names vs reserved-for-create prefixes).
The e2e persistent_user_secret_isolation assertion in tests/e2e-mw-dev/harness.sh should gain a temp-secret leg (user A CREATE SECRET; user B must not see it).
🤖 Generated with Claude Code
Problem
Found while writing a customer-runnable test script for #752 against mw-prod-us: a plain (in-memory)
CREATE SECRETissued in session A is still visible in session B whenever B reuses the same hot-idle worker — empirically reproduced on a prod duckling. Since hot-idle reuse spans users of the same org, user A's in-memory secret (with live credential material) is readable by user B viaduckdb_secrets()and usable by scope match.This is pre-existing behavior, not a #752 regression: DuckDB secrets are instance-global, and the #752 session-start hygiene wipe deliberately clears only persistent-storage secrets, because the system catalog secrets (
ducklake_s3,iceberg_sigv4,iceberg_oauth) are in-memory and must survive. Before #752 the same lingering applied to persistent secrets too (worse); the in-memory half of the gap remains.Reproduce
Proposed fix
Extend
wipeUserPersistentSecrets(duckdbservice/user_secrets.go) into a full user-secret wipe at session create: drop all secrets — any storage — whose name is not reserved (usersecrets.IsReservedNamecovers the system set +__default_*/duckgres_*prefixes). The reserved-name guard already exists and is already load-bearing for CREATE interception; reusing it here keeps one source of truth. Same one-session-per-worker precondition assertion applies.Caveat to check: unnamed user secrets get DuckDB default names (
__default_s3), which collide with the reserved prefix — wiping them is correct (they're user-created), so the wipe predicate should be "not a system secret name" rather thanIsReservedNameverbatim; may need to split the reserved set (system names vs reserved-for-create prefixes).The e2e
persistent_user_secret_isolationassertion intests/e2e-mw-dev/harness.shshould gain a temp-secret leg (user ACREATE SECRET; user B must not see it).🤖 Generated with Claude Code