Skip to content

@JsonFilter with serializeAllExcept() does not filter @JsonAnyGetter entries #6136

Description

@aysha-afrah26

Describe the bug

When a POJO has both @JsonFilter and a @JsonAnyGetter, exclude-style filters (SimpleBeanPropertyFilter.serializeAllExcept()) are not applied to the entries the any-getter produces: every entry is written out, including ones whose key the filter explicitly excludes. Since exclude filters are typically used to suppress sensitive properties, entries slip out that the filter was configured to hide.

The cause is that SimpleBeanPropertyFilter.serializeAsProperty() calls include(writer) on the AnyGetterWriter itself, so the name being checked is the any-getter accessor's implied name, not the names of the entries it emits. That name is not in the exclude set, so the writer goes straight to getAndSerialize(), which writes all entries unfiltered. Only include-style filters (filterOutAllExcept()) ever reach the per-entry getAndFilter() path, since that call sits in the else branch behind canOmitProperties().

There is a second variant: a JsonNode/ObjectNode-valued any-getter (supported since [databind#3604]) leaks under both filter styles, because AnyGetterWriter.getAndFilter() short-circuits JsonNode values to plain unfiltered entry serialization, so no filter is consulted at all.

2.18 and earlier are not affected: there the any-getter writer was kept out of the property array and BeanSerializerBase.serializeFieldsFiltered() called getAndFilter() unconditionally. Folding the any-getter into the property array as a BeanPropertyWriter put it behind the writer-level include() check.

Version Information

Reproduced on 3.3.0-SNAPSHOT (3.x head); same code is on 3.1/3.2. 2.18 is not affected.

Reproduction

@JsonFilter("anyFilter")
static class AnyBeanWithSecret {
    public String name = "bob";

    private Map<String, String> properties = new LinkedHashMap<>();
    {
        properties.put("a", "1");
        properties.put("secret", "s3cr3t");
    }

    @JsonAnyGetter
    public Map<String, String> anyProperties() {
        return properties;
    }
}

FilterProvider prov = new SimpleFilterProvider().addFilter("anyFilter",
        SimpleBeanPropertyFilter.serializeAllExcept("secret"));
String json = MAPPER.writer(prov).writeValueAsString(new AnyBeanWithSecret());
// expected: {"name":"bob","a":"1"}
// actual:   {"name":"bob","a":"1","secret":"s3cr3t"}

The ObjectNode variant leaks the same way, and also with filterOutAllExcept("name", "a"):

@JsonFilter("anyFilter")
static class ObjectNodeAnyBeanWithSecret {
    public String name = "bob";

    @JsonAnyGetter
    public ObjectNode anyProperties() {
        return JsonNodeFactory.instance.objectNode()
                .put("a", "1")
                .put("secret", "s3cr3t");
    }
}

Expected behavior

The filter should decide inclusion per emitted entry name, the way filterOutAllExcept() already does for Map-valued any-getters, so that serializeAllExcept("secret") suppresses the secret entry regardless of filter style or any-getter value type.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions