Skip to content

Commit

Permalink
[SECURITY-2185]
Browse files Browse the repository at this point in the history
  • Loading branch information
rsandell committed Mar 8, 2022
1 parent eb2d407 commit b5ec2b4
Show file tree
Hide file tree
Showing 13 changed files with 344 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
package hudson.plugins.parameterizedtrigger;

import hudson.EnvVars;
import hudson.diagnosis.OldDataMonitor;
import hudson.model.InvisibleAction;
import hudson.model.Run;
import jenkins.model.RunAction2;

import java.util.Collections;

/**
* @author <a href="mailto:[email protected]">Nicolas De Loof</a>
*/
public class CapturedEnvironmentAction extends InvisibleAction {
public class CapturedEnvironmentAction extends InvisibleAction implements RunAction2 {

private final EnvVars env;
static final String OLD_DATA_MESSAGE = "The build.xml contains captured environment variables at the time of building which could contain sensitive data.";
private transient volatile EnvVars env;

public CapturedEnvironmentAction(EnvVars env) {
this.env = env;
Expand All @@ -17,4 +23,18 @@ public CapturedEnvironmentAction(EnvVars env) {
public EnvVars getCapturedEnvironment() {
return env;
}

@Override
public void onAttached(final Run<?, ?> r) {
//noop
}

@Override
public void onLoad(final Run<?, ?> r) {
if (env != null) {
OldDataMonitor.report(r, Collections.singletonList(new AssertionError(OLD_DATA_MESSAGE)));
}
//If it is not null then we loaded old data that needs to be cleaned, if it is null then it needs to be something.
env = new EnvVars();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package hudson.plugins.parameterizedtrigger;

import hudson.ExtensionList;
import hudson.FilePath;
import hudson.diagnosis.OldDataMonitor;
import hudson.model.FreeStyleBuild;
import hudson.model.FreeStyleProject;
import hudson.model.Saveable;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsSessionRule;

import java.io.File;
import java.net.URL;
import java.util.Map;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.anEmptyMap;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.sameInstance;
import static org.hamcrest.collection.IsMapContaining.hasEntry;
import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

public class CapturedEnvironmentActionTest {

@Rule
public JenkinsSessionRule j = new JenkinsSessionRule();

@Test
@Issue("SECURITY-2185") //@LocalData
public void onLoad() throws Throwable {
j.then(r -> {
final URL url = CapturedEnvironmentActionTest.class.getResource("/hudson/plugins/parameterizedtrigger/CapturedEnvironmentActionTest/onLoad");
if (url == null) {
fail("No test resources found!");
}
if (!url.getProtocol().equals("file"))
throw new AssertionError("Test data is not available in the file system: " + url);
File home = new File(url.toURI());
System.err.println("Loading $JENKINS_HOME from " + home);
new FilePath(home).copyRecursiveTo("**/*", r.jenkins.getRootPath());
});
j.then(r -> {
final OldDataMonitor monitor = ExtensionList.lookupSingleton(OldDataMonitor.class);
final FreeStyleProject triggering = r.jenkins.getItem("triggering", r.jenkins, FreeStyleProject.class);
final FreeStyleBuild build = triggering.getLastBuild();

assertTrue("OldDataMonitor should be active.", monitor.isActivated());
Map<Saveable, OldDataMonitor.VersionRange> data = monitor.getData();
assertThat(data,
hasEntry(sameInstance(build),
new HasExtra(containsString("AssertionError: " + CapturedEnvironmentAction.OLD_DATA_MESSAGE))));

build.save();
data = monitor.getData();
assertThat(data, anEmptyMap());
});
j.then(r -> {
final OldDataMonitor monitor = ExtensionList.lookupSingleton(OldDataMonitor.class);
final FreeStyleProject triggering = r.jenkins.getItem("triggering", r.jenkins, FreeStyleProject.class);

assertFalse("OldDataMonitor should not be active.", monitor.isActivated());

FreeStyleBuild build = triggering.getLastBuild();
assertNotNull(build);
assertEquals(1, build.getNumber());
CapturedEnvironmentAction action = build.getAction(CapturedEnvironmentAction.class);
assertNotNull(action);
assertThat(action.getCapturedEnvironment(), anEmptyMap());

r.buildAndAssertSuccess(triggering);
r.waitUntilNoActivity();

build = triggering.getLastBuild();
assertNotNull(build);
assertEquals(2, build.getNumber());
action = build.getAction(CapturedEnvironmentAction.class);
assertNotNull(action);
assertThat(action.getCapturedEnvironment(), not(anEmptyMap()));
});
j.then(r -> {
final OldDataMonitor monitor = ExtensionList.lookupSingleton(OldDataMonitor.class);
final FreeStyleProject triggering = r.jenkins.getItem("triggering", r.jenkins, FreeStyleProject.class);

assertFalse("OldDataMonitor should not be active.", monitor.isActivated());

FreeStyleBuild build = triggering.getLastBuild();
assertNotNull(build);
assertEquals(2, build.getNumber());
CapturedEnvironmentAction action = build.getAction(CapturedEnvironmentAction.class);
assertNotNull(action);
assertThat(action.getCapturedEnvironment(), anEmptyMap());
});
}

private static class HasExtra extends TypeSafeMatcher<OldDataMonitor.VersionRange> {
private final Matcher<? super String> valueMatcher;

private HasExtra(final Matcher<? super String> valueMatcher) {
this.valueMatcher = valueMatcher;
}

@Override
protected boolean matchesSafely(final OldDataMonitor.VersionRange item) {
return valueMatcher.matches(item.extra);
}

@Override
public void describeTo(final Description description) {
description.appendText(" a VersionRange with extra ").appendDescriptionOf(valueMatcher);
}

@Override
protected void describeMismatchSafely(final OldDataMonitor.VersionRange item, final Description mismatchDescription) {
mismatchDescription.appendText(" extra was ");
valueMatcher.describeMismatch(item, mismatchDescription);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?xml version='1.1' encoding='UTF-8'?>
<build>
<actions>
<hudson.model.ParametersAction>
<safeParameters class="sorted-set"/>
<parameters>
<hudson.model.BooleanParameterValue>
<name>ok</name>
<value>false</value>
</hudson.model.BooleanParameterValue>
</parameters>
<parameterDefinitionNames>
<string>ok</string>
</parameterDefinitionNames>
</hudson.model.ParametersAction>
<hudson.model.CauseAction>
<causeBag class="linked-hash-map">
<entry>
<hudson.model.Cause_-UpstreamCause>
<upstreamProject>triggering</upstreamProject>
<upstreamUrl>job/triggering/</upstreamUrl>
<upstreamBuild>1</upstreamBuild>
<upstreamCauses>
<hudson.model.Cause_-UserIdCause/>
</upstreamCauses>
</hudson.model.Cause_-UpstreamCause>
<int>1</int>
</entry>
</causeBag>
</hudson.model.CauseAction>
</actions>
<queueId>4</queueId>
<timestamp>1646074593325</timestamp>
<startTime>1646074593336</startTime>
<result>SUCCESS</result>
<duration>64</duration>
<charset>UTF-8</charset>
<keepLog>false</keepLog>
<builtOn></builtOn>
<workspace>work/workspace/tobetriggered</workspace>
<hudsonVersion>2.270</hudsonVersion>
<scm class="hudson.scm.NullChangeLogParser"/>
<culprits class="com.google.common.collect.EmptyImmutableSortedSet"/>
</build>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<log/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Started by upstream project "ha:////4GRnFg0qnrPw4M47q42/6Hn+zLu1JydjlwbdO4AqwQb+AAAAmR+LCAAAAAAAAP9b85aBtbiIQTGjNKU4P08vOT+vOD8nVc83PyU1x6OyILUoJzMv2y+/JJUBAhiZGBgqihhk0NSjKDWzXb3RdlLBUSYGJk8GtpzUvPSSDB8G5tKinBIGIZ+sxLJE/ZzEvHT94JKizLx0a6BxUmjGOUNodHsLgAyuEgYB/az8JH2g5vT0VJAJ+gCV2UdCxQAAAA==triggering" build number ha:////4D+Ec5DGhEbnE6Cp3rmOis4sanYY4ucMjj06VZLZDDfkAAAAmR+LCAAAAAAAAP9b85aBtbiIQTGjNKU4P08vOT+vOD8nVc83PyU1x6OyILUoJzMv2y+/JJUBAhiZGBgqihhk0NSjKDWzXb3RdlLBUSYGJk8GtpzUvPSSDB8G5tKinBIGIZ+sxLJE/ZzEvHT94JKizLx0a6BxUmjGOUNodHsLQIwSBkH9rPwkfaDm9PRUkAn6RgBro0wrxgAAAA==2
originally caused by:
Started by user unknown or anonymous
Running as SYSTEM
Building in workspace work/workspace/tobetriggered
[tobetriggered] $ /bin/sh -xe /tmp/jenkins6745008012408524781.sh
+ echo warning
warning
Finished: SUCCESS
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version='1.1' encoding='UTF-8'?>
<project>
<actions/>
<description></description>
<keepDependencies>false</keepDependencies>
<properties>
<hudson.model.ParametersDefinitionProperty>
<parameterDefinitions>
<hudson.model.BooleanParameterDefinition>
<name>ok</name>
<description>Are you OK?</description>
<defaultValue>true</defaultValue>
</hudson.model.BooleanParameterDefinition>
</parameterDefinitions>
</hudson.model.ParametersDefinitionProperty>
</properties>
<scm class="hudson.scm.NullSCM"/>
<canRoam>true</canRoam>
<disabled>false</disabled>
<blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
<blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
<triggers/>
<concurrentBuild>false</concurrentBuild>
<builders>
<hudson.tasks.Shell>
<command>echo warning</command>
<configuredLocalRules/>
</hudson.tasks.Shell>
</builders>
<publishers/>
<buildWrappers/>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?xml version='1.1' encoding='UTF-8'?>
<build>
<actions>
<hudson.model.CauseAction>
<causeBag class="linked-hash-map">
<entry>
<hudson.model.Cause_-UserIdCause/>
<int>1</int>
</entry>
</causeBag>
</hudson.model.CauseAction>
<hudson.plugins.parameterizedtrigger.CapturedEnvironmentAction plugin="[email protected]">
<env serialization="custom">
<unserializable-parents/>
<tree-map>
<default>
<comparator class="hudson.util.CaseInsensitiveComparator"/>
</default>
<int>4</int>
<string>BUILD_DISPLAY_NAME</string>
<string>#2</string>
<string>BUILD_ID</string>
<string>2</string>
<string>BUILD_NUMBER</string>
<string>1</string>
<string>BUILD_TAG</string>
<string>jenkins-triggering-2</string>
</tree-map>
<hudson.EnvVars>
<default>
<platform>UNIX</platform>
</default>
</hudson.EnvVars>
</env>
</hudson.plugins.parameterizedtrigger.CapturedEnvironmentAction>
</actions>
<queueId>3</queueId>
<timestamp>1646074584286</timestamp>
<startTime>1646074584297</startTime>
<result>SUCCESS</result>
<duration>117</duration>
<charset>UTF-8</charset>
<keepLog>false</keepLog>
<builtOn></builtOn>
<workspace>work/workspace/triggering</workspace>
<hudsonVersion>2.270</hudsonVersion>
<scm class="hudson.scm.NullChangeLogParser"/>
<culprits class="com.google.common.collect.EmptyImmutableSortedSet"/>
</build>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<log/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Started by user unknown or anonymous
Running as SYSTEM
Building in workspace work/workspace/triggering
[triggering] $ /bin/sh -xe /tmp/jenkins6322047612148674788.sh
+ echo hello world
hello world
Triggering a new build of ha:////4GiHzYchwi/IfoIgwGyntRMZkxF7TZatrqlGUxMVSCGyAAAAnh+LCAAAAAAAAP9b85aBtbiIQTGjNKU4P08vOT+vOD8nVc83PyU1x6OyILUoJzMv2y+/JJUBAhiZGBgqihhk0NSjKDWzXb3RdlLBUSYGJk8GtpzUvPSSDB8G5tKinBIGIZ+sxLJE/ZzEvHT94JKizLx0a6BxUmjGOUNodHsLgAzeEgZh/az8JP2S/KRUoAHp6alFqSn6ALQLPErIAAAAtobetriggered
Finished: SUCCESS
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?xml version='1.1' encoding='UTF-8'?>
<project>
<actions/>
<description></description>
<keepDependencies>false</keepDependencies>
<properties/>
<scm class="hudson.scm.NullSCM"/>
<canRoam>true</canRoam>
<disabled>false</disabled>
<blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
<blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
<triggers/>
<concurrentBuild>false</concurrentBuild>
<builders>
<hudson.tasks.Shell>
<command>echo hello world</command>
<configuredLocalRules/>
</hudson.tasks.Shell>
</builders>
<publishers>
<hudson.plugins.parameterizedtrigger.BuildTrigger plugin="[email protected]">
<configs>
<hudson.plugins.parameterizedtrigger.BuildTriggerConfig>
<configs>
<hudson.plugins.parameterizedtrigger.BooleanParameters>
<configs>
<hudson.plugins.parameterizedtrigger.BooleanParameterConfig>
<name>ok</name>
<value>false</value>
</hudson.plugins.parameterizedtrigger.BooleanParameterConfig>
</configs>
</hudson.plugins.parameterizedtrigger.BooleanParameters>
</configs>
<projects>tobetriggered, </projects>
<condition>ALWAYS</condition>
<triggerWithNoParameters>false</triggerWithNoParameters>
<triggerFromChildProjects>false</triggerFromChildProjects>
</hudson.plugins.parameterizedtrigger.BuildTriggerConfig>
</configs>
</hudson.plugins.parameterizedtrigger.BuildTrigger>
</publishers>
<buildWrappers/>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version='1.1' encoding='UTF-8'?>
<hudson.model.Queue_-State>
<counter>4</counter>
<items/>
</hudson.model.Queue_-State>

0 comments on commit b5ec2b4

Please sign in to comment.