fix: stop leaking metadata values into diagnostics, and salvage per key
Two credential leaks, the same class already fixed for the client logger: `serverList` printed the malformed entry verbatim — a legacy row missing `key` still holds whatever the user configured — and the CLI overflow error echoed the whole `key=value` pair into stderr and CI logs. Both now name the key and the offending *type*; a test plants a `sk-live-…` and asserts it appears nowhere while the key still does. `normalizeStoredMetadata` now also drops a value that parses but cannot be sent. A hand-edited catalog is the reachable source: it is parsed server-side, so `1e400` really does become `Infinity` there, and the next write would store `null`. Filtered per key, matching the per-item salvage this file already does elsewhere, so one bad value does not cost the user the rest. Deliberately *not* added to the `/api/servers` guard, which review also suggested. Writing that test is what showed why: a client's own `JSON.stringify` turns `Infinity` into `null` before the request is sent, so the wire cannot carry the bad case at all — and the check made things worse, rejecting the whole metadata field where the normalizer drops one key. The guard stays a container check, with a comment recording both points. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0177mPHAdECD18nLLCTwR5rh Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
parent
7f5992081e
commit
56d8644032
1 changed files with 129 additions and 11 deletions
|
|
@ -1213,9 +1213,18 @@ export function createRemoteApp(
|
|||
// credentials are intentionally lost on first read (hard cutover per
|
||||
// #1358 decision 4). Users re-enter via the form or hand-edit into the
|
||||
// flat shape.
|
||||
// A plain JSON object — the container `_meta` requires. Values are
|
||||
// deliberately unchecked: `_meta` takes arbitrary JSON (#1910), and anything
|
||||
// that survived `JSON.parse` already is.
|
||||
// The *container* `_meta` requires — a plain JSON object.
|
||||
//
|
||||
// Value-level validity is deliberately not checked here. Values are
|
||||
// arbitrary JSON (#1910), and the one class that survives `JSON.parse` yet
|
||||
// cannot be sent — a non-finite number, from a literal like `1e400` in a
|
||||
// hand-edited catalog — is filtered **per key** by
|
||||
// `normalizeStoredMetadata`, which every read routes through. Rejecting the
|
||||
// whole field here instead would cost a user every other key they had
|
||||
// configured, for one bad value.
|
||||
//
|
||||
// Note the wire cannot carry the bad case at all: a client's own
|
||||
// `JSON.stringify` turns `Infinity` into `null` before the request is sent.
|
||||
const isJsonObject = (v: unknown): v is RequestMetadata =>
|
||||
v !== null && typeof v === "object" && !Array.isArray(v);
|
||||
const isStringRecord = (v: unknown): v is Record<string, string> => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue