<classpathentry kind="lib" path="ext/commons-pool2-2.0.jar" sourcepath="ext/src/commons-pool2-2.0.jar" />
<classpathentry kind="lib" path="ext/pf4j-0.8.0.jar" sourcepath="ext/src/pf4j-0.8.0.jar" />
<classpathentry kind="lib" path="ext/tika-core-1.5.jar" sourcepath="ext/src/tika-core-1.5.jar" />
+ <classpathentry kind="lib" path="ext/jsoup-1.7.3.jar" sourcepath="ext/src/jsoup-1.7.3.jar" />
<classpathentry kind="lib" path="ext/junit-4.11.jar" sourcepath="ext/src/junit-4.11.jar" />
<classpathentry kind="lib" path="ext/hamcrest-core-1.3.jar" sourcepath="ext/src/hamcrest-core-1.3.jar" />
<classpathentry kind="lib" path="ext/selenium-java-2.28.0.jar" sourcepath="ext/src/selenium-java-2.28.0.jar" />
- compile 'redis.clients:jedis:2.3.1' :war
- compile 'ro.fortsoft.pf4j:pf4j:0.8.0' :war
- compile 'org.apache.tika:tika-core:1.5' :war
+- compile 'org.jsoup:jsoup:1.7.3' :war
- test 'junit'
# Dependencies for Selenium web page testing
- test 'org.seleniumhq.selenium:selenium-java:${selenium.version}' @jar
</SOURCES>
</library>
</orderEntry>
+ <orderEntry type="module-library">
+ <library name="jsoup-1.7.3.jar">
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/ext/jsoup-1.7.3.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/ext/src/jsoup-1.7.3.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
<orderEntry type="module-library" scope="TEST">
<library name="junit-4.11.jar">
<CLASSES>
import com.gitblit.transport.ssh.IPublicKeyManager;
import com.gitblit.transport.ssh.MemoryKeyManager;
import com.gitblit.transport.ssh.NullKeyManager;
+import com.gitblit.utils.JSoupXssFilter;
import com.gitblit.utils.StringUtils;
+import com.gitblit.utils.XssFilter;
import com.gitblit.wicket.GitBlitWebApp;
import dagger.Module;
library = true,
injects = {
IStoredSettings.class,
+ XssFilter.class,
// core managers
IRuntimeManager.class,
return new FileSettings();
}
- @Provides @Singleton IRuntimeManager provideRuntimeManager(IStoredSettings settings) {
- return new RuntimeManager(settings);
+ @Provides @Singleton XssFilter provideXssFilter() {
+ return new JSoupXssFilter();
+ }
+
+ @Provides @Singleton IRuntimeManager provideRuntimeManager(IStoredSettings settings, XssFilter xssFilter) {
+ return new RuntimeManager(settings, xssFilter);
}
@Provides @Singleton IPluginManager providePluginManager(IRuntimeManager runtimeManager) {
import com.gitblit.service.FederationPullService;\r
import com.gitblit.utils.FederationUtils;\r
import com.gitblit.utils.StringUtils;\r
+import com.gitblit.utils.XssFilter;\r
+import com.gitblit.utils.XssFilter.AllowXssFilter;\r
\r
/**\r
* Command-line client to pull federated Gitblit repositories.\r
}\r
\r
// configure the Gitblit singleton for minimal, non-server operation\r
- RuntimeManager runtime = new RuntimeManager(settings, baseFolder).start();\r
+ XssFilter xssFilter = new AllowXssFilter();\r
+ RuntimeManager runtime = new RuntimeManager(settings, xssFilter, baseFolder).start();\r
NoopNotificationManager notifications = new NoopNotificationManager().start();\r
UserManager users = new UserManager(runtime, null).start();\r
RepositoryManager repositories = new RepositoryManager(runtime, null, users).start();\r
import com.gitblit.tickets.ITicketService;
import com.gitblit.tickets.RedisTicketService;
import com.gitblit.utils.StringUtils;
+import com.gitblit.utils.XssFilter;
+import com.gitblit.utils.XssFilter.AllowXssFilter;
/**
* A command-line tool to move all tickets from one ticket service to another.
settings.overrideSetting(Keys.web.activityCacheDays, 0);
settings.overrideSetting(ITicketService.SETTING_UPDATE_DIFFSTATS, false);
- IRuntimeManager runtimeManager = new RuntimeManager(settings, baseFolder).start();
+ XssFilter xssFilter = new AllowXssFilter();
+ IRuntimeManager runtimeManager = new RuntimeManager(settings, xssFilter, baseFolder).start();
IRepositoryManager repositoryManager = new RepositoryManager(runtimeManager, null, null).start();
String inputServiceName = settings.getString(Keys.tickets.service, BranchTicketService.class.getSimpleName());
import com.gitblit.tickets.ITicketService;
import com.gitblit.tickets.RedisTicketService;
import com.gitblit.utils.StringUtils;
+import com.gitblit.utils.XssFilter;
+import com.gitblit.utils.XssFilter.AllowXssFilter;
/**
* A command-line tool to reindex all tickets in all repositories when the
settings.overrideSetting(Keys.git.enableMirroring, false);
settings.overrideSetting(Keys.web.activityCacheDays, 0);
- IRuntimeManager runtimeManager = new RuntimeManager(settings, baseFolder).start();
+ XssFilter xssFilter = new AllowXssFilter();
+ IRuntimeManager runtimeManager = new RuntimeManager(settings, xssFilter, baseFolder).start();
IRepositoryManager repositoryManager = new RepositoryManager(runtimeManager, null, null).start();
String serviceName = settings.getString(Keys.tickets.service, BranchTicketService.class.getSimpleName());
import com.gitblit.transport.ssh.IPublicKeyManager;
import com.gitblit.transport.ssh.SshKey;
import com.gitblit.utils.ArrayUtils;
+import com.gitblit.utils.XssFilter;
import com.gitblit.utils.HttpUtils;
import com.gitblit.utils.JsonUtils;
import com.gitblit.utils.ObjectCache;
return runtimeManager.getStatus();
}
+ @Override
+ public XssFilter getXssFilter() {
+ return runtimeManager.getXssFilter();
+ }
+
/*
* NOTIFICATION MANAGER
*/
import com.gitblit.IStoredSettings;
import com.gitblit.models.ServerSettings;
import com.gitblit.models.ServerStatus;
+import com.gitblit.utils.XssFilter;
public interface IRuntimeManager extends IManager {
* @since 1.4.0
*/
boolean updateSettings(Map<String, String> updatedSettings);
+
+ /**
+ * Returns the HTML sanitizer used to clean user content.
+ *
+ * @return the HTML sanitizer
+ */
+ XssFilter getXssFilter();
}
\ No newline at end of file
import com.gitblit.models.ServerStatus;
import com.gitblit.models.SettingModel;
import com.gitblit.utils.StringUtils;
+import com.gitblit.utils.XssFilter;
public class RuntimeManager implements IRuntimeManager {
private final IStoredSettings settings;
+ private final XssFilter xssFilter;
+
private final ServerStatus serverStatus;
private final ServerSettings settingsModel;
private TimeZone timezone;
- public RuntimeManager(IStoredSettings settings) {
- this(settings, null);
+ public RuntimeManager(IStoredSettings settings, XssFilter xssFilter) {
+ this(settings, xssFilter, null);
}
- public RuntimeManager(IStoredSettings settings, File baseFolder) {
+ public RuntimeManager(IStoredSettings settings, XssFilter xssFilter, File baseFolder) {
this.settings = settings;
this.settingsModel = new ServerSettings();
this.serverStatus = new ServerStatus();
+ this.xssFilter = xssFilter;
this.baseFolder = baseFolder == null ? new File("") : baseFolder;
}
serverStatus.heapFree = Runtime.getRuntime().freeMemory();
return serverStatus;
}
+
+ /**
+ * Returns the XSS filter.
+ *
+ * @return the XSS filter
+ */
+ @Override
+ public XssFilter getXssFilter() {
+ return xssFilter;
+ }
+
}
--- /dev/null
+/*
+ * Copyright 2014 gitblit.com.
+ *
+ * Licensed 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 com.gitblit.utils;
+
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.safety.Cleaner;
+import org.jsoup.safety.Whitelist;
+
+/**
+ * Implementation of an XSS filter based on JSoup.
+ *
+ * @author James Moger
+ *
+ */
+public class JSoupXssFilter implements XssFilter {
+
+ private final Cleaner none;
+
+ private final Cleaner relaxed;
+
+ public JSoupXssFilter() {
+ none = new Cleaner(Whitelist.none());
+ relaxed = new Cleaner(getRelaxedWhiteList());
+ }
+
+ @Override
+ public String none(String input) {
+ return clean(input, none);
+ }
+
+ @Override
+ public String relaxed(String input) {
+ return clean(input, relaxed);
+ }
+
+ protected String clean(String input, Cleaner cleaner) {
+ Document unsafe = Jsoup.parse(input);
+ Document safe = cleaner.clean(unsafe);
+ return safe.body().html();
+ }
+
+ /**
+ * Builds & returns a loose HTML whitelist similar to Github.
+ *
+ * https://github.com/github/markup/tree/master#html-sanitization
+ * @return a loose HTML whitelist
+ */
+ protected Whitelist getRelaxedWhiteList() {
+ return new Whitelist()
+ .addTags(
+ "a", "b", "blockquote", "br", "caption", "cite", "code", "col",
+ "colgroup", "dd", "del", "div", "dl", "dt", "em", "h1", "h2", "h3", "h4", "h5", "h6", "hr",
+ "i", "img", "ins", "kbd", "li", "ol", "p", "pre", "q", "samp", "small", "strike", "strong",
+ "sub", "sup", "table", "tbody", "td", "tfoot", "th", "thead", "tr", "tt", "u",
+ "ul", "var")
+
+ .addAttributes("a", "href", "title")
+ .addAttributes("blockquote", "cite")
+ .addAttributes("col", "span", "width")
+ .addAttributes("colgroup", "span", "width")
+ .addAttributes("img", "align", "alt", "height", "src", "title", "width")
+ .addAttributes("ol", "start", "type")
+ .addAttributes("q", "cite")
+ .addAttributes("table", "summary", "width")
+ .addAttributes("td", "abbr", "axis", "colspan", "rowspan", "width")
+ .addAttributes("th", "abbr", "axis", "colspan", "rowspan", "scope", "width")
+ .addAttributes("ul", "type")
+
+ .addEnforcedAttribute("a", "rel", "nofollow")
+ ;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright 2014 gitblit.com.
+ *
+ * Licensed 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 com.gitblit.utils;
+
+/**
+ * Defines the contract for an XSS filter implementation.
+ *
+ * @author James Moger
+ *
+ */
+public interface XssFilter {
+
+ /**
+ * Returns a filtered version of the input value that contains no html
+ * elements.
+ *
+ * @param input
+ * @return a plain text value
+ */
+ String none(String input);
+
+ /**
+ * Returns a filtered version of the input that contains structural html
+ * elements.
+ *
+ * @param input
+ * @return a filtered html value
+ */
+ String relaxed(String input);
+
+ /**
+ * A NOOP XSS filter.
+ *
+ * @author James Moger
+ *
+ */
+ public class AllowXssFilter implements XssFilter {
+
+ @Override
+ public String none(String input) {
+ return input;
+ }
+
+ @Override
+ public String relaxed(String input) {
+ return input;
+ }
+
+ }
+
+}
import com.gitblit.manager.IUserManager;
import com.gitblit.tickets.ITicketService;
import com.gitblit.transport.ssh.IPublicKeyManager;
+import com.gitblit.utils.XssFilter;
import com.gitblit.wicket.pages.ActivityPage;
import com.gitblit.wicket.pages.BlamePage;
import com.gitblit.wicket.pages.BlobDiffPage;
private final IStoredSettings settings;
+ private final XssFilter xssFilter;
+
private final IRuntimeManager runtimeManager;
private final IPluginManager pluginManager;
super();
this.settings = runtimeManager.getSettings();
+ this.xssFilter = runtimeManager.getXssFilter();
this.runtimeManager = runtimeManager;
this.pluginManager = pluginManager;
this.notificationManager = notificationManager;
return settings;
}
+ /* (non-Javadoc)
+ * @see com.gitblit.wicket.Webapp#xssFilter()
+ */
+ @Override
+ public XssFilter xssFilter() {
+ return xssFilter;
+ }
+
/* (non-Javadoc)
* @see com.gitblit.wicket.Webapp#isDebugMode()
*/
import com.gitblit.manager.IUserManager;
import com.gitblit.tickets.ITicketService;
import com.gitblit.transport.ssh.IPublicKeyManager;
+import com.gitblit.utils.XssFilter;
public interface GitblitWicketApp {
public abstract IStoredSettings settings();
+ public abstract XssFilter xssFilter();
+
/**
* Is Gitblit running in debug mode?
*
import com.gitblit.manager.UserManager;
import com.gitblit.models.UserModel;
import com.gitblit.tests.mock.MemorySettings;
+import com.gitblit.utils.XssFilter;
+import com.gitblit.utils.XssFilter.AllowXssFilter;
/**
* Class for testing local authentication.
}
IAuthenticationManager newAuthenticationManager() {
- RuntimeManager runtime = new RuntimeManager(getSettings(), GitBlitSuite.BASEFOLDER).start();
+ XssFilter xssFilter = new AllowXssFilter();
+ RuntimeManager runtime = new RuntimeManager(getSettings(), xssFilter, GitBlitSuite.BASEFOLDER).start();
users = new UserManager(runtime, null).start();
AuthenticationManager auth = new AuthenticationManager(runtime, users).start();
return auth;
import com.gitblit.models.RepositoryModel;
import com.gitblit.tickets.BranchTicketService;
import com.gitblit.tickets.ITicketService;
+import com.gitblit.utils.XssFilter;
+import com.gitblit.utils.XssFilter.AllowXssFilter;
/**
* Tests the branch ticket service.
protected ITicketService getService(boolean deleteAll) throws Exception {
IStoredSettings settings = getSettings(deleteAll);
-
- IRuntimeManager runtimeManager = new RuntimeManager(settings).start();
+ XssFilter xssFilter = new AllowXssFilter();
+ IRuntimeManager runtimeManager = new RuntimeManager(settings, xssFilter).start();
IPluginManager pluginManager = new PluginManager(runtimeManager).start();
INotificationManager notificationManager = new NotificationManager(settings).start();
IUserManager userManager = new UserManager(runtimeManager, pluginManager).start();
import com.gitblit.models.RepositoryModel;
import com.gitblit.tickets.FileTicketService;
import com.gitblit.tickets.ITicketService;
+import com.gitblit.utils.XssFilter;
+import com.gitblit.utils.XssFilter.AllowXssFilter;
/**
* Tests the file ticket service.
protected ITicketService getService(boolean deleteAll) throws Exception {
IStoredSettings settings = getSettings(deleteAll);
-
- IRuntimeManager runtimeManager = new RuntimeManager(settings).start();
+ XssFilter xssFilter = new AllowXssFilter();
+ IRuntimeManager runtimeManager = new RuntimeManager(settings, xssFilter).start();
IPluginManager pluginManager = new PluginManager(runtimeManager).start();
INotificationManager notificationManager = new NotificationManager(settings).start();
IUserManager userManager = new UserManager(runtimeManager, pluginManager).start();
import com.gitblit.manager.UserManager;
import com.gitblit.models.UserModel;
import com.gitblit.tests.mock.MemorySettings;
+import com.gitblit.utils.XssFilter;
+import com.gitblit.utils.XssFilter.AllowXssFilter;
/**
* Test the Htpasswd user service.
}
private HtpasswdAuthProvider newHtpasswdAuthentication(IStoredSettings settings) {
- RuntimeManager runtime = new RuntimeManager(settings, GitBlitSuite.BASEFOLDER).start();
+ XssFilter xssFilter = new AllowXssFilter();
+ RuntimeManager runtime = new RuntimeManager(settings, xssFilter, GitBlitSuite.BASEFOLDER).start();
UserManager users = new UserManager(runtime, null).start();
HtpasswdAuthProvider htpasswd = new HtpasswdAuthProvider();
htpasswd.setup(runtime, users);
}
private AuthenticationManager newAuthenticationManager(IStoredSettings settings) {
- RuntimeManager runtime = new RuntimeManager(settings, GitBlitSuite.BASEFOLDER).start();
+ XssFilter xssFilter = new AllowXssFilter();
+ RuntimeManager runtime = new RuntimeManager(settings, xssFilter, GitBlitSuite.BASEFOLDER).start();
UserManager users = new UserManager(runtime, null).start();
HtpasswdAuthProvider htpasswd = new HtpasswdAuthProvider();
htpasswd.setup(runtime, users);
import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
import com.gitblit.tests.mock.MemorySettings;
+import com.gitblit.utils.XssFilter;
+import com.gitblit.utils.XssFilter.AllowXssFilter;
import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
import com.unboundid.ldap.listener.InMemoryListenerConfig;
}
private LdapAuthProvider newLdapAuthentication(IStoredSettings settings) {
- RuntimeManager runtime = new RuntimeManager(settings, GitBlitSuite.BASEFOLDER).start();
+ XssFilter xssFilter = new AllowXssFilter();
+ RuntimeManager runtime = new RuntimeManager(settings, xssFilter, GitBlitSuite.BASEFOLDER).start();
userManager = new UserManager(runtime, null).start();
LdapAuthProvider ldap = new LdapAuthProvider();
ldap.setup(runtime, userManager);
}
private AuthenticationManager newAuthenticationManager(IStoredSettings settings) {
- RuntimeManager runtime = new RuntimeManager(settings, GitBlitSuite.BASEFOLDER).start();
+ XssFilter xssFilter = new AllowXssFilter();
+ RuntimeManager runtime = new RuntimeManager(settings, xssFilter, GitBlitSuite.BASEFOLDER).start();
AuthenticationManager auth = new AuthenticationManager(runtime, userManager);
auth.addAuthenticationProvider(newLdapAuthentication(settings));
return auth;
import com.gitblit.tests.mock.MemorySettings;\r
import com.gitblit.utils.FileUtils;\r
import com.gitblit.utils.JGitUtils;\r
+import com.gitblit.utils.XssFilter;\r
+import com.gitblit.utils.XssFilter.AllowXssFilter;\r
\r
/**\r
* Tests Lucene indexing and querying.\r
private LuceneService newLuceneExecutor() {\r
MemorySettings settings = new MemorySettings();\r
settings.put(Keys.git.repositoriesFolder, GitBlitSuite.REPOSITORIES);\r
- RuntimeManager runtime = new RuntimeManager(settings, GitBlitSuite.BASEFOLDER).start();\r
+ XssFilter xssFilter = new AllowXssFilter();\r
+ RuntimeManager runtime = new RuntimeManager(settings, xssFilter, GitBlitSuite.BASEFOLDER).start();\r
UserManager users = new UserManager(runtime, null).start();\r
RepositoryManager repos = new RepositoryManager(runtime, null, users);\r
return new LuceneService(settings, repos);\r
import com.gitblit.models.RepositoryModel;
import com.gitblit.tickets.ITicketService;
import com.gitblit.tickets.RedisTicketService;
+import com.gitblit.utils.XssFilter;
+import com.gitblit.utils.XssFilter.AllowXssFilter;
/**
* Tests the Redis ticket service.
protected ITicketService getService(boolean deleteAll) throws Exception {
IStoredSettings settings = getSettings(deleteAll);
-
- IRuntimeManager runtimeManager = new RuntimeManager(settings).start();
+ XssFilter xssFilter = new AllowXssFilter();
+ IRuntimeManager runtimeManager = new RuntimeManager(settings, xssFilter).start();
IPluginManager pluginManager = new PluginManager(runtimeManager).start();
INotificationManager notificationManager = new NotificationManager(settings).start();
IUserManager userManager = new UserManager(runtimeManager, pluginManager).start();
import com.gitblit.manager.UserManager;
import com.gitblit.models.UserModel;
import com.gitblit.tests.mock.MemorySettings;
+import com.gitblit.utils.XssFilter;
+import com.gitblit.utils.XssFilter.AllowXssFilter;
public class RedmineAuthenticationTest extends GitblitUnitTest {
}
RedmineAuthProvider newRedmineAuthentication(IStoredSettings settings) {
- RuntimeManager runtime = new RuntimeManager(settings, GitBlitSuite.BASEFOLDER).start();
+ XssFilter xssFilter = new AllowXssFilter();
+ RuntimeManager runtime = new RuntimeManager(settings, xssFilter, GitBlitSuite.BASEFOLDER).start();
UserManager users = new UserManager(runtime, null).start();
RedmineAuthProvider redmine = new RedmineAuthProvider();
redmine.setup(runtime, users);
}
AuthenticationManager newAuthenticationManager() {
- RuntimeManager runtime = new RuntimeManager(getSettings(), GitBlitSuite.BASEFOLDER).start();
+ XssFilter xssFilter = new AllowXssFilter();
+ RuntimeManager runtime = new RuntimeManager(getSettings(), xssFilter, GitBlitSuite.BASEFOLDER).start();
UserManager users = new UserManager(runtime, null).start();
RedmineAuthProvider redmine = new RedmineAuthProvider();
redmine.setup(runtime, users);
import com.gitblit.models.ServerSettings;
import com.gitblit.models.ServerStatus;
import com.gitblit.models.SettingModel;
+import com.gitblit.utils.XssFilter;
+import com.gitblit.utils.XssFilter.AllowXssFilter;
public class MockRuntimeManager implements IRuntimeManager {
return settings;
}
+ @Override
+ public XssFilter getXssFilter() {
+ return new AllowXssFilter();
+ }
+
@Override
public boolean updateSettings(Map<String, String> updatedSettings) {
return settings.saveSettings(updatedSettings);