class UnsafeJacksonDeserializationDetector implements Detector {

    private static final String DESERIALIZATION_TYPE = "JACKSON_UNSAFE_DESERIALIZATION";

    private BugReporter bugReporter;


    public UnsafeJacksonDeserializationDetector(BugReporter bugReporter) {
        this.bugReporter = bugReporter;
    }

    private static final List<String> ANNOTATION_TYPES = Arrays.asList(
            "Lcom/fasterxml/jackson/annotation/JsonTypeInfo;");

    private static final List<String> VULNERABLE_USE_NAMES = Arrays.asList(
            "CLASS", "MINIMAL_CLASS");

    private static final List<String> OBJECT_MAPPER_CLASSES = Arrays.asList(
            "com.fasterxml.jackson.databind.ObjectMapper",
            "org.codehaus.jackson.map.ObjectMapper");


    @Override
    public void visitClassContext(ClassContext classContext) {
        JavaClass javaClass = classContext.getJavaClass();
        if (OBJECT_MAPPER_CLASSES.contains(javaClass.getClassName())) {
            return;
        }
        for (Field field : javaClass.getFields()) {
            analyzeField(field, javaClass);
        }
        for (Method m : javaClass.getMethods()) {
            try {
                analyzeMethod(m, classContext);
            }
            catch (CFGBuilderException | DataflowAnalysisException e) {
            }
        }
    }

    private void analyzeField(Field field, JavaClass javaClass) {<FILL_FUNCTION_BODY>}

    private void analyzeMethod(Method m, ClassContext classContext) throws CFGBuilderException, DataflowAnalysisException {
        MethodGen methodGen = classContext.getMethodGen(m);
        ConstantPoolGen cpg = classContext.getConstantPoolGen();
        CFG cfg = classContext.getCFG(m);

        if (methodGen == null || methodGen.getInstructionList() == null) {
            return; //No instruction .. nothing to do
        }
        for (Iterator<Location> i = cfg.locationIterator(); i.hasNext(); ) {
            Location location = i.next();
            Instruction inst = location.getHandle().getInstruction();
            if (inst instanceof InvokeInstruction) {
                InvokeInstruction invoke = (InvokeInstruction) inst;
                String methodName = invoke.getMethodName(cpg);
                if ("enableDefaultTyping".equals(methodName)) {
                    JavaClass clz = classContext.getJavaClass();
                    bugReporter.reportBug(new BugInstance(this, DESERIALIZATION_TYPE, HIGH_PRIORITY)
                            .addClass(clz)
                            .addMethod(clz, m)
                            .addCalledMethod(cpg, invoke)
                            .addSourceLine(classContext, m, location)
                    );
                }
            }
        }
    }

    @Override
    public void report() {
    }

}

        for (AnnotationEntry annotation : field.getAnnotationEntries())  {
            if (ANNOTATION_TYPES.contains(annotation.getAnnotationType()) ||
                    annotation.getAnnotationType().contains("JsonTypeInfo")) {
                for (ElementValuePair elementValuePair : annotation.getElementValuePairs()) {
                    if ("use".equals((elementValuePair.getNameString())) &&
                            VULNERABLE_USE_NAMES.contains(elementValuePair.getValue().stringifyValue())) {
                        bugReporter.reportBug(new BugInstance(this, DESERIALIZATION_TYPE, HIGH_PRIORITY)
                                .addClass(javaClass)
                                .addString(javaClass.getClassName() + " on field " +
                                        field.getName() + " of type " + field.getType() +
                                        " annotated with " + annotation.toShortString())
                                .addField(FieldAnnotation.fromBCELField(javaClass, field))
                                .addString("")
                        );
                    }
                }
            }
        }
    
<no_super_class>