zalando/logbook

JsonPath body filter does not obfuscate due to unexisting field in request/response

paswd opened this issue · 4 comments

paswd commented

Description

In my project I use JsonPathBodyFilters to obfuscate json properties in several responses. These properties are unique for each response. So, at least one BodyFilter throws ClassCastException as in #1369.

P.S. I catch this issue in 2.15.0, but, as I see in issues and source code, it has't been fixed yet.

Actual Behavior

Result of this bug is totally not obfuscated response.

Expected Behavior

I think that correct behavior is to ignore unexisting field and obfuscate another correct fields. Or at least make it optional.

Possible Fix

In class JsonPathBodyFilters.CompositeOperation we have method filter.

It's current implementation:

@Override
public DocumentContext filter(final DocumentContext context) {
    DocumentContext result = context;

    for (final Operation operation : operations) {
        result = operation.filter(result);
    }

    return result;
}

Possible solution:

@Override
public DocumentContext filter(final DocumentContext context) {
    DocumentContext result = context;

    for (final Operation operation : operations) {
        try {
            result = operation.filter(result);
        } catch (Exception ex) {
            // maybe logging or smth else
        }
    }

    return result;
}

So, single operation exception does not break another filters anymore.

Result of this bug is totally not obfuscated response.

If that is the current behavior, then there is already a place in the code somewhere that catches and ignores exceptions in body filters. Have you found it?

paswd commented

Result of this bug is totally not obfuscated response.

If that is the current behavior, then there is already a place in the code somewhere that catches and ignores exceptions in body filters. Have you found it?

Yes, I found it. This place is in JsonPathBodyFilter.filter:

@Override
public String filter(
        @Nullable final String contentType, final String body) {

    if (body.isEmpty() || !JSON.test(contentType)) {
        return body;
    }

    try {
        final DocumentContext original = CONTEXT.parse(body);
        // BodyFilter exception throws here
        return operation.filter(original).jsonString();
    } catch (Exception e) {
        log.trace("The body could not be filtered, the following exception {} has been thrown", e.getClass());
        // The place where returns not obfuscated response
        return body;
    }
}

Good find! Yeah, the same catch block should be added to CompositeOperation as well.

@paswd Thank you for pinpointing to the concrete bug location, the fix should be available in the next release.