VYPR
Moderate severityNVD Advisory· Published Jul 9, 2012· Updated Apr 29, 2026

CVE-2012-2138

CVE-2012-2138

Description

The @CopyFrom operation in the POST servlet in the org.apache.sling.servlets.post bundle before 2.1.2 in Apache Sling does not prevent attempts to copy an ancestor node to a descendant node, which allows remote attackers to cause a denial of service (infinite loop) via a crafted HTTP request.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.apache.sling:org.apache.sling.servlets.postMaven
< 2.1.22.1.2

Affected products

1

Patches

1
0205892908d6

SLING-2517 - validity checks for CopyFrom paths, with tests

2 files changed · +95 0
  • src/main/java/org/apache/sling/servlets/post/impl/operations/CopyOperation.java+18 0 modified
    @@ -97,6 +97,11 @@ static Item copy(Item src, Node dstParent, String name)
         static Item copy(Node src, Node dstParent, String name)
                 throws RepositoryException {
     
    +        if(isAncestorOrSameNode(src, dstParent)) {
    +            throw new RepositoryException(
    +                    "Cannot copy ancestor " + src.getPath() + " to descendant " + dstParent.getPath());
    +        }
    +        
             // ensure destination name
             if (name == null) {
                 name = src.getName();
    @@ -127,6 +132,19 @@ static Item copy(Node src, Node dstParent, String name)
             }
             return dst;
         }
    +    
    +    /** @return true if src is an ancestor node of dest, or if
    +     *  both are the same node */
    +    static boolean isAncestorOrSameNode(Node src, Node dest) throws RepositoryException {
    +        if(src.getPath().equals("/")) {
    +            return true;
    +        } else if(src.getPath().equals(dest.getPath())) {
    +            return true;
    +        } else if(dest.getPath().startsWith(src.getPath() + "/")) {
    +            return true;
    +        }
    +        return false;
    +    }
     
         /**
          * Copy the <code>src</code> property into the <code>dstParent</code>
    
  • src/test/java/org/apache/sling/servlets/post/impl/operations/CopyOperationTest.java+77 0 added
    @@ -0,0 +1,77 @@
    +/*
    + * Licensed to the Apache Software Foundation (ASF) under one
    + * or more contributor license agreements.  See the NOTICE file
    + * distributed with this work for additional information
    + * regarding copyright ownership.  The ASF licenses this file
    + * to you under the Apache License, Version 2.0 (the
    + * "License"); you may not use this file except in compliance
    + * with the License.  You may obtain a copy of the License at
    + *
    + *   http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing,
    + * software distributed under the License is distributed on an
    + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    + * KIND, either express or implied.  See the License for the
    + * specific language governing permissions and limitations
    + * under the License.
    + */
    +package org.apache.sling.servlets.post.impl.operations;
    +
    +import javax.jcr.Node;
    +import javax.jcr.RepositoryException;
    +
    +import junit.framework.TestCase;
    +
    +import org.jmock.Expectations;
    +import org.jmock.Mockery;
    +import org.jmock.integration.junit4.JMock;
    +import org.jmock.integration.junit4.JUnit4Mockery;
    +import org.junit.Test;
    +import org.junit.runner.RunWith;
    +
    +@RunWith(JMock.class)
    +public class CopyOperationTest extends TestCase {
    +    private Mockery context = new JUnit4Mockery();
    +    private int counter;
    +    
    +    private void assertResult(final String srcPath, final String destPath, Boolean expectedResult) throws RepositoryException {
    +        counter++;
    +        final Node src = context.mock(Node.class, "src" + counter);
    +        final Node dest = context.mock(Node.class, "dest" + counter);
    +        
    +        context.checking(new Expectations() {
    +            {
    +                allowing(src).getPath();
    +                will(returnValue(srcPath));
    +                allowing(dest).getPath();
    +                will(returnValue(destPath));
    +            }
    +        });
    +
    +        final boolean result = CopyOperation.isAncestorOrSameNode(src, dest);
    +        assertEquals(
    +                "Expecting isAncestorOrSameNode to be " + expectedResult + " for " + srcPath + " and " + destPath,
    +                expectedResult.booleanValue(), result);
    +    }
    +    
    +    @Test
    +    public void testIsAncestorOrSameNode() throws RepositoryException {
    +        final Object [] testCases = {
    +                "/", "/", true,
    +                "/a", "/a", true,
    +                "/a/bee/ceee", "/a/bee/ceee", true,
    +                "/", "/tmp", true,
    +                "/a", "/a/b", true,
    +                "/a", "/a/b/c/dee/eeee", true,
    +                "/a", "/ab", false,
    +                "/ab/cd", "/ab/cde", false,
    +                "/ab", "/cd", false,
    +        };
    +        
    +        for(int i=0; i < testCases.length; i+=3) {
    +            assertResult((String)testCases[i], (String)testCases[i+1], (Boolean)(testCases[i+2]));
    +        }
    +        
    +    }
    +}
    \ No newline at end of file
    

Vulnerability mechanics

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

References

7

News mentions

0

No linked articles in our index yet.