VYPR
Low severityNVD Advisory· Published Apr 4, 2019· Updated Aug 5, 2024

CVE-2019-1003063

CVE-2019-1003063

Description

Jenkins Amazon SNS Build Notifier Plugin stores credentials unencrypted in its global configuration file on the Jenkins master where they can be viewed by users with access to the master file system.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.jenkins-ci.plugins:snsnotifyMaven
< 2.372.37

Affected products

1

Patches

1
874db1f2882a

Update AWS SDK + Fix clear text AWS secret key

https://github.com/jenkinsci/snsnotify-pluginMichael MeissnerApr 26, 2021via ghsa
10 files changed · +126 52
  • CHANGELOG.md+48 0 added
    @@ -0,0 +1,48 @@
    +Changelog
    +===
    +
    +### 2.0
    +
    +Release date: _Apr ??, 2021_
    +
    +* Fixed clear text persistence of AWS secret key
    +* Updated parent pom to 4.18
    +* Set min Jenkins version to 2.263.1
    +* Added dependency to plugin aws-java-sdk 1.11.995
    +* Removed dependency to included aws-java-sdk-sns
    +* Removed dependency to included httpcore
    +* Added docs
    +* Added changelog
    +
    +### 1.13
    +
    +Release date: _Mar 9, 2016_
    +
    +* Added support for IAM Roles
    +* Ability to disable notifications on every build.
    +
    +### 1.10
    +
    +Release date: _Jan 19, 2016_
    +
    +* Cleaned up dependencies.
    +
    +### 1.9
    +
    +Release date: _May 21, 2015_
    +
    +* Containing support for more BUILD_* variables.
    +
    +### 1.8
    +
    +Release date: _Oct 12, 2014_
    +
    +* Allow to send out SNS notifications also on build start.
    +
    +### 1.7
    +
    +Release date: _Aug 25, 2014_
    +
    +* Update to current LTS version
    +* Send SNS notification for all build return types
    +* Allow to specify template for subject and message notification.
    
  • docs/images/snsnotify-global-config.png+0 0 added
  • docs/images/snsnotify-post-build-config.png+0 0 added
  • .gitignore+1 0 modified
    @@ -4,6 +4,7 @@ release.properties
     pom.xml.releaseBackup
     
     # IntelliJ project files
    +.idea/
     *.ipr
     *.iml
     *.iws
    
  • pom.xml+16 13 modified
    @@ -5,15 +5,21 @@
         <parent>
             <groupId>org.jenkins-ci.plugins</groupId>
             <artifactId>plugin</artifactId>
    -        <version>1.565.1</version>
    +        <version>4.18</version> <!-- or whatever the newest version available is -->
    +        <relativePath />
         </parent>
     
         <artifactId>snsnotify</artifactId>
    -    <version>1.14-SNAPSHOT</version>
    +    <version>2.0-SNAPSHOT</version>
         <packaging>hpi</packaging>
         <name>Amazon SNS Build Notifier</name>
         <description>Publish build notifications to an AWS SNS Topic</description>
    -    <url>https://wiki.jenkins-ci.org/display/JENKINS/Amazon+SNS+Notifier</url>
    +    <url>https://github.com/jenkinsci/snsnotify-plugin</url>
    +
    +    <properties>
    +        <jenkins.version>2.263.1</jenkins.version>
    +        <java.level>8</java.level>
    +    </properties>
     
         <developers>
             <developer>
    @@ -28,6 +34,10 @@
                 <id>nikos</id>
                 <name>Niko Schmuck</name>
             </developer>
    +        <developer>
    +            <id>lenslord</id>
    +            <name>Michael Meissner</name>
    +        </developer>
         </developers>
     
         <scm>
    @@ -38,19 +48,12 @@
     
         <dependencies>
             <dependency>
    -            <groupId>com.amazonaws</groupId>
    -            <artifactId>aws-java-sdk-sns</artifactId>
    -            <version>RELEASE</version>
    -        </dependency>
    -
    -        <dependency>
    -            <groupId>org.apache.httpcomponents</groupId>
    -            <artifactId>httpcore</artifactId>
    -            <version>4.4.1</version>
    +            <groupId>org.jenkins-ci.plugins</groupId>
    +            <artifactId>aws-java-sdk</artifactId>
    +            <version>1.11.995</version>
             </dependency>
         </dependencies>
     
    -
         <repositories>
             <repository>
                 <id>repo.jenkins-ci.org</id>
    
  • README.md+4 2 modified
    @@ -13,7 +13,7 @@ Create an installable artifact:
     1. `mvn clean install`
     2. (wait for mvn to download the internet)
     3. Manage Jenkins > Plugins > Advanced > Upload ```./target/snsnotify.hpi```
    -4. Restart Jenkins ([$JENKINS_URL]/restart)
    +4. Restart Jenkins ([$JENKINS_URL]/safeRestart)
     
     Now, login to AWS and do the following:
     
    @@ -24,11 +24,13 @@ Finally, back to Jenkins...
     
     1. Manage Jenkins > Configure Jenkins to use AWS creds and newly created Topic ARN.
        You can also specify the default bevaiour in case you want to send out also an 
    -   SNS notification when the build is started (off by default). 
    +   SNS notification when the build is started (off by default).
    +   ![](docs/images/snsnotify-global-config.png)
     2. As part of your job: add post-build step for SNS notification, optionally configure 
        subject and message (you can make use of build and environment variables, which do 
        get substituted), resp. override Topic ARN (if you do not want to stick with globally 
        configured one).
    +   ![](docs/images/snsnotify-post-build-config.png)
        
     
     ## helpfull aws snippets
    
  • src/main/java/org/jenkinsci/plugins/snsnotify/AmazonSNSNotifier.java+47 30 modified
    @@ -1,8 +1,8 @@
     package org.jenkinsci.plugins.snsnotify;
     
    -import com.amazonaws.auth.AWSCredentials;
    -import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
    -import com.amazonaws.auth.BasicAWSCredentials;
    +import com.amazonaws.auth.*;
    +import com.amazonaws.client.builder.AwsClientBuilder;
    +import com.amazonaws.services.sns.AmazonSNS;
     import com.amazonaws.services.sns.AmazonSNSClient;
     import com.amazonaws.services.sns.model.PublishRequest;
     import hudson.EnvVars;
    @@ -16,6 +16,7 @@
     import hudson.tasks.BuildStepMonitor;
     import hudson.tasks.Notifier;
     import hudson.tasks.Publisher;
    +import hudson.util.Secret;
     import net.sf.json.JSONObject;
     import org.apache.commons.lang.StringUtils;
     import org.kohsuke.stapler.DataBoundConstructor;
    @@ -105,7 +106,7 @@ public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListen
     
         private void send(AbstractBuild build, TaskListener listener, BuildPhase phase) {
             String awsAccessKey = getDescriptor().getAwsAccessKey();
    -        String awsSecretKey = getDescriptor().getAwsSecretKey();
    +        Secret awsSecretKey = getDescriptor().getAwsSecretKey();
             String publishTopic = isEmpty(projectTopicArn) ?
                     getDescriptor().getDefaultTopicArn() : projectTopicArn;
             boolean useLocalCredential = getDescriptor().isDefaultLocalCredential();
    @@ -115,23 +116,24 @@ private void send(AbstractBuild build, TaskListener listener, BuildPhase phase)
                 return;
             }
     
    -        if (!(useLocalCredential) && (isEmpty(awsAccessKey) || isEmpty(awsSecretKey))) {
    +        if (!(useLocalCredential) && (isEmpty(awsAccessKey) || isEmpty(awsSecretKey.getPlainText()))) {
                 listener.error("AWS credentials not configured; cannot send SNS notification");
                 return;
             }
     
    -        String snsApiEndpoint = getSNSApiEndpoint(publishTopic);
    -        if (isEmpty(snsApiEndpoint)) {
    +        AwsClientBuilder.EndpointConfiguration snsApiEndpoint = getSNSApiEndpoint(publishTopic);
    +        if (snsApiEndpoint == null) {
                 listener.error("Could not determine SNS API Endpoint from topic ARN: " + publishTopic);
                 return;
             }
     
             // ~~ prepare subject (incl. variable replacement)
             String subject;
             if (StringUtils.isEmpty(subjectTemplate)) {
    +            Result buildResult = build.getResult();
                 subject = truncate(
                         String.format("Build %s: %s",
    -                            phase == BuildPhase.STARTED ? "STARTED" : build.getResult().toString(),
    +                            phase == BuildPhase.STARTED || buildResult == null? "STARTED" : buildResult.toString(),
                                 build.getFullDisplayName()), 100);
             } else {
                 subject = replaceVariables(build, listener, phase, subjectTemplate);
    @@ -142,22 +144,24 @@ private void send(AbstractBuild build, TaskListener listener, BuildPhase phase)
                     isEmpty(messageTemplate) ? getDescriptor().getDefaultMessageTemplate() : messageTemplate);
     
             LOG.info("Setup SNS client '" + snsApiEndpoint + "' ...");
    -        AWSCredentials awsCredentials;
    +        AWSCredentialsProvider awsCredentialsProvider;
             try {
                 if (useLocalCredential) {
    -                awsCredentials = new DefaultAWSCredentialsProviderChain().getCredentials();
    +                awsCredentialsProvider = new DefaultAWSCredentialsProviderChain();
                 }
                 else {
    -                awsCredentials = new BasicAWSCredentials(awsAccessKey, awsSecretKey);
    +                awsCredentialsProvider = new AWSStaticCredentialsProvider(new BasicAWSCredentials(awsAccessKey, awsSecretKey.getPlainText()));
                 }
             }
             catch (Exception e) {
                 listener.error("Failed to send SNS notification: " + e.getMessage());
                 return;
             }
     
    -        AmazonSNSClient snsClient = new AmazonSNSClient(awsCredentials);
    -        snsClient.setEndpoint(snsApiEndpoint);
    +        AmazonSNS snsClient = AmazonSNSClient.builder()
    +                .withEndpointConfiguration(snsApiEndpoint)
    +                .withCredentials(awsCredentialsProvider)
    +                .build();
     
             try {
                 String summary = String.format("subject=%s topic=%s", subject, publishTopic);
    @@ -216,18 +220,27 @@ private boolean isEmpty(String s) {
          */
         private String replaceVariables(AbstractBuild build, TaskListener listener,
                                         BuildPhase phase, String tmpl) {
    +        String resultString = tmpl;
    +
             try {
                 EnvVars envVars = build.getEnvironment(listener);
    +            Result buildResult = build.getResult();
    +
                 envVars.put("BUILD_PHASE", phase.name());
                 envVars.put("BUILD_ARTIFACT_PATHS", artifactPaths(build.getArtifacts()));
    -            envVars.put("BUILD_RESULT", phase == BuildPhase.STARTED ? "STARTED" : build.getResult().toString());
    +            envVars.put("BUILD_RESULT", phase == BuildPhase.STARTED || buildResult == null ? "STARTED" : buildResult.toString());
                 envVars.put("BUILD_DURATION", Long.toString(build.getDuration()));
                 String result = Util.replaceMacro(tmpl, build.getBuildVariableResolver());
    -            return Util.replaceMacro(result, envVars);
    -        } catch (Exception e) {
    +            resultString = Util.replaceMacro(result, envVars);
    +        }
    +        catch (RuntimeException e) {
    +            LOG.warning("Unable to get environment while trying to replace variables on " + tmpl);
    +        }
    +        catch (Exception e) {
                 LOG.warning("Unable to get environment while trying to replace variables on " + tmpl);
    -            return tmpl;
             }
    +
    +        return resultString;
         }
     
         /**
    @@ -244,7 +257,7 @@ private String artifactPaths(List<Artifact> artifacts) {
          * Determine the SNS API endpoint to make API calls to, based on the region
          * included in the topic ARN.
          */
    -    private String getSNSApiEndpoint(String topicArn) {
    +    private AwsClientBuilder.EndpointConfiguration getSNSApiEndpoint(String topicArn) {
     
             // This is probably not a recommended way to pick the API endpoint, but
             // it seems to be a reasonably safe assumption, and avoids extra
    @@ -256,7 +269,17 @@ private String getSNSApiEndpoint(String topicArn) {
             }
     
             String region = arnParts[3];
    -        return "sns." + region + ".amazonaws.com";
    +
    +        String apiEndpoint = "";
    +        if (region.startsWith("cn-")){
    +            apiEndpoint = "sns." + region + ".amazonaws.com.cn";
    +        } else {
    +            apiEndpoint = "sns." + region + ".amazonaws.com";
    +        }
    +
    +        AwsClientBuilder.EndpointConfiguration conf = new AwsClientBuilder.EndpointConfiguration (apiEndpoint, region);
    +
    +        return conf;
         }
     
     
    @@ -266,7 +289,7 @@ private String getSNSApiEndpoint(String topicArn) {
         public static final class DescriptorImpl extends BuildStepDescriptor<Publisher> {
     
             private String awsAccessKey;
    -        private String awsSecretKey;
    +        private Secret awsSecretKey;
             private String defaultTopicArn;
             private String defaultMessageTemplate;
             private boolean defaultSendNotificationOnStart;
    @@ -290,22 +313,16 @@ public boolean isApplicable(Class<? extends AbstractProject> aClass) {
     
             @Override
             public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {
    -            awsAccessKey = formData.getString("awsAccessKey");
    -            awsSecretKey = formData.getString("awsSecretKey");
    -            defaultTopicArn = formData.getString("defaultTopicArn");
    -            defaultMessageTemplate = formData.getString("defaultMessageTemplate");
    -            defaultSendNotificationOnStart = formData.getBoolean("defaultSendNotificationOnStart");
    -            defaultLocalCredential = formData.getBoolean("defaultLocalCredential");
    -            defaultNotifyOnConsecutiveSuccesses = formData.getBoolean("defaultNotifyOnConsecutiveSuccesses");
    +            req.bindJSON(this, formData);
                 save();
    -            return super.configure(req, formData);
    +            return true;
             }
     
             public String getAwsAccessKey() {
                 return awsAccessKey;
             }
     
    -        public String getAwsSecretKey() {
    +        public Secret getAwsSecretKey() {
                 return awsSecretKey;
             }
     
    @@ -333,7 +350,7 @@ public void setAwsAccessKey(String awsAccessKey) {
                 this.awsAccessKey = awsAccessKey;
             }
     
    -        public void setAwsSecretKey(String awsSecretKey) {
    +        public void setAwsSecretKey(Secret awsSecretKey) {
                 this.awsSecretKey = awsSecretKey;
             }
     
    
  • src/main/resources/index.jelly+1 0 modified
    @@ -1,3 +1,4 @@
    +<?jelly escape-by-default='true'?>
     <div>
       Send build notifications to an Amazon SNS Topic
     </div>
    
  • src/main/resources/org/jenkinsci/plugins/snsnotify/AmazonSNSNotifier/config.jelly+1 0 modified
    @@ -1,3 +1,4 @@
    +<?jelly escape-by-default='true'?>
     <j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
     
       <f:entry title="Topic ARN (overrides global default)" field="projectTopicArn">
    
  • src/main/resources/org/jenkinsci/plugins/snsnotify/AmazonSNSNotifier/global.jelly+8 7 modified
    @@ -1,3 +1,4 @@
    +<?jelly escape-by-default='true'?>
     <j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
         <f:section title="Amazon SNS Notification">
     
    @@ -6,55 +7,55 @@
                 help="/plugin/snsnotify/help-awsAccessKey.html"
                 field="awsAccessKey">
     
    -            <f:textbox name="snsnotify.awsAccessKey" />
    +            <f:textbox />
             </f:entry>
     
             <f:entry 
                 title="AWS Secret Key" 
                 help="/plugin/snsnotify/help-awsSecretKey.html"
                 field="awsSecretKey">
     
    -            <f:password name="snsnotify.awsSecretKey" />
    +            <f:password />
             </f:entry>
     
             <f:entry 
                 title="Use Local Credentials" 
                 help="/plugin/snsnotify/help-defaultCredential.html"
                 field="defaultLocalCredential">
     
    -            <f:booleanRadio name="snsnotify.defaultLocalCredential" />
    +            <f:booleanRadio />
             </f:entry>
     
             <f:entry 
                 title="Default notification topic ARN" 
                 help="/plugin/snsnotify/help-defaultTopicArn.html"
                 field="defaultTopicArn">
     
    -            <f:textbox name="snsnotify.defaultTopicArn" />
    +            <f:textbox />
             </f:entry>
     
             <f:entry 
                 title="Default message (default: {BUILD_URL})" 
                 help="/plugin/snsnotify/help-defaultMessageTemplate.html"
                 field="defaultMessageTemplate">
     
    -            <f:textbox name="snsnotify.defaultMessageTemplate" />
    +            <f:textbox />
             </f:entry>
     
             <f:entry
                 title="Send notification also on start of build?"
                 help="/plugin/snsnotify/help-defaultSendNotificationOnStart.html"
                 field="defaultSendNotificationOnStart">
     
    -            <f:booleanRadio name="snsnotify.defaultSendNotificationOnStart" />
    +            <f:booleanRadio />
             </f:entry>
     
             <f:entry 
                 title="Send notifications on every build?"
                 help="/plugin/snsnotify/help-defaultNotifyOnConsecutiveSuccesses.html"
                 field="defaultNotifyOnConsecutiveSuccesses">
     
    -            <f:booleanRadio name="snsnotify.defaultNotifyOnConsecutiveSuccesses" />
    +            <f:booleanRadio />
             </f:entry>
         </f:section>
     </j:jelly>
    

Vulnerability mechanics

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

References

6

News mentions

0

No linked articles in our index yet.