Skip to content

Optional with a mutable default ([] / {}) is shared across all validate() calls #352

Description

@pramodavansaber

Summary

An Optional key with a mutable default (e.g. default=[] or default={}) returns the same object on every validate(). Mutating one validation's result corrupts the default for all subsequent validations of the same Schema — the classic shared-mutable-default footgun, causing state to leak between unrelated validate() calls.

Reproduction

from schema import Schema, Optional
s = Schema({Optional("items", default=[]): list})
a = s.validate({})
a["items"].append(1)
b = s.validate({})
print(b["items"])   # [1]   <- expected []

Expected

Each independent validate({}) returns a fresh default; b["items"] == [].

Actual

b["items"] == [1] — the default object is shared and leaks across calls.

Fix sketch

Copy the default when applying it (e.g. copy.deepcopy(default)), and/or support callable defaults.

Environment

schema 0.7.8 (master @ 310a123), Python 3.12.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions