Skip to content

Commit 6b7cd22

Browse files
committed
[SECURITY-2185]
1 parent ae7eb39 commit 6b7cd22

File tree

13 files changed

+344
-2
lines changed

13 files changed

+344
-2
lines changed
Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
package hudson.plugins.parameterizedtrigger;
22

33
import hudson.EnvVars;
4+
import hudson.diagnosis.OldDataMonitor;
45
import hudson.model.InvisibleAction;
6+
import hudson.model.Run;
7+
import jenkins.model.RunAction2;
8+
9+
import java.util.Collections;
510

611
/**
712
* @author <a href="mailto:[email protected]">Nicolas De Loof</a>
813
*/
9-
public class CapturedEnvironmentAction extends InvisibleAction {
14+
public class CapturedEnvironmentAction extends InvisibleAction implements RunAction2 {
1015

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

1319
public CapturedEnvironmentAction(EnvVars env) {
1420
this.env = env;
@@ -17,4 +23,18 @@ public CapturedEnvironmentAction(EnvVars env) {
1723
public EnvVars getCapturedEnvironment() {
1824
return env;
1925
}
26+
27+
@Override
28+
public void onAttached(final Run<?, ?> r) {
29+
//noop
30+
}
31+
32+
@Override
33+
public void onLoad(final Run<?, ?> r) {
34+
if (env != null) {
35+
OldDataMonitor.report(r, Collections.singletonList(new AssertionError(OLD_DATA_MESSAGE)));
36+
}
37+
//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.
38+
env = new EnvVars();
39+
}
2040
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package hudson.plugins.parameterizedtrigger;
2+
3+
import hudson.ExtensionList;
4+
import hudson.FilePath;
5+
import hudson.diagnosis.OldDataMonitor;
6+
import hudson.model.FreeStyleBuild;
7+
import hudson.model.FreeStyleProject;
8+
import hudson.model.Saveable;
9+
import org.hamcrest.Description;
10+
import org.hamcrest.Matcher;
11+
import org.hamcrest.TypeSafeMatcher;
12+
import org.junit.Rule;
13+
import org.junit.Test;
14+
import org.jvnet.hudson.test.Issue;
15+
import org.jvnet.hudson.test.JenkinsSessionRule;
16+
17+
import java.io.File;
18+
import java.net.URL;
19+
import java.util.Map;
20+
21+
import static org.hamcrest.MatcherAssert.assertThat;
22+
import static org.hamcrest.Matchers.anEmptyMap;
23+
import static org.hamcrest.Matchers.containsString;
24+
import static org.hamcrest.Matchers.sameInstance;
25+
import static org.hamcrest.collection.IsMapContaining.hasEntry;
26+
import static org.hamcrest.core.IsNot.not;
27+
import static org.junit.Assert.assertEquals;
28+
import static org.junit.Assert.assertFalse;
29+
import static org.junit.Assert.assertNotNull;
30+
import static org.junit.Assert.assertTrue;
31+
import static org.junit.Assert.fail;
32+
33+
public class CapturedEnvironmentActionTest {
34+
35+
@Rule
36+
public JenkinsSessionRule j = new JenkinsSessionRule();
37+
38+
@Test
39+
@Issue("SECURITY-2185") //@LocalData
40+
public void onLoad() throws Throwable {
41+
j.then(r -> {
42+
final URL url = CapturedEnvironmentActionTest.class.getResource("/hudson/plugins/parameterizedtrigger/CapturedEnvironmentActionTest/onLoad");
43+
if (url == null) {
44+
fail("No test resources found!");
45+
}
46+
if (!url.getProtocol().equals("file"))
47+
throw new AssertionError("Test data is not available in the file system: " + url);
48+
File home = new File(url.toURI());
49+
System.err.println("Loading $JENKINS_HOME from " + home);
50+
new FilePath(home).copyRecursiveTo("**/*", r.jenkins.getRootPath());
51+
});
52+
j.then(r -> {
53+
final OldDataMonitor monitor = ExtensionList.lookupSingleton(OldDataMonitor.class);
54+
final FreeStyleProject triggering = r.jenkins.getItem("triggering", r.jenkins, FreeStyleProject.class);
55+
final FreeStyleBuild build = triggering.getLastBuild();
56+
57+
assertTrue("OldDataMonitor should be active.", monitor.isActivated());
58+
Map<Saveable, OldDataMonitor.VersionRange> data = monitor.getData();
59+
assertThat(data,
60+
hasEntry(sameInstance(build),
61+
new HasExtra(containsString("AssertionError: " + CapturedEnvironmentAction.OLD_DATA_MESSAGE))));
62+
63+
build.save();
64+
data = monitor.getData();
65+
assertThat(data, anEmptyMap());
66+
});
67+
j.then(r -> {
68+
final OldDataMonitor monitor = ExtensionList.lookupSingleton(OldDataMonitor.class);
69+
final FreeStyleProject triggering = r.jenkins.getItem("triggering", r.jenkins, FreeStyleProject.class);
70+
71+
assertFalse("OldDataMonitor should not be active.", monitor.isActivated());
72+
73+
FreeStyleBuild build = triggering.getLastBuild();
74+
assertNotNull(build);
75+
assertEquals(1, build.getNumber());
76+
CapturedEnvironmentAction action = build.getAction(CapturedEnvironmentAction.class);
77+
assertNotNull(action);
78+
assertThat(action.getCapturedEnvironment(), anEmptyMap());
79+
80+
r.buildAndAssertSuccess(triggering);
81+
r.waitUntilNoActivity();
82+
83+
build = triggering.getLastBuild();
84+
assertNotNull(build);
85+
assertEquals(2, build.getNumber());
86+
action = build.getAction(CapturedEnvironmentAction.class);
87+
assertNotNull(action);
88+
assertThat(action.getCapturedEnvironment(), not(anEmptyMap()));
89+
});
90+
j.then(r -> {
91+
final OldDataMonitor monitor = ExtensionList.lookupSingleton(OldDataMonitor.class);
92+
final FreeStyleProject triggering = r.jenkins.getItem("triggering", r.jenkins, FreeStyleProject.class);
93+
94+
assertFalse("OldDataMonitor should not be active.", monitor.isActivated());
95+
96+
FreeStyleBuild build = triggering.getLastBuild();
97+
assertNotNull(build);
98+
assertEquals(2, build.getNumber());
99+
CapturedEnvironmentAction action = build.getAction(CapturedEnvironmentAction.class);
100+
assertNotNull(action);
101+
assertThat(action.getCapturedEnvironment(), anEmptyMap());
102+
});
103+
}
104+
105+
private static class HasExtra extends TypeSafeMatcher<OldDataMonitor.VersionRange> {
106+
private final Matcher<? super String> valueMatcher;
107+
108+
private HasExtra(final Matcher<? super String> valueMatcher) {
109+
this.valueMatcher = valueMatcher;
110+
}
111+
112+
@Override
113+
protected boolean matchesSafely(final OldDataMonitor.VersionRange item) {
114+
return valueMatcher.matches(item.extra);
115+
}
116+
117+
@Override
118+
public void describeTo(final Description description) {
119+
description.appendText(" a VersionRange with extra ").appendDescriptionOf(valueMatcher);
120+
}
121+
122+
@Override
123+
protected void describeMismatchSafely(final OldDataMonitor.VersionRange item, final Description mismatchDescription) {
124+
mismatchDescription.appendText(" extra was ");
125+
valueMatcher.describeMismatch(item, mismatchDescription);
126+
}
127+
}
128+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?xml version='1.1' encoding='UTF-8'?>
2+
<build>
3+
<actions>
4+
<hudson.model.ParametersAction>
5+
<safeParameters class="sorted-set"/>
6+
<parameters>
7+
<hudson.model.BooleanParameterValue>
8+
<name>ok</name>
9+
<value>false</value>
10+
</hudson.model.BooleanParameterValue>
11+
</parameters>
12+
<parameterDefinitionNames>
13+
<string>ok</string>
14+
</parameterDefinitionNames>
15+
</hudson.model.ParametersAction>
16+
<hudson.model.CauseAction>
17+
<causeBag class="linked-hash-map">
18+
<entry>
19+
<hudson.model.Cause_-UpstreamCause>
20+
<upstreamProject>triggering</upstreamProject>
21+
<upstreamUrl>job/triggering/</upstreamUrl>
22+
<upstreamBuild>1</upstreamBuild>
23+
<upstreamCauses>
24+
<hudson.model.Cause_-UserIdCause/>
25+
</upstreamCauses>
26+
</hudson.model.Cause_-UpstreamCause>
27+
<int>1</int>
28+
</entry>
29+
</causeBag>
30+
</hudson.model.CauseAction>
31+
</actions>
32+
<queueId>4</queueId>
33+
<timestamp>1646074593325</timestamp>
34+
<startTime>1646074593336</startTime>
35+
<result>SUCCESS</result>
36+
<duration>64</duration>
37+
<charset>UTF-8</charset>
38+
<keepLog>false</keepLog>
39+
<builtOn></builtOn>
40+
<workspace>work/workspace/tobetriggered</workspace>
41+
<hudsonVersion>2.270</hudsonVersion>
42+
<scm class="hudson.scm.NullChangeLogParser"/>
43+
<culprits class="com.google.common.collect.EmptyImmutableSortedSet"/>
44+
</build>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<log/>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
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
2+
originally caused by:
3+
Started by user unknown or anonymous
4+
Running as SYSTEM
5+
Building in workspace work/workspace/tobetriggered
6+
[tobetriggered] $ /bin/sh -xe /tmp/jenkins6745008012408524781.sh
7+
+ echo warning
8+
warning
9+
Finished: SUCCESS
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?xml version='1.1' encoding='UTF-8'?>
2+
<project>
3+
<actions/>
4+
<description></description>
5+
<keepDependencies>false</keepDependencies>
6+
<properties>
7+
<hudson.model.ParametersDefinitionProperty>
8+
<parameterDefinitions>
9+
<hudson.model.BooleanParameterDefinition>
10+
<name>ok</name>
11+
<description>Are you OK?</description>
12+
<defaultValue>true</defaultValue>
13+
</hudson.model.BooleanParameterDefinition>
14+
</parameterDefinitions>
15+
</hudson.model.ParametersDefinitionProperty>
16+
</properties>
17+
<scm class="hudson.scm.NullSCM"/>
18+
<canRoam>true</canRoam>
19+
<disabled>false</disabled>
20+
<blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
21+
<blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
22+
<triggers/>
23+
<concurrentBuild>false</concurrentBuild>
24+
<builders>
25+
<hudson.tasks.Shell>
26+
<command>echo warning</command>
27+
<configuredLocalRules/>
28+
</hudson.tasks.Shell>
29+
</builders>
30+
<publishers/>
31+
<buildWrappers/>
32+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?xml version='1.1' encoding='UTF-8'?>
2+
<build>
3+
<actions>
4+
<hudson.model.CauseAction>
5+
<causeBag class="linked-hash-map">
6+
<entry>
7+
<hudson.model.Cause_-UserIdCause/>
8+
<int>1</int>
9+
</entry>
10+
</causeBag>
11+
</hudson.model.CauseAction>
12+
<hudson.plugins.parameterizedtrigger.CapturedEnvironmentAction plugin="[email protected]">
13+
<env serialization="custom">
14+
<unserializable-parents/>
15+
<tree-map>
16+
<default>
17+
<comparator class="hudson.util.CaseInsensitiveComparator"/>
18+
</default>
19+
<int>4</int>
20+
<string>BUILD_DISPLAY_NAME</string>
21+
<string>#2</string>
22+
<string>BUILD_ID</string>
23+
<string>2</string>
24+
<string>BUILD_NUMBER</string>
25+
<string>1</string>
26+
<string>BUILD_TAG</string>
27+
<string>jenkins-triggering-2</string>
28+
</tree-map>
29+
<hudson.EnvVars>
30+
<default>
31+
<platform>UNIX</platform>
32+
</default>
33+
</hudson.EnvVars>
34+
</env>
35+
</hudson.plugins.parameterizedtrigger.CapturedEnvironmentAction>
36+
</actions>
37+
<queueId>3</queueId>
38+
<timestamp>1646074584286</timestamp>
39+
<startTime>1646074584297</startTime>
40+
<result>SUCCESS</result>
41+
<duration>117</duration>
42+
<charset>UTF-8</charset>
43+
<keepLog>false</keepLog>
44+
<builtOn></builtOn>
45+
<workspace>work/workspace/triggering</workspace>
46+
<hudsonVersion>2.270</hudsonVersion>
47+
<scm class="hudson.scm.NullChangeLogParser"/>
48+
<culprits class="com.google.common.collect.EmptyImmutableSortedSet"/>
49+
</build>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<log/>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Started by user unknown or anonymous
2+
Running as SYSTEM
3+
Building in workspace work/workspace/triggering
4+
[triggering] $ /bin/sh -xe /tmp/jenkins6322047612148674788.sh
5+
+ echo hello world
6+
hello world
7+
Triggering a new build of ha:////4GiHzYchwi/IfoIgwGyntRMZkxF7TZatrqlGUxMVSCGyAAAAnh+LCAAAAAAAAP9b85aBtbiIQTGjNKU4P08vOT+vOD8nVc83PyU1x6OyILUoJzMv2y+/JJUBAhiZGBgqihhk0NSjKDWzXb3RdlLBUSYGJk8GtpzUvPSSDB8G5tKinBIGIZ+sxLJE/ZzEvHT94JKizLx0a6BxUmjGOUNodHsLgAzeEgZh/az8JP2S/KRUoAHp6alFqSn6ALQLPErIAAAAtobetriggered
8+
Finished: SUCCESS

0 commit comments

Comments
 (0)