CVE-2014-8122 (Java, published 2015-02-13T15:59Z)
Description: value: Race condition in JBoss Weld before 2.2.8 and 3.x before 3.0.0 Alpha3 allows remote attackers to obtain information from a previous conversation via vectors related to a stale thread state.
Severity: MEDIUM (CVSS v3 base score: )
Weakness: CWE-362 \u2014 Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition')
The product contains a code sequence that can run concurrently with other code, and the code sequence requires temporary, exclusive access to a shared resource, but a timing window exists in which the shared resource can be modified by another code sequence that is operating concurrently.
Repository: https://github.com/weld/core
Files changed:
impl/src/main/java/org/jboss/weld/logging/ServletLogger.java
impl/src/main/java/org/jboss/weld/servlet/ConversationContextActivator.java
impl/src/main/java/org/jboss/weld/servlet/HttpContextLifecycle.java
Commit message: WELD-1802 An exception during context deactivation/dissociation should
not abort further procesing


Vulnerable code:
import javax.enterprise.context.spi.Context;
import javax.servlet.http.HttpServletRequest;

    @Message(id = 712, value = "Unable to dissociate context {0} when destroying request {1}", format = Format.MESSAGE_FORMAT)
    void unableToDissociateContext(Context context, HttpServletRequest request);
        ConversationContext conversationContext = httpConversationContext();
        if (conversationContext.isActive()) {
            // Only deactivate the context if one is already active, otherwise we get Exceptions
            if (conversationContext instanceof LazyHttpConversationContextImpl) {
                LazyHttpConversationContextImpl lazyConversationContext = (LazyHttpConversationContextImpl) conversationContext;
                if (!lazyConversationContext.isInitialized()) {
                    // if this lazy conversation has not been touched yet, just deactivate it
                    lazyConversationContext.deactivate();
                    return;
            }
            boolean isTransient = conversationContext.getCurrentConversation().isTransient();
            if (ConversationLogger.LOG.isTraceEnabled()) {
                    ConversationLogger.LOG.cleaningUpTransientConversation();
                } else {
                    ConversationLogger.LOG.cleaningUpConversation(conversationContext.getCurrentConversation().getId());
            conversationContext.invalidate();
            conversationContext.deactivate();
            if (isTransient) {
                conversationDestroyedEvent.fire(request);
            }
            getRequestContext().deactivate();
            getSessionContext().deactivate();
            getRequestContext().dissociate(request);

            try {
                getSessionContext().dissociate(request);
            } catch (Exception e) {
                ServletLogger.LOG.unableToDissociateContext(getSessionContext(), request);
                ServletLogger.LOG.catchingDebug(e);
            }
    @Override
    public void cleanup() {

Fixed code:
    @Message(id = 712, value = "Unable to dissociate context {0} from the storage {1}", format = Format.MESSAGE_FORMAT)
    void unableToDissociateContext(Object context, Object storage);
    @LogMessage(level = Level.WARN)
    @Message(id = 717, value = "Unable to deactivate context {0} when destroying request {1}", format = Format.MESSAGE_FORMAT)
    void unableToDeactivateContext(Object context, Object request);

        try {
            ConversationContext conversationContext = httpConversationContext();
            if (conversationContext.isActive()) {
                // Only deactivate the context if one is already active, otherwise we get Exceptions
                if (conversationContext instanceof LazyHttpConversationContextImpl) {
                    LazyHttpConversationContextImpl lazyConversationContext = (LazyHttpConversationContextImpl) conversationContext;
                    if (!lazyConversationContext.isInitialized()) {
                        // if this lazy conversation has not been touched yet, just deactivate it
                        lazyConversationContext.deactivate();
                        return;
                    }
                boolean isTransient = conversationContext.getCurrentConversation().isTransient();
                if (ConversationLogger.LOG.isTraceEnabled()) {
                    if (isTransient) {
                        ConversationLogger.LOG.cleaningUpTransientConversation();
                    } else {
                        ConversationLogger.LOG.cleaningUpConversation(conversationContext.getCurrentConversation().getId());
                    }
                }
                conversationContext.invalidate();
                conversationContext.deactivate();
                    conversationDestroyedEvent.fire(request);
        } catch (Exception e) {
            ServletLogger.LOG.unableToDeactivateContext(httpConversationContext(), request);
            ServletLogger.LOG.catchingDebug(e);
import org.jboss.weld.context.BoundContext;
import org.jboss.weld.context.ManagedContext;

            safelyDeactivate(getRequestContext(),  request);

            safelyDeactivate(getSessionContext(), request);
            safelyDissociate(getRequestContext(), request);
            safelyDissociate(getSessionContext(), request);

    @Override
    public void cleanup() {
    }

    private <T> void safelyDissociate(BoundContext<T> context, T storage) {
        try {
            context.dissociate(storage);
        } catch(Exception e) {
            ServletLogger.LOG.unableToDissociateContext(context, storage);
            ServletLogger.LOG.catchingDebug(e);
        }
    }

    private void safelyDeactivate(ManagedContext context, HttpServletRequest request) {
        try {
            context.deactivate();
        } catch(Exception e) {
            ServletLogger.LOG.unableToDeactivateContext(context, request);
            ServletLogger.LOG.catchingDebug(e);
        }