Skip to content

Commit ab42b6e

Browse files
committed
fix: fix invalid redacting for sibling branches with coercions
1 parent 8eb3183 commit ab42b6e

3 files changed

Lines changed: 43 additions & 2 deletions

File tree

src/structs/types.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ function withSensitiveEntries<Type, Schema extends ObjectSchema>(
4545
return new Struct({
4646
...base,
4747
*entries(value: unknown, context: Context) {
48+
// `run` initialises `branch` before coercion runs, so `value` here may
49+
// be a freshly-created coerced copy (e.g. `object()`'s `{ ...value }`)
50+
// while `context.branch[last]` still holds the original reference that
51+
// ends up in failure branches. Using the branch reference ensures the
52+
// `===` check inside `withRedactedBranch` matches when coercion is active.
53+
// Falls back to `value` if branch is somehow empty (entries called outside
54+
// of `run`).
55+
const parentInBranch = context.branch[context.branch.length - 1] ?? value;
4856
for (const entry of base.entries(value, context)) {
4957
const [fieldKey, fieldValue, fieldStruct] = entry;
5058
// The entries tuple types the third element as `Struct<any> |
@@ -54,7 +62,11 @@ function withSensitiveEntries<Type, Schema extends ObjectSchema>(
5462
yield [
5563
fieldKey,
5664
fieldValue,
57-
withRedactedBranch(fieldStruct as AnyStruct, value, sensitiveKeys),
65+
withRedactedBranch(
66+
fieldStruct as AnyStruct,
67+
parentInBranch,
68+
sensitiveKeys,
69+
),
5870
];
5971
}
6072
},
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { literal, object, sensitive, string } from '../../../src';
2+
3+
// Validates that sibling-field branch redaction works when coercion is active
4+
// (create / mask / validate with coerce). `run` builds `branch` before calling
5+
// the struct coercer, so the parent reference in `branch` can differ from the
6+
// coerced `value` received by `entries`. The fix reads from `context.branch`.
7+
export const Struct = object({
8+
secret: sensitive(string()),
9+
tag: literal('ok'),
10+
});
11+
12+
export const create = true;
13+
export const data = { secret: 'raw-secret', tag: 'bad' };
14+
15+
export const failures = [
16+
{
17+
value: 'bad',
18+
type: 'literal',
19+
refinement: undefined,
20+
path: ['tag'],
21+
branch: [{ secret: '***', tag: 'bad' }, 'bad'],
22+
},
23+
];

test/validation/sensitive/invalid-sibling-exactoptional.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
import { exactOptional, literal, object, sensitive, string } from '../../../src';
1+
import {
2+
exactOptional,
3+
literal,
4+
object,
5+
sensitive,
6+
string,
7+
} from '../../../src';
28

39
export const Struct = object({
410
secret: exactOptional(sensitive(string())),

0 commit comments

Comments
 (0)