VYPR
High severityNVD Advisory· Published Apr 29, 2017· Updated Aug 5, 2024

CVE-2017-7957

CVE-2017-7957

Description

XStream through 1.4.9, when a certain denyTypes workaround is not used, mishandles attempts to create an instance of the primitive type 'void' during unmarshalling, leading to a remote application crash, as demonstrated by an xstream.fromXML("") call.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
com.thoughtworks.xstream:xstreamMaven
< 1.4.101.4.10

Affected products

31

Patches

6
8542d02d9ac5

Implement black list. Fix security unit test.

https://github.com/x-stream/xstreamjoehniMay 1, 2017via ghsa
2 files changed · +36 1
  • xstream/src/java/com/thoughtworks/xstream/XStream.java+34 0 modified
    @@ -58,8 +58,10 @@
     import com.thoughtworks.xstream.converters.ConverterLookup;
     import com.thoughtworks.xstream.converters.ConverterRegistry;
     import com.thoughtworks.xstream.converters.DataHolder;
    +import com.thoughtworks.xstream.converters.MarshallingContext;
     import com.thoughtworks.xstream.converters.SingleValueConverter;
     import com.thoughtworks.xstream.converters.SingleValueConverterWrapper;
    +import com.thoughtworks.xstream.converters.UnmarshallingContext;
     import com.thoughtworks.xstream.converters.basic.BigDecimalConverter;
     import com.thoughtworks.xstream.converters.basic.BigIntegerConverter;
     import com.thoughtworks.xstream.converters.basic.BooleanConverter;
    @@ -325,6 +327,8 @@ public class XStream {
         private SecurityMapper securityMapper;
         private AnnotationConfiguration annotationConfiguration;
     
    +    private transient boolean insecureWarning;
    +
         public static final int NO_REFERENCES = 1001;
         public static final int ID_REFERENCES = 1002;
         public static final int XPATH_RELATIVE_REFERENCES = 1003;
    @@ -681,6 +685,7 @@ protected void setupSecurity() {
             }
             
             addPermission(AnyTypePermission.ANY);
    +        insecureWarning = true;
         }
     
         protected void setupAliases() {
    @@ -847,6 +852,7 @@ protected void setupConverters() {
             registerConverter(
                 new SerializableConverter(mapper, reflectionProvider, classLoaderReference), PRIORITY_LOW);
             registerConverter(new ExternalizableConverter(mapper, classLoaderReference), PRIORITY_LOW);
    +        registerConverter(new InternalBlackList(), PRIORITY_LOW);
     
             registerConverter(new NullConverter(), PRIORITY_VERY_HIGH);
             registerConverter(new IntConverter(), PRIORITY_NORMAL);
    @@ -1364,6 +1370,10 @@ public Object unmarshal(HierarchicalStreamReader reader, Object root) {
          */
         public Object unmarshal(HierarchicalStreamReader reader, Object root, DataHolder dataHolder) {
             try {
    +            if (insecureWarning) {
    +                insecureWarning = false;
    +                System.err.println("Security framework of XStream not initialized, XStream is probably vulnerable.");
    +            }
                 return marshallingStrategy.unmarshal(
                     root, reader, dataHolder, converterLookup, mapper);
     
    @@ -2240,6 +2250,7 @@ public void autodetectAnnotations(boolean mode) {
          */
         public void addPermission(TypePermission permission) {
             if (securityMapper != null) {
    +            insecureWarning &= permission != NoTypePermission.NONE;
                 securityMapper.addPermission(permission);
             }
         }
    @@ -2413,4 +2424,27 @@ public InitializationException(String message) {
                 super(message);
             }
         }
    +
    +    private class InternalBlackList implements Converter {
    +
    +        public boolean canConvert(final Class type) {
    +            return (type == void.class || type == Void.class)
    +                || (insecureWarning
    +                    && type != null
    +                    && (type.getName().equals("java.beans.EventHandler")
    +                        || type.getName().endsWith("$LazyIterator")
    +                        || type.getName().startsWith("javax.crypto.")));
    +        }
    +
    +        @Override
    +        public void marshal(final Object source, final HierarchicalStreamWriter writer,
    +                final MarshallingContext context) {
    +            throw new ConversionException("Security alert. Marshalling rejected.");
    +        }
    +
    +        @Override
    +        public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
    +            throw new ConversionException("Security alert. Unmarshalling rejected.");
    +        }
    +    }
     }
    
  • xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java+2 1 modified
    @@ -67,6 +67,7 @@ public void testExplicitlyConvertEventHandler() {
                     + "  </dynamic-proxy>\n"
                     + "</string>";
     
    +        xstream.allowTypes(new Class[]{EventHandler.class});
             xstream.registerConverter(new ReflectionConverter(xstream.getMapper(), xstream
                 .getReflectionProvider(), EventHandler.class));
     
    @@ -98,7 +99,7 @@ public void testAllowedInstanceOfVoid() {
                 xstream.fromXML("<void/>");
                 fail("Thrown " + ConversionException.class.getName() + " expected");
             } catch (final ConversionException e) {
    -            assertEquals("void", e.get("construction-type"));
    +            assertEquals("void", e.get("required-type"));
             }
         }
     }
    
8542d02d9ac5

Implement black list. Fix security unit test.

https://github.com/x-stream/xstreamjoehniMay 1, 2017via ghsa
2 files changed · +36 1
  • xstream/src/java/com/thoughtworks/xstream/XStream.java+34 0 modified
    @@ -58,8 +58,10 @@
     import com.thoughtworks.xstream.converters.ConverterLookup;
     import com.thoughtworks.xstream.converters.ConverterRegistry;
     import com.thoughtworks.xstream.converters.DataHolder;
    +import com.thoughtworks.xstream.converters.MarshallingContext;
     import com.thoughtworks.xstream.converters.SingleValueConverter;
     import com.thoughtworks.xstream.converters.SingleValueConverterWrapper;
    +import com.thoughtworks.xstream.converters.UnmarshallingContext;
     import com.thoughtworks.xstream.converters.basic.BigDecimalConverter;
     import com.thoughtworks.xstream.converters.basic.BigIntegerConverter;
     import com.thoughtworks.xstream.converters.basic.BooleanConverter;
    @@ -325,6 +327,8 @@ public class XStream {
         private SecurityMapper securityMapper;
         private AnnotationConfiguration annotationConfiguration;
     
    +    private transient boolean insecureWarning;
    +
         public static final int NO_REFERENCES = 1001;
         public static final int ID_REFERENCES = 1002;
         public static final int XPATH_RELATIVE_REFERENCES = 1003;
    @@ -681,6 +685,7 @@ protected void setupSecurity() {
             }
             
             addPermission(AnyTypePermission.ANY);
    +        insecureWarning = true;
         }
     
         protected void setupAliases() {
    @@ -847,6 +852,7 @@ protected void setupConverters() {
             registerConverter(
                 new SerializableConverter(mapper, reflectionProvider, classLoaderReference), PRIORITY_LOW);
             registerConverter(new ExternalizableConverter(mapper, classLoaderReference), PRIORITY_LOW);
    +        registerConverter(new InternalBlackList(), PRIORITY_LOW);
     
             registerConverter(new NullConverter(), PRIORITY_VERY_HIGH);
             registerConverter(new IntConverter(), PRIORITY_NORMAL);
    @@ -1364,6 +1370,10 @@ public Object unmarshal(HierarchicalStreamReader reader, Object root) {
          */
         public Object unmarshal(HierarchicalStreamReader reader, Object root, DataHolder dataHolder) {
             try {
    +            if (insecureWarning) {
    +                insecureWarning = false;
    +                System.err.println("Security framework of XStream not initialized, XStream is probably vulnerable.");
    +            }
                 return marshallingStrategy.unmarshal(
                     root, reader, dataHolder, converterLookup, mapper);
     
    @@ -2240,6 +2250,7 @@ public void autodetectAnnotations(boolean mode) {
          */
         public void addPermission(TypePermission permission) {
             if (securityMapper != null) {
    +            insecureWarning &= permission != NoTypePermission.NONE;
                 securityMapper.addPermission(permission);
             }
         }
    @@ -2413,4 +2424,27 @@ public InitializationException(String message) {
                 super(message);
             }
         }
    +
    +    private class InternalBlackList implements Converter {
    +
    +        public boolean canConvert(final Class type) {
    +            return (type == void.class || type == Void.class)
    +                || (insecureWarning
    +                    && type != null
    +                    && (type.getName().equals("java.beans.EventHandler")
    +                        || type.getName().endsWith("$LazyIterator")
    +                        || type.getName().startsWith("javax.crypto.")));
    +        }
    +
    +        @Override
    +        public void marshal(final Object source, final HierarchicalStreamWriter writer,
    +                final MarshallingContext context) {
    +            throw new ConversionException("Security alert. Marshalling rejected.");
    +        }
    +
    +        @Override
    +        public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
    +            throw new ConversionException("Security alert. Unmarshalling rejected.");
    +        }
    +    }
     }
    
  • xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java+2 1 modified
    @@ -67,6 +67,7 @@ public void testExplicitlyConvertEventHandler() {
                     + "  </dynamic-proxy>\n"
                     + "</string>";
     
    +        xstream.allowTypes(new Class[]{EventHandler.class});
             xstream.registerConverter(new ReflectionConverter(xstream.getMapper(), xstream
                 .getReflectionProvider(), EventHandler.class));
     
    @@ -98,7 +99,7 @@ public void testAllowedInstanceOfVoid() {
                 xstream.fromXML("<void/>");
                 fail("Thrown " + ConversionException.class.getName() + " expected");
             } catch (final ConversionException e) {
    -            assertEquals("void", e.get("construction-type"));
    +            assertEquals("void", e.get("required-type"));
             }
         }
     }
    
6e546ec36641

Prevent deserialization of void.

https://github.com/x-stream/xstreamjoehniApr 3, 2017via ghsa
3 files changed · +41 13
  • xstream/src/java/com/thoughtworks/xstream/converters/reflection/SunLimitedUnsafeReflectionProvider.java+13 9 modified
    @@ -1,6 +1,6 @@
     /*
      * Copyright (C) 2004, 2005 Joe Walnes.
    - * Copyright (C) 2006, 2007, 2008, 2011, 2013, 2014, 2016 XStream Committers.
    + * Copyright (C) 2006, 2007, 2008, 2011, 2013, 2014, 2016, 2017 XStream Committers.
      * All rights reserved.
      *
      * Created on 08. January 2014 by Joerg Schaible, factored out from SunUnsafeReflectionProvider
    @@ -78,14 +78,18 @@ public Object newInstance(Class type) {
                 throw ex;
             }
             ErrorWritingException ex = null;
    -        try {
    -            return unsafe.allocateInstance(type);
    -        } catch (SecurityException e) {
    -            ex = new ObjectAccessException("Cannot construct type", e);
    -        } catch (InstantiationException e) {
    -            ex =  new ConversionException("Cannot construct type", e);
    -        } catch (IllegalArgumentException e) {
    -            ex = new ObjectAccessException("Cannot construct type", e);
    +        if (type == void.class || type == Void.class) {
    +            ex = new ConversionException("Type void cannot have an instance");
    +        } else {
    +            try {
    +                return unsafe.allocateInstance(type);
    +            } catch (final SecurityException e) {
    +                ex = new ObjectAccessException("Cannot construct type", e);
    +            } catch (final InstantiationException e) {
    +                ex = new ConversionException("Cannot construct type", e);
    +            } catch (final IllegalArgumentException e) {
    +                ex = new ObjectAccessException("Cannot construct type", e);
    +            }
             }
             ex.add("construction-type", type.getName());
             throw ex;
    
  • xstream/src/java/com/thoughtworks/xstream/security/PrimitiveTypePermission.java+5 3 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (C) 2014 XStream Committers.
    + * Copyright (C) 2014, 2017 XStream Committers.
      * All rights reserved.
      *
      * Created on 09. January 2014 by Joerg Schaible
    @@ -8,8 +8,9 @@
     
     import com.thoughtworks.xstream.core.util.Primitives;
     
    +
     /**
    - * Permission for any primitive type and its boxed counterpart (incl. void).
    + * Permission for any primitive type and its boxed counterpart (excl. void).
      * 
      * @author J&ouml;rg Schaible
      * @since 1.4.7
    @@ -21,7 +22,8 @@ public class PrimitiveTypePermission implements TypePermission {
         public static final TypePermission PRIMITIVES = new PrimitiveTypePermission();
     
         public boolean allows(Class type) {
    -        return type != null && type.isPrimitive() || Primitives.isBoxed(type);
    +        return type != null && type != void.class && type != Void.class && type.isPrimitive()
    +            || Primitives.isBoxed(type);
         }
     
         public int hashCode() {
    
  • xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java+23 1 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (C) 2013, 2014 XStream Committers.
    + * Copyright (C) 2013, 2014, 2017 XStream Committers.
      * All rights reserved.
      *
      * The software in this package is published under the terms of the BSD
    @@ -13,9 +13,12 @@
     import java.beans.EventHandler;
     
     import com.thoughtworks.xstream.XStreamException;
    +import com.thoughtworks.xstream.converters.ConversionException;
     import com.thoughtworks.xstream.converters.reflection.ReflectionConverter;
    +import com.thoughtworks.xstream.security.ForbiddenClassException;
     import com.thoughtworks.xstream.security.ProxyTypePermission;
     
    +
     /**
      * @author J&ouml;rg Schaible
      */
    @@ -80,4 +83,23 @@ public void exec() {
                 BUFFER.append("Executed!");
             }
         }
    +
    +    public void testDeniedInstanceOfVoid() {
    +        try {
    +            xstream.fromXML("<void/>");
    +            fail("Thrown " + ForbiddenClassException.class.getName() + " expected");
    +        } catch (final ForbiddenClassException e) {
    +            // OK
    +        }
    +    }
    +
    +    public void testAllowedInstanceOfVoid() {
    +        xstream.allowTypes(new Class[] { void.class, Void.class });
    +        try {
    +            xstream.fromXML("<void/>");
    +            fail("Thrown " + ConversionException.class.getName() + " expected");
    +        } catch (final ConversionException e) {
    +            assertEquals("void", e.get("construction-type"));
    +        }
    +    }
     }
    
b3570be2f392

Prevent deserialization of void.

https://github.com/x-stream/xstreamjoehniApr 3, 2017via ghsa
3 files changed · +41 13
  • xstream/src/java/com/thoughtworks/xstream/converters/reflection/SunLimitedUnsafeReflectionProvider.java+13 9 modified
    @@ -1,6 +1,6 @@
     /*
      * Copyright (C) 2004, 2005 Joe Walnes.
    - * Copyright (C) 2006, 2007, 2008, 2011, 2013, 2014, 2016 XStream Committers.
    + * Copyright (C) 2006, 2007, 2008, 2011, 2013, 2014, 2016, 2017 XStream Committers.
      * All rights reserved.
      *
      * Created on 08. January 2014 by Joerg Schaible, factored out from SunUnsafeReflectionProvider
    @@ -80,14 +80,18 @@ public Object newInstance(final Class<?> type) {
                 throw ex;
             }
             ErrorWritingException ex = null;
    -        try {
    -            return unsafe.allocateInstance(type);
    -        } catch (final SecurityException e) {
    -            ex = new ObjectAccessException("Cannot construct type", e);
    -        } catch (final InstantiationException e) {
    -            ex = new ConversionException("Cannot construct type", e);
    -        } catch (final IllegalArgumentException e) {
    -            ex = new ObjectAccessException("Cannot construct type", e);
    +        if (type == void.class || type == Void.class) {
    +            ex = new ConversionException("Type void cannot have an instance");
    +        } else {
    +            try {
    +                return unsafe.allocateInstance(type);
    +            } catch (final SecurityException e) {
    +                ex = new ObjectAccessException("Cannot construct type", e);
    +            } catch (final InstantiationException e) {
    +                ex = new ConversionException("Cannot construct type", e);
    +            } catch (final IllegalArgumentException e) {
    +                ex = new ObjectAccessException("Cannot construct type", e);
    +            }
             }
             ex.add("construction-type", type.getName());
             throw ex;
    
  • xstream/src/java/com/thoughtworks/xstream/security/PrimitiveTypePermission.java+5 3 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (C) 2014 XStream Committers.
    + * Copyright (C) 2014, 2017 XStream Committers.
      * All rights reserved.
      *
      * Created on 09. January 2014 by Joerg Schaible
    @@ -8,8 +8,9 @@
     
     import com.thoughtworks.xstream.core.util.Primitives;
     
    +
     /**
    - * Permission for any primitive type and its boxed counterpart (incl. void).
    + * Permission for any primitive type and its boxed counterpart (excl. void).
      * 
      * @author J&ouml;rg Schaible
      * @since 1.4.7
    @@ -22,7 +23,8 @@ public class PrimitiveTypePermission implements TypePermission {
     
         @Override
         public boolean allows(Class<?> type) {
    -        return type != null && type.isPrimitive() || Primitives.isBoxed(type);
    +        return type != null && type != void.class && type != Void.class && type.isPrimitive()
    +            || Primitives.isBoxed(type);
         }
     
         @Override
    
  • xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java+23 1 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (C) 2013, 2014 XStream Committers.
    + * Copyright (C) 2013, 2014, 2017 XStream Committers.
      * All rights reserved.
      *
      * The software in this package is published under the terms of the BSD
    @@ -13,9 +13,12 @@
     import java.beans.EventHandler;
     
     import com.thoughtworks.xstream.XStreamException;
    +import com.thoughtworks.xstream.converters.ConversionException;
     import com.thoughtworks.xstream.converters.reflection.ReflectionConverter;
    +import com.thoughtworks.xstream.security.ForbiddenClassException;
     import com.thoughtworks.xstream.security.ProxyTypePermission;
     
    +
     /**
      * @author J&ouml;rg Schaible
      */
    @@ -80,4 +83,23 @@ public void exec() {
                 BUFFER.append("Executed!");
             }
         }
    +
    +    public void testDeniedInstanceOfVoid() {
    +        try {
    +            xstream.fromXML("<void/>");
    +            fail("Thrown " + ForbiddenClassException.class.getName() + " expected");
    +        } catch (final ForbiddenClassException e) {
    +            // OK
    +        }
    +    }
    +
    +    public void testAllowedInstanceOfVoid() {
    +        xstream.allowTypes(void.class, Void.class);
    +        try {
    +            xstream.fromXML("<void/>");
    +            fail("Thrown " + ConversionException.class.getName() + " expected");
    +        } catch (final ConversionException e) {
    +            assertEquals("void", e.get("construction-type"));
    +        }
    +    }
     }
    
b3570be2f392

Prevent deserialization of void.

https://github.com/x-stream/xstreamjoehniApr 3, 2017via ghsa
3 files changed · +41 13
  • xstream/src/java/com/thoughtworks/xstream/converters/reflection/SunLimitedUnsafeReflectionProvider.java+13 9 modified
    @@ -1,6 +1,6 @@
     /*
      * Copyright (C) 2004, 2005 Joe Walnes.
    - * Copyright (C) 2006, 2007, 2008, 2011, 2013, 2014, 2016 XStream Committers.
    + * Copyright (C) 2006, 2007, 2008, 2011, 2013, 2014, 2016, 2017 XStream Committers.
      * All rights reserved.
      *
      * Created on 08. January 2014 by Joerg Schaible, factored out from SunUnsafeReflectionProvider
    @@ -80,14 +80,18 @@ public Object newInstance(final Class<?> type) {
                 throw ex;
             }
             ErrorWritingException ex = null;
    -        try {
    -            return unsafe.allocateInstance(type);
    -        } catch (final SecurityException e) {
    -            ex = new ObjectAccessException("Cannot construct type", e);
    -        } catch (final InstantiationException e) {
    -            ex = new ConversionException("Cannot construct type", e);
    -        } catch (final IllegalArgumentException e) {
    -            ex = new ObjectAccessException("Cannot construct type", e);
    +        if (type == void.class || type == Void.class) {
    +            ex = new ConversionException("Type void cannot have an instance");
    +        } else {
    +            try {
    +                return unsafe.allocateInstance(type);
    +            } catch (final SecurityException e) {
    +                ex = new ObjectAccessException("Cannot construct type", e);
    +            } catch (final InstantiationException e) {
    +                ex = new ConversionException("Cannot construct type", e);
    +            } catch (final IllegalArgumentException e) {
    +                ex = new ObjectAccessException("Cannot construct type", e);
    +            }
             }
             ex.add("construction-type", type.getName());
             throw ex;
    
  • xstream/src/java/com/thoughtworks/xstream/security/PrimitiveTypePermission.java+5 3 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (C) 2014 XStream Committers.
    + * Copyright (C) 2014, 2017 XStream Committers.
      * All rights reserved.
      *
      * Created on 09. January 2014 by Joerg Schaible
    @@ -8,8 +8,9 @@
     
     import com.thoughtworks.xstream.core.util.Primitives;
     
    +
     /**
    - * Permission for any primitive type and its boxed counterpart (incl. void).
    + * Permission for any primitive type and its boxed counterpart (excl. void).
      * 
      * @author J&ouml;rg Schaible
      * @since 1.4.7
    @@ -22,7 +23,8 @@ public class PrimitiveTypePermission implements TypePermission {
     
         @Override
         public boolean allows(Class<?> type) {
    -        return type != null && type.isPrimitive() || Primitives.isBoxed(type);
    +        return type != null && type != void.class && type != Void.class && type.isPrimitive()
    +            || Primitives.isBoxed(type);
         }
     
         @Override
    
  • xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java+23 1 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (C) 2013, 2014 XStream Committers.
    + * Copyright (C) 2013, 2014, 2017 XStream Committers.
      * All rights reserved.
      *
      * The software in this package is published under the terms of the BSD
    @@ -13,9 +13,12 @@
     import java.beans.EventHandler;
     
     import com.thoughtworks.xstream.XStreamException;
    +import com.thoughtworks.xstream.converters.ConversionException;
     import com.thoughtworks.xstream.converters.reflection.ReflectionConverter;
    +import com.thoughtworks.xstream.security.ForbiddenClassException;
     import com.thoughtworks.xstream.security.ProxyTypePermission;
     
    +
     /**
      * @author J&ouml;rg Schaible
      */
    @@ -80,4 +83,23 @@ public void exec() {
                 BUFFER.append("Executed!");
             }
         }
    +
    +    public void testDeniedInstanceOfVoid() {
    +        try {
    +            xstream.fromXML("<void/>");
    +            fail("Thrown " + ForbiddenClassException.class.getName() + " expected");
    +        } catch (final ForbiddenClassException e) {
    +            // OK
    +        }
    +    }
    +
    +    public void testAllowedInstanceOfVoid() {
    +        xstream.allowTypes(void.class, Void.class);
    +        try {
    +            xstream.fromXML("<void/>");
    +            fail("Thrown " + ConversionException.class.getName() + " expected");
    +        } catch (final ConversionException e) {
    +            assertEquals("void", e.get("construction-type"));
    +        }
    +    }
     }
    
6e546ec36641

Prevent deserialization of void.

https://github.com/x-stream/xstreamjoehniApr 3, 2017via ghsa
3 files changed · +41 13
  • xstream/src/java/com/thoughtworks/xstream/converters/reflection/SunLimitedUnsafeReflectionProvider.java+13 9 modified
    @@ -1,6 +1,6 @@
     /*
      * Copyright (C) 2004, 2005 Joe Walnes.
    - * Copyright (C) 2006, 2007, 2008, 2011, 2013, 2014, 2016 XStream Committers.
    + * Copyright (C) 2006, 2007, 2008, 2011, 2013, 2014, 2016, 2017 XStream Committers.
      * All rights reserved.
      *
      * Created on 08. January 2014 by Joerg Schaible, factored out from SunUnsafeReflectionProvider
    @@ -78,14 +78,18 @@ public Object newInstance(Class type) {
                 throw ex;
             }
             ErrorWritingException ex = null;
    -        try {
    -            return unsafe.allocateInstance(type);
    -        } catch (SecurityException e) {
    -            ex = new ObjectAccessException("Cannot construct type", e);
    -        } catch (InstantiationException e) {
    -            ex =  new ConversionException("Cannot construct type", e);
    -        } catch (IllegalArgumentException e) {
    -            ex = new ObjectAccessException("Cannot construct type", e);
    +        if (type == void.class || type == Void.class) {
    +            ex = new ConversionException("Type void cannot have an instance");
    +        } else {
    +            try {
    +                return unsafe.allocateInstance(type);
    +            } catch (final SecurityException e) {
    +                ex = new ObjectAccessException("Cannot construct type", e);
    +            } catch (final InstantiationException e) {
    +                ex = new ConversionException("Cannot construct type", e);
    +            } catch (final IllegalArgumentException e) {
    +                ex = new ObjectAccessException("Cannot construct type", e);
    +            }
             }
             ex.add("construction-type", type.getName());
             throw ex;
    
  • xstream/src/java/com/thoughtworks/xstream/security/PrimitiveTypePermission.java+5 3 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (C) 2014 XStream Committers.
    + * Copyright (C) 2014, 2017 XStream Committers.
      * All rights reserved.
      *
      * Created on 09. January 2014 by Joerg Schaible
    @@ -8,8 +8,9 @@
     
     import com.thoughtworks.xstream.core.util.Primitives;
     
    +
     /**
    - * Permission for any primitive type and its boxed counterpart (incl. void).
    + * Permission for any primitive type and its boxed counterpart (excl. void).
      * 
      * @author J&ouml;rg Schaible
      * @since 1.4.7
    @@ -21,7 +22,8 @@ public class PrimitiveTypePermission implements TypePermission {
         public static final TypePermission PRIMITIVES = new PrimitiveTypePermission();
     
         public boolean allows(Class type) {
    -        return type != null && type.isPrimitive() || Primitives.isBoxed(type);
    +        return type != null && type != void.class && type != Void.class && type.isPrimitive()
    +            || Primitives.isBoxed(type);
         }
     
         public int hashCode() {
    
  • xstream/src/test/com/thoughtworks/acceptance/SecurityVulnerabilityTest.java+23 1 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (C) 2013, 2014 XStream Committers.
    + * Copyright (C) 2013, 2014, 2017 XStream Committers.
      * All rights reserved.
      *
      * The software in this package is published under the terms of the BSD
    @@ -13,9 +13,12 @@
     import java.beans.EventHandler;
     
     import com.thoughtworks.xstream.XStreamException;
    +import com.thoughtworks.xstream.converters.ConversionException;
     import com.thoughtworks.xstream.converters.reflection.ReflectionConverter;
    +import com.thoughtworks.xstream.security.ForbiddenClassException;
     import com.thoughtworks.xstream.security.ProxyTypePermission;
     
    +
     /**
      * @author J&ouml;rg Schaible
      */
    @@ -80,4 +83,23 @@ public void exec() {
                 BUFFER.append("Executed!");
             }
         }
    +
    +    public void testDeniedInstanceOfVoid() {
    +        try {
    +            xstream.fromXML("<void/>");
    +            fail("Thrown " + ForbiddenClassException.class.getName() + " expected");
    +        } catch (final ForbiddenClassException e) {
    +            // OK
    +        }
    +    }
    +
    +    public void testAllowedInstanceOfVoid() {
    +        xstream.allowTypes(new Class[] { void.class, Void.class });
    +        try {
    +            xstream.fromXML("<void/>");
    +            fail("Thrown " + ConversionException.class.getName() + " expected");
    +        } catch (final ConversionException e) {
    +            assertEquals("void", e.get("construction-type"));
    +        }
    +    }
     }
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

14

News mentions

0

No linked articles in our index yet.