VYPR
Moderate severityNVD Advisory· Published Mar 29, 2023· Updated Feb 13, 2025

Apache Archiva privilege escalation

CVE-2023-28158

Description

Privilege escalation via stored XSS using the file upload service to upload malicious content. The issue can be exploited only by authenticated users which can create directory name to inject some XSS content and gain some privileges such admin user.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Authenticated stored XSS in Apache Archiva file upload allows privilege escalation via malicious directory names.

Vulnerability

Description

CVE-2023-28158 is a privilege escalation vulnerability in Apache Archiva, the build artifact repository manager. The issue stems from stored cross-site scripting (XSS) in the file upload service. An authenticated attacker can inject malicious content through specially crafted directory names during file upload operations, bypassing insufficient input validation [1].

Exploitation

The attack requires authentication, as only authenticated users can upload files and create directories. By providing a directory name containing HTML or JavaScript payloads (e.g., containing <, >, or & characters), the attacker triggers stored XSS. The patch diffs show that Archiva previously lacked checks for these characters in directory names, and also used escapeJavaScript instead of the more appropriate escapeHtml for certain parameters [2][3].

Impact

Successful exploitation allows the attacker to execute arbitrary JavaScript in the context of the Archiva web interface. This can be leveraged to perform actions on behalf of a higher-privileged user viewing the malicious directory entry, ultimately leading to privilege escalation to admin-level access [1][4].

Mitigation

The vulnerability has been patched in the Apache Archiva codebase. Commit d62e81c7e75f617cf01d2a75952a2c857758f8c4 adds input validation for the <, >, and & characters in directory names and switches from escapeJavaScript to escapeHtml for several parameters [3]. Administrators should update to the patched version as soon as possible. No workaround is documented, and there is no indication that CVE-2023-28158 has been added to the CISA Known Exploited Vulnerabilities catalog.

AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.apache.archiva:archivaMaven
>= 2.0.0, < 2.2.102.2.10

Affected products

2

Patches

3
d62e81c7e75f

better testing of characters

https://github.com/apache/archivaOlivier LamyMar 14, 2023via ghsa
1 file changed · +19 10
  • archiva-modules/archiva-web/archiva-web-common/src/main/java/org/apache/archiva/web/api/DefaultFileUploadService.java+19 10 modified
    @@ -262,6 +262,15 @@ private boolean hasValidChars(String checkString) {
             if (checkString.contains("/..")) {
                 return false;
             }
    +        if (checkString.contains("<")) {
    +            return false;
    +        }
    +        if (checkString.contains(">")) {
    +            return false;
    +        }
    +        if (checkString.contains("&")) {
    +            return false;
    +        }
             return true;
         }
     
    @@ -280,11 +289,11 @@ public Boolean save( String repositoryId, String groupId, String artifactId, Str
                              boolean generatePom )
             throws ArchivaRestServiceException
         {
    -        repositoryId = StringEscapeUtils.escapeJavaScript( StringUtils.trim( repositoryId ) );
    -        groupId = StringEscapeUtils.escapeJavaScript( StringUtils.trim( groupId ) );
    -        artifactId = StringEscapeUtils.escapeJavaScript( StringUtils.trim( artifactId ) );
    -        version = StringEscapeUtils.escapeJavaScript( StringUtils.trim( version ) );
    -        packaging = StringEscapeUtils.escapeJavaScript( StringUtils.trim( packaging ) );
    +        repositoryId = StringEscapeUtils.escapeHtml( StringUtils.trim( repositoryId ) );
    +        groupId = StringEscapeUtils.escapeHtml( StringUtils.trim( groupId ) );
    +        artifactId = StringEscapeUtils.escapeHtml( StringUtils.trim( artifactId ) );
    +        version = StringEscapeUtils.escapeHtml( StringUtils.trim( version ) );
    +        packaging = StringEscapeUtils.escapeHtml( StringUtils.trim( packaging ) );
     
             checkParamChars("repositoryId", repositoryId);
             checkParamChars("groupId", groupId);
    @@ -378,11 +387,11 @@ protected void savePomFile( String repositoryId, FileMetadata fileMetadata, Stri
     
                 ManagedRepository repoConfig = managedRepositoryAdmin.getManagedRepository( repositoryId );
     
    -            repositoryId = StringEscapeUtils.escapeJavaScript( StringUtils.trim( repositoryId ) );
    -            groupId = StringEscapeUtils.escapeJavaScript( StringUtils.trim( groupId ) );
    -            artifactId = StringEscapeUtils.escapeJavaScript( StringUtils.trim( artifactId ) );
    -            version = StringEscapeUtils.escapeJavaScript( StringUtils.trim( version ) );
    -            packaging = StringEscapeUtils.escapeJavaScript( StringUtils.trim( packaging ) );
    +            repositoryId = StringEscapeUtils.escapeHtml( StringUtils.trim( repositoryId ) );
    +            groupId = StringEscapeUtils.escapeHtml( StringUtils.trim( groupId ) );
    +            artifactId = StringEscapeUtils.escapeHtml( StringUtils.trim( artifactId ) );
    +            version = StringEscapeUtils.escapeHtml( StringUtils.trim( version ) );
    +            packaging = StringEscapeUtils.escapeHtml( StringUtils.trim( packaging ) );
     
                 ArtifactReference artifactReference = new ArtifactReference();
                 artifactReference.setArtifactId( artifactId );
    
e7f7e70992d3

fix tomcat:run with last log4j api and multi release jars

https://github.com/apache/archivaOlivier LamyMar 14, 2023via ghsa
3 files changed · +124 7
  • archiva-modules/archiva-web/archiva-webapp/pom.xml+109 0 modified
    @@ -45,6 +45,7 @@
         <archiva.repositorySessionFactory.id>jcr</archiva.repositorySessionFactory.id>
         <cassandra.host>localhost</cassandra.host>
         <cassandra.port>9160</cassandra.port>
    +    <tomcat7Version>7.0.76</tomcat7Version>
       </properties>
     
       <dependencies>
    @@ -852,6 +853,7 @@
                 <org.apache.sirona.configuration.sirona.properties>${archiva.sirona.configuration}</org.apache.sirona.configuration.sirona.properties>
                 <AsyncLoggerConfig.WaitStrategy>Block</AsyncLoggerConfig.WaitStrategy>
                 <AsyncLogger.WaitStrategy>Block</AsyncLogger.WaitStrategy>
    +            <tomcat.util.scan.DefaultJarScanner.jarsToSkip>log4j-*.jar</tomcat.util.scan.DefaultJarScanner.jarsToSkip>
               </systemProperties>
               <additionalClasspathDirs>
                 <additionalClasspathDir>${basedir}/src/test/tomcat</additionalClasspathDir>
    @@ -868,6 +870,113 @@
                 <artifactId>mail</artifactId>
                 <version>${javaxMailVersion}</version>
               </dependency>
    +          <!-- insane but needed because of this https://bz.apache.org/bugzilla/show_bug.cgi?id=60688 -->
    +          <dependency>
    +            <groupId>org.apache.tomcat.embed</groupId>
    +            <artifactId>tomcat-embed-core</artifactId>
    +            <version>${tomcat7Version}</version>
    +          </dependency>
    +          <dependency>
    +            <groupId>org.apache.tomcat</groupId>
    +            <artifactId>tomcat-util</artifactId>
    +            <version>${tomcat7Version}</version>
    +          </dependency>
    +          <dependency>
    +            <groupId>org.apache.tomcat</groupId>
    +            <artifactId>tomcat-coyote</artifactId>
    +            <version>${tomcat7Version}</version>
    +          </dependency>
    +          <dependency>
    +            <groupId>org.apache.tomcat</groupId>
    +            <artifactId>tomcat-api</artifactId>
    +            <version>${tomcat7Version}</version>
    +          </dependency>
    +
    +          <dependency>
    +            <groupId>org.apache.tomcat</groupId>
    +            <artifactId>tomcat-jdbc</artifactId>
    +            <version>${tomcat7Version}</version>
    +          </dependency>
    +
    +          <dependency>
    +            <groupId>org.apache.tomcat</groupId>
    +            <artifactId>tomcat-dbcp</artifactId>
    +            <version>${tomcat7Version}</version>
    +          </dependency>
    +
    +          <dependency>
    +            <groupId>org.apache.tomcat</groupId>
    +            <artifactId>tomcat-servlet-api</artifactId>
    +            <version>${tomcat7Version}</version>
    +          </dependency>
    +
    +          <dependency>
    +            <groupId>org.apache.tomcat</groupId>
    +            <artifactId>tomcat-jsp-api</artifactId>
    +            <version>${tomcat7Version}</version>
    +          </dependency>
    +
    +          <dependency>
    +            <groupId>org.apache.tomcat</groupId>
    +            <artifactId>tomcat-jasper</artifactId>
    +            <version>${tomcat7Version}</version>
    +          </dependency>
    +
    +          <dependency>
    +            <groupId>org.apache.tomcat</groupId>
    +            <artifactId>tomcat-jasper-el</artifactId>
    +            <version>${tomcat7Version}</version>
    +          </dependency>
    +
    +          <dependency>
    +            <groupId>org.apache.tomcat</groupId>
    +            <artifactId>tomcat-el-api</artifactId>
    +            <version>${tomcat7Version}</version>
    +          </dependency>
    +
    +          <dependency>
    +            <groupId>org.apache.tomcat</groupId>
    +            <artifactId>tomcat-catalina</artifactId>
    +            <version>${tomcat7Version}</version>
    +          </dependency>
    +
    +          <dependency>
    +            <groupId>org.apache.tomcat</groupId>
    +            <artifactId>tomcat-tribes</artifactId>
    +            <version>${tomcat7Version}</version>
    +          </dependency>
    +
    +          <dependency>
    +            <groupId>org.apache.tomcat</groupId>
    +            <artifactId>tomcat-catalina-ha</artifactId>
    +            <version>${tomcat7Version}</version>
    +          </dependency>
    +
    +          <dependency>
    +            <groupId>org.apache.tomcat</groupId>
    +            <artifactId>tomcat-annotations-api</artifactId>
    +            <version>${tomcat7Version}</version>
    +          </dependency>
    +
    +          <!-- tomcat i18n too ?? -->
    +
    +          <!-- not sure we need that -->
    +          <dependency>
    +            <groupId>org.apache.tomcat</groupId>
    +            <artifactId>tomcat-juli</artifactId>
    +            <version>${tomcat7Version}</version>
    +          </dependency>
    +
    +          <dependency>
    +            <groupId>org.apache.tomcat.embed</groupId>
    +            <artifactId>tomcat-embed-logging-juli</artifactId>
    +            <version>${tomcat7Version}</version>
    +          </dependency>
    +          <dependency>
    +            <groupId>org.apache.tomcat.embed</groupId>
    +            <artifactId>tomcat-embed-logging-log4j</artifactId>
    +            <version>${tomcat7Version}</version>
    +          </dependency>
             </dependencies>
           </plugin>
     
    
  • archiva-modules/archiva-web/archiva-web-common/src/main/java/org/apache/archiva/web/api/DefaultFileUploadService.java+12 5 modified
    @@ -50,6 +50,7 @@
     import org.apache.commons.io.FilenameUtils;
     import org.apache.commons.io.IOUtils;
     import org.apache.commons.lang.BooleanUtils;
    +import org.apache.commons.lang.StringEscapeUtils;
     import org.apache.commons.lang.StringUtils;
     import org.apache.commons.lang.SystemUtils;
     import org.apache.cxf.jaxrs.ext.multipart.Attachment;
    @@ -279,11 +280,11 @@ public Boolean save( String repositoryId, String groupId, String artifactId, Str
                              boolean generatePom )
             throws ArchivaRestServiceException
         {
    -        repositoryId = StringUtils.trim( repositoryId );
    -        groupId = StringUtils.trim( groupId );
    -        artifactId = StringUtils.trim( artifactId );
    -        version = StringUtils.trim( version );
    -        packaging = StringUtils.trim( packaging );
    +        repositoryId = StringEscapeUtils.escapeJavaScript( StringUtils.trim( repositoryId ) );
    +        groupId = StringEscapeUtils.escapeJavaScript( StringUtils.trim( groupId ) );
    +        artifactId = StringEscapeUtils.escapeJavaScript( StringUtils.trim( artifactId ) );
    +        version = StringEscapeUtils.escapeJavaScript( StringUtils.trim( version ) );
    +        packaging = StringEscapeUtils.escapeJavaScript( StringUtils.trim( packaging ) );
     
             checkParamChars("repositoryId", repositoryId);
             checkParamChars("groupId", groupId);
    @@ -377,6 +378,12 @@ protected void savePomFile( String repositoryId, FileMetadata fileMetadata, Stri
     
                 ManagedRepository repoConfig = managedRepositoryAdmin.getManagedRepository( repositoryId );
     
    +            repositoryId = StringEscapeUtils.escapeJavaScript( StringUtils.trim( repositoryId ) );
    +            groupId = StringEscapeUtils.escapeJavaScript( StringUtils.trim( groupId ) );
    +            artifactId = StringEscapeUtils.escapeJavaScript( StringUtils.trim( artifactId ) );
    +            version = StringEscapeUtils.escapeJavaScript( StringUtils.trim( version ) );
    +            packaging = StringEscapeUtils.escapeJavaScript( StringUtils.trim( packaging ) );
    +
                 ArtifactReference artifactReference = new ArtifactReference();
                 artifactReference.setArtifactId( artifactId );
                 artifactReference.setGroupId( groupId );
    
  • archiva-modules/archiva-web/archiva-web-common/src/test/java/org/apache/archiva/upload/UploadArtifactsTest.java+3 2 modified
    @@ -28,7 +28,6 @@
     import org.apache.archiva.web.api.FileUploadService;
     import org.apache.archiva.web.model.FileMetadata;
     import org.apache.catalina.Context;
    -import org.apache.catalina.LifecycleException;
     import org.apache.catalina.deploy.ApplicationParameter;
     import org.apache.catalina.startup.Tomcat;
     import org.apache.commons.io.FileUtils;
    @@ -337,7 +336,9 @@ public void failSaveFileWithBadParams( ) throws IOException, ArchivaRestServiceE
                 meta = service.post( body );
                 log.debug( "Metadata {}", meta.toString( ) );
                 try {
    -                service.save("internal", "org", URLEncoder.encode("../../../test", "UTF-8"), URLEncoder.encode("testSave", "UTF-8"), "4", true);
    +                service.save("internal", "org",
    +                        URLEncoder.encode("../../../test", "UTF-8"),
    +                        URLEncoder.encode("testSave", "UTF-8"), "4", true);
                     fail("Error expected, if the content contains bad characters.");
                 } catch (ClientErrorException e) {
                     assertEquals(422, e.getResponse().getStatus());
    
ee3ee0a18977

[MRM-1793] trailing spaces not trimmed in upload form

https://github.com/apache/archivaOlivier LamyNov 20, 2013via ghsa
1 file changed · +8 2
  • archiva-modules/archiva-web/archiva-web-common/src/main/java/org/apache/archiva/web/api/DefaultFileUploadService.java+8 2 modified
    @@ -210,10 +210,16 @@ public List<FileMetadata> getSessionFileMetadatas()
             return fileMetadatas == null ? Collections.<FileMetadata>emptyList() : fileMetadatas;
         }
     
    -    public Boolean save( String repositoryId, final String groupId, final String artifactId, String version,
    -                         String packaging, final boolean generatePom )
    +    public Boolean save( String repositoryId, String groupId, String artifactId, String version,
    +                         String packaging, boolean generatePom )
             throws ArchivaRestServiceException
         {
    +        repositoryId = StringUtils.trim( repositoryId );
    +        groupId = StringUtils.trim( groupId );
    +        artifactId = StringUtils.trim( artifactId );
    +        version = StringUtils.trim( version );
    +        packaging = StringUtils.trim( packaging );
    +
             List<FileMetadata> fileMetadatas = getSessionFilesList();
             if ( fileMetadatas == null || fileMetadatas.isEmpty() )
             {
    

Vulnerability mechanics

Synthesis attempt was rejected by the grounding validator. Re-run pending.

References

8

News mentions

0

No linked articles in our index yet.