diff --git a/src/main/java/org/nrg/xapi/rest/settings/SiteConfigApi.java b/src/main/java/org/nrg/xapi/rest/settings/SiteConfigApi.java
index 1b74e2faa9a1078df4dc5ceae2f1806af52bfe8c..d2f839d5a876efda6046f1a48015db8703f93fff 100644
--- a/src/main/java/org/nrg/xapi/rest/settings/SiteConfigApi.java
+++ b/src/main/java/org/nrg/xapi/rest/settings/SiteConfigApi.java
@@ -46,7 +46,7 @@ public class SiteConfigApi extends AbstractXapiRestController {
     public void checkForFoundPreferences() {
         if (!_appInfo.isInitialized()) {
             Map<String, String> tempPrefs = _appInfo.getFoundPreferences();
-            if(tempPrefs!=null){
+            if (tempPrefs != null) {
                 _found.putAll(tempPrefs);
             }
             if (_found.size() > 0) {
@@ -56,12 +56,17 @@ public class SiteConfigApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Returns the full map of site configuration properties.", notes = "Complex objects may be returned as encapsulated JSON strings.", response = String.class, responseContainer = "Map")
-    @ApiResponses({@ApiResponse(code = 200, message = "Site configuration properties successfully retrieved."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to set site configuration properties."), @ApiResponse(code = 500, message = "Unexpected error")})
+    @ApiResponses({@ApiResponse(code = 200, message = "Site configuration properties successfully retrieved."),
+                   @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
+                   @ApiResponse(code = 403, message = "Not authorized to set site configuration properties."),
+                   @ApiResponse(code = 500, message = "Unexpected error")})
     @RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET)
     public ResponseEntity<Map<String, Object>> getSiteConfigProperties(final HttpServletRequest request) {
-        final HttpStatus status = isPermitted();
-        if (status != null) {
-            return new ResponseEntity<>(status);
+        if (!_appInfo.isOpenUrlRequest(request)) {
+            final HttpStatus status = isPermitted(request, _appInfo.getOpenUrls().values());
+            if (status != null) {
+                return new ResponseEntity<>(status);
+            }
         }
         final String username = getSessionUser().getUsername();
         if (_log.isDebugEnabled()) {
@@ -83,7 +88,10 @@ public class SiteConfigApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Sets a map of site configuration properties.", notes = "Sets the site configuration properties specified in the map.", response = Void.class)
-    @ApiResponses({@ApiResponse(code = 200, message = "Site configuration properties successfully set."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to set site configuration properties."), @ApiResponse(code = 500, message = "Unexpected error")})
+    @ApiResponses({@ApiResponse(code = 200, message = "Site configuration properties successfully set."),
+                   @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
+                   @ApiResponse(code = 403, message = "Not authorized to set site configuration properties."),
+                   @ApiResponse(code = 500, message = "Unexpected error")})
     @RequestMapping(consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE, MediaType.APPLICATION_JSON_VALUE}, method = RequestMethod.POST)
     public ResponseEntity<Void> setSiteConfigProperties(@ApiParam(value = "The map of site configuration properties to be set.", required = true) @RequestBody final Map<String, String> properties) throws InitializationException {
         final HttpStatus status = isPermitted();
@@ -121,7 +129,10 @@ public class SiteConfigApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Returns a map of the selected site configuration properties.", notes = "Complex objects may be returned as encapsulated JSON strings.", response = String.class, responseContainer = "Map")
-    @ApiResponses({@ApiResponse(code = 200, message = "Site configuration properties successfully retrieved."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to set site configuration properties."), @ApiResponse(code = 500, message = "Unexpected error")})
+    @ApiResponses({@ApiResponse(code = 200, message = "Site configuration properties successfully retrieved."),
+                   @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
+                   @ApiResponse(code = 403, message = "Not authorized to set site configuration properties."),
+                   @ApiResponse(code = 500, message = "Unexpected error")})
     @RequestMapping(value = "values/{preferences}", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET)
     public ResponseEntity<Map<String, Object>> getSpecifiedSiteConfigProperties(@PathVariable final List<String> preferences) {
         final HttpStatus status = isPermitted();
@@ -135,21 +146,28 @@ public class SiteConfigApi extends AbstractXapiRestController {
 
         final Map<String, Object> values = new HashMap<>();
         for (final String preference : preferences) {
-            final Object value = getPreferences().get(preference);
-            if (value != null) {
-                values.put(preference, value);
+            if (getPreferences().containsKey(preference)) {
+                values.put(preference, getPreferences().get(preference));
             }
         }
         return new ResponseEntity<>(values, HttpStatus.OK);
     }
 
     @ApiOperation(value = "Returns the value of the selected site configuration property.", notes = "Complex objects may be returned as encapsulated JSON strings.", response = Object.class)
-    @ApiResponses({@ApiResponse(code = 200, message = "Site configuration property successfully retrieved."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to access site configuration properties."), @ApiResponse(code = 500, message = "Unexpected error")})
+    @ApiResponses({@ApiResponse(code = 200, message = "Site configuration property successfully retrieved."),
+                   @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
+                   @ApiResponse(code = 403, message = "Not authorized to access site configuration properties."),
+                   @ApiResponse(code = 500, message = "Unexpected error")})
     @RequestMapping(value = "{property}", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET)
-    public ResponseEntity<Object> getSpecifiedSiteConfigProperty(@ApiParam(value = "The site configuration property to retrieve.", required = true) @PathVariable final String property) {
-        final HttpStatus status = isPermitted();
-        if (status != null) {
-            return new ResponseEntity<>(status);
+    public ResponseEntity<Object> getSpecifiedSiteConfigProperty(final HttpServletRequest request, @ApiParam(value = "The site configuration property to retrieve.", required = true) @PathVariable final String property) {
+        if (!_appInfo.isOpenUrlRequest(request)) {
+            final HttpStatus status = isPermitted();
+            if (status != null) {
+                return new ResponseEntity<>(status);
+            }
+        }
+        if (!getPreferences().containsKey(property)) {
+            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
         }
         final Object value = getPreferences().get(property);
         if (_log.isDebugEnabled()) {
@@ -159,7 +177,10 @@ public class SiteConfigApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Sets a single site configuration property.", notes = "Sets the site configuration property specified in the URL to the value set in the body.", response = Void.class)
-    @ApiResponses({@ApiResponse(code = 200, message = "Site configuration properties successfully set."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 403, message = "Not authorized to set site configuration properties."), @ApiResponse(code = 500, message = "Unexpected error")})
+    @ApiResponses({@ApiResponse(code = 200, message = "Site configuration properties successfully set."),
+                   @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
+                   @ApiResponse(code = 403, message = "Not authorized to set site configuration properties."),
+                   @ApiResponse(code = 500, message = "Unexpected error")})
     @RequestMapping(value = "{property}", consumes = {MediaType.TEXT_PLAIN_VALUE, MediaType.APPLICATION_JSON_VALUE}, produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.POST)
     public ResponseEntity<Void> setSiteConfigProperty(@ApiParam(value = "The property to be set.", required = true) @PathVariable("property") final String property, @ApiParam("The value to be set for the property.") @RequestBody final String value) throws InitializationException {
         final HttpStatus status = isPermitted();
@@ -187,7 +208,9 @@ public class SiteConfigApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Returns a map of application build properties.", notes = "This includes the implementation version, Git commit hash, and build number and number.", response = Properties.class)
-    @ApiResponses({@ApiResponse(code = 200, message = "Application build properties successfully retrieved."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 500, message = "Unexpected error")})
+    @ApiResponses({@ApiResponse(code = 200, message = "Application build properties successfully retrieved."),
+                   @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
+                   @ApiResponse(code = 500, message = "Unexpected error")})
     @RequestMapping(value = "buildInfo", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET)
     public ResponseEntity<Properties> getBuildInfo() {
         if (_log.isDebugEnabled()) {
@@ -198,7 +221,9 @@ public class SiteConfigApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Returns a map of extended build attributes.", notes = "The values are dependent on what attributes are set for the build. It is not unexpected that there are no extended build attributes.", response = String.class, responseContainer = "Map")
-    @ApiResponses({@ApiResponse(code = 200, message = "Extended build attributes successfully retrieved."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 500, message = "Unexpected error")})
+    @ApiResponses({@ApiResponse(code = 200, message = "Extended build attributes successfully retrieved."),
+                   @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
+                   @ApiResponse(code = 500, message = "Unexpected error")})
     @RequestMapping(value = "buildInfo/attributes", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET)
     public ResponseEntity<Map<String, Map<String, String>>> getBuildAttributeInfo() {
         if (_log.isDebugEnabled()) {
@@ -209,7 +234,9 @@ public class SiteConfigApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Returns the system uptime.", notes = "This returns the uptime as a map of time units: days, hours, minutes, and seconds.", response = String.class, responseContainer = "Map")
-    @ApiResponses({@ApiResponse(code = 200, message = "System uptime successfully retrieved."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 500, message = "Unexpected error")})
+    @ApiResponses({@ApiResponse(code = 200, message = "System uptime successfully retrieved."),
+                   @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
+                   @ApiResponse(code = 500, message = "Unexpected error")})
     @RequestMapping(value = "uptime", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET)
     public ResponseEntity<Map<String, String>> getSystemUptime() {
         if (_log.isDebugEnabled()) {
@@ -220,7 +247,9 @@ public class SiteConfigApi extends AbstractXapiRestController {
     }
 
     @ApiOperation(value = "Returns the system uptime.", notes = "This returns the uptime as a formatted string.", response = String.class)
-    @ApiResponses({@ApiResponse(code = 200, message = "System uptime successfully retrieved."), @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."), @ApiResponse(code = 500, message = "Unexpected error")})
+    @ApiResponses({@ApiResponse(code = 200, message = "System uptime successfully retrieved."),
+                   @ApiResponse(code = 401, message = "Must be authenticated to access the XNAT REST API."),
+                   @ApiResponse(code = 500, message = "Unexpected error")})
     @RequestMapping(value = "uptime/display", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET)
     public ResponseEntity<String> getFormattedSystemUptime() {
         if (_log.isDebugEnabled()) {
diff --git a/src/main/java/org/nrg/xnat/initialization/RootConfig.java b/src/main/java/org/nrg/xnat/initialization/RootConfig.java
index f26e745a96c4550c22d5fe0ae11c40f5f2aa9bc9..4c9aa1efc4a1d359dd05065880d073267cd57368 100644
--- a/src/main/java/org/nrg/xnat/initialization/RootConfig.java
+++ b/src/main/java/org/nrg/xnat/initialization/RootConfig.java
@@ -51,8 +51,8 @@ import java.util.Properties;
 @Import({PropertiesConfig.class, DatabaseConfig.class, SecurityConfig.class, ApplicationConfig.class})
 public class RootConfig {
     @Bean
-    public XnatAppInfo appInfo(final ServletContext context, final JdbcTemplate template) throws IOException {
-        return new XnatAppInfo(context, template);
+    public XnatAppInfo appInfo(final ServletContext context, final SerializerService serializerService, final JdbcTemplate template) throws IOException {
+        return new XnatAppInfo(context, serializerService, template);
     }
 
     @Bean
diff --git a/src/main/java/org/nrg/xnat/initialization/SecurityConfig.java b/src/main/java/org/nrg/xnat/initialization/SecurityConfig.java
index 68b90f6529397f49d6cef304eb6a9a02683a272c..6d4530e3fcc1abfbd209909a3f0c7d874cea89ff 100644
--- a/src/main/java/org/nrg/xnat/initialization/SecurityConfig.java
+++ b/src/main/java/org/nrg/xnat/initialization/SecurityConfig.java
@@ -1,10 +1,6 @@
 package org.nrg.xnat.initialization;
 
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ArrayNode;
 import org.nrg.config.exceptions.SiteConfigurationException;
-import org.nrg.framework.services.SerializerService;
 import org.nrg.xdat.preferences.SiteConfigPreferences;
 import org.nrg.xdat.services.AliasTokenService;
 import org.nrg.xdat.services.XdatUserAuthService;
@@ -20,9 +16,6 @@ import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.ImportResource;
 import org.springframework.context.annotation.Primary;
-import org.springframework.core.io.DefaultResourceLoader;
-import org.springframework.core.io.Resource;
-import org.springframework.core.io.ResourceLoader;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.security.access.AccessDecisionVoter;
 import org.springframework.security.access.vote.AuthenticatedVoter;
@@ -46,7 +39,6 @@ import org.springframework.security.web.session.ConcurrentSessionFilter;
 
 import javax.sql.DataSource;
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.*;
 
 @Configuration
@@ -124,15 +116,8 @@ public class SecurityConfig {
     }
 
     @Bean
-    public FilterSecurityInterceptorBeanPostProcessor filterSecurityInterceptorBeanPostProcessor(final SerializerService serializer, final SiteConfigPreferences preferences) throws IOException {
-        final Resource resource = RESOURCE_LOADER.getResource("classpath:META-INF/xnat/security/configured-urls.yaml");
-        try (final InputStream inputStream = resource.getInputStream()) {
-            final HashMap<String, ArrayList<String>>         urlMap        = serializer.deserializeYaml(inputStream, SerializerService.TYPE_REF_MAP_STRING_LIST_STRING);
-            final FilterSecurityInterceptorBeanPostProcessor postProcessor = new FilterSecurityInterceptorBeanPostProcessor(preferences);
-            postProcessor.setOpenUrls(urlMap.get("openUrls"));
-            postProcessor.setAdminUrls(urlMap.get("adminUrls"));
-            return postProcessor;
-        }
+    public FilterSecurityInterceptorBeanPostProcessor filterSecurityInterceptorBeanPostProcessor(final SiteConfigPreferences preferences, final XnatAppInfo appInfo) throws IOException {
+        return new FilterSecurityInterceptorBeanPostProcessor(preferences, appInfo);
     }
 
     @Bean
@@ -203,38 +188,12 @@ public class SecurityConfig {
     }
 
     @Bean
-    public XnatInitCheckFilter xnatInitCheckFilter(final SerializerService serializer, final XnatAppInfo appInfo) throws IOException {
-        final Resource resource = RESOURCE_LOADER.getResource("classpath:META-INF/xnat/security/initialization-urls.yaml");
-        try (final InputStream inputStream = resource.getInputStream()) {
-            final XnatInitCheckFilter filter = new XnatInitCheckFilter(appInfo);
-            final JsonNode            paths  = serializer.deserializeYaml(inputStream);
-            filter.setConfigurationPath(paths.get("configPath").asText());
-            filter.setNonAdminErrorPath(paths.get("nonAdminErrorPath").asText());
-            filter.setInitializationPaths(nodeToList(paths.get("initPaths")));
-            filter.setExemptedPaths(nodeToList(paths.get("exemptedPaths")));
-            return filter;
-        }
+    public XnatInitCheckFilter xnatInitCheckFilter(final XnatAppInfo appInfo) throws IOException {
+        return new XnatInitCheckFilter(appInfo);
     }
 
     @Bean
     public XnatDatabaseUserDetailsService customDatabaseService(final XdatUserAuthService userAuthService, final DataSource dataSource) {
         return new XnatDatabaseUserDetailsService(userAuthService, dataSource);
     }
-
-    protected List<String> nodeToList(final JsonNode node) {
-        final List<String> list = new ArrayList<>();
-        if (node.isArray()) {
-            final ArrayNode arrayNode = (ArrayNode) node;
-            for (final JsonNode item : arrayNode) {
-                list.add(item.asText());
-            }
-        } else if (node.isTextual()) {
-            list.add(node.asText());
-        } else {
-            list.add(node.toString());
-        }
-        return list;
-    }
-
-    private static final ResourceLoader RESOURCE_LOADER = new DefaultResourceLoader();
 }
diff --git a/src/main/java/org/nrg/xnat/security/FilterSecurityInterceptorBeanPostProcessor.java b/src/main/java/org/nrg/xnat/security/FilterSecurityInterceptorBeanPostProcessor.java
index 2144dae6ecb6583b0a74eea5418cb7b39bb89127..fa23664f8c7d7ae5ee2551c519714e8fdad4762c 100644
--- a/src/main/java/org/nrg/xnat/security/FilterSecurityInterceptorBeanPostProcessor.java
+++ b/src/main/java/org/nrg/xnat/security/FilterSecurityInterceptorBeanPostProcessor.java
@@ -13,6 +13,7 @@ package org.nrg.xnat.security;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.nrg.xdat.preferences.SiteConfigPreferences;
+import org.nrg.xnat.services.XnatAppInfo;
 import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.config.BeanPostProcessor;
@@ -25,25 +26,14 @@ import org.springframework.security.web.access.intercept.FilterSecurityIntercept
 import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
 import org.springframework.security.web.util.matcher.RequestMatcher;
 
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.LinkedHashMap;
-import java.util.List;
 
 public class FilterSecurityInterceptorBeanPostProcessor implements BeanPostProcessor {
     @Autowired
-    public FilterSecurityInterceptorBeanPostProcessor(final SiteConfigPreferences preferences) {
+    public FilterSecurityInterceptorBeanPostProcessor(final SiteConfigPreferences preferences, final XnatAppInfo appInfo) {
         _preferences = preferences;
-    }
-
-    public void setOpenUrls(List<String> openUrls) {
-        _openUrls.clear();
-        _openUrls.addAll(openUrls);
-    }
-
-    public void setAdminUrls(List<String> adminUrls) {
-        _adminUrls.clear();
-        _adminUrls.addAll(adminUrls);
+        _appInfo = appInfo;
     }
 
     @Override
@@ -70,27 +60,25 @@ public class FilterSecurityInterceptorBeanPostProcessor implements BeanPostProce
     public ExpressionBasedFilterInvocationSecurityMetadataSource getMetadataSource(boolean requiredLogin) {
         final LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> map = new LinkedHashMap<>();
 
-        for (final String openUrl : _openUrls) {
+        for (final AntPathRequestMatcher matcher : _appInfo.getOpenUrls().values()) {
             if (_log.isDebugEnabled()) {
-                _log.debug("Setting permitAll on the open URL: " + openUrl);
+                _log.debug("Setting permitAll on the open URL: " + matcher.getPattern());
             }
-
-            map.put(new AntPathRequestMatcher(openUrl), SecurityConfig.createList(PERMIT_ALL));
+            map.put(matcher, SecurityConfig.createList(PERMIT_ALL));
         }
 
-        for (String adminUrl : _adminUrls) {
+        for (final AntPathRequestMatcher matcher : _appInfo.getAdminUrls().values()) {
             if (_log.isDebugEnabled()) {
-                _log.debug("Setting permissions on the admin URL: " + adminUrl);
+                _log.debug("Setting permissions on the admin URL: " + matcher.getPattern());
             }
-
-            map.put(new AntPathRequestMatcher(adminUrl), SecurityConfig.createList(ADMIN_EXPRESSION));
+            map.put(matcher, SecurityConfig.createList(ADMIN_EXPRESSION));
         }
 
-        final String nonopen = requiredLogin ? DEFAULT_EXPRESSION : PERMIT_ALL;
+        final String secure = requiredLogin ? DEFAULT_EXPRESSION : PERMIT_ALL;
         if (_log.isDebugEnabled()) {
-            _log.debug("Setting " + nonopen + " on the default pattern: " + DEFAULT_PATTERN);
+            _log.debug("Setting " + secure + " on the default pattern: " + DEFAULT_PATTERN);
         }
-        map.put(new AntPathRequestMatcher(DEFAULT_PATTERN), SecurityConfig.createList(nonopen));
+        map.put(new AntPathRequestMatcher(DEFAULT_PATTERN), SecurityConfig.createList(secure));
         return new ExpressionBasedFilterInvocationSecurityMetadataSource(map, new DefaultWebSecurityExpressionHandler());
     }
 
@@ -115,7 +103,5 @@ public class FilterSecurityInterceptorBeanPostProcessor implements BeanPostProce
     private static final String DEFAULT_EXPRESSION = "hasRole('ROLE_USER')";
 
     private final SiteConfigPreferences _preferences;
-
-    private final List<String> _openUrls = new ArrayList<>();
-    private final List<String> _adminUrls = new ArrayList<>();
+    private final XnatAppInfo           _appInfo;
 }
diff --git a/src/main/java/org/nrg/xnat/security/XnatInitCheckFilter.java b/src/main/java/org/nrg/xnat/security/XnatInitCheckFilter.java
index d485f0f5d70daaafd53b01df64e999bcae73193a..6369a1b1acf968cdcf998899d85aa0e5ca8b1fa9 100644
--- a/src/main/java/org/nrg/xnat/security/XnatInitCheckFilter.java
+++ b/src/main/java/org/nrg/xnat/security/XnatInitCheckFilter.java
@@ -27,9 +27,6 @@ import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.regex.Pattern;
 
 public class XnatInitCheckFilter extends GenericFilterBean {
     @Autowired
@@ -55,7 +52,7 @@ public class XnatInitCheckFilter extends GenericFilterBean {
 
             if (isAnonymous) {
                 String header = request.getHeader("Authorization");
-                if (header != null && header.startsWith("Basic ") && !isInitializerPath(uri)) {
+                if (header != null && header.startsWith("Basic ") && !_appInfo.isInitPathRequest(request)) {
                     // Users that authenticated using basic authentication receive an error message informing
                     // them that the system is not yet initialized.
                     response.sendError(HttpServletResponse.SC_FORBIDDEN, "Site has not yet been configured.");
@@ -65,13 +62,13 @@ public class XnatInitCheckFilter extends GenericFilterBean {
 
             final String referer = request.getHeader("Referer");
 
-            if (isInitializerPath(uri) ||
-                _configurationPathPattern.matcher(uri).matches() ||
-                _nonAdminErrorPathPattern.matcher(uri).matches() ||
-                isExemptedPath(uri)) {
+            if (_appInfo.isInitPathRequest(request) ||
+                _appInfo.isConfigPathRequest(request) ||
+                _appInfo.isNonAdminErrorPathRequest(request) ||
+                _appInfo.isExemptedPathRequest(request)) {
                 //If you're already on the configuration page, error page, or expired password page, continue on without redirect.
                 chain.doFilter(req, res);
-            } else if (referer != null && (_configurationPathPattern.matcher(referer).matches() || _nonAdminErrorPathPattern.matcher(referer).matches() || isExemptedPath(referer)) && !uri.contains("/app/template") && !uri.contains("/app/screen") && !uri.endsWith(".vm") && !uri.equals("/")) {
+            } else if (referer != null && (_appInfo.isConfigPathRequest(referer) || _appInfo.isNonAdminErrorPathRequest(referer) || _appInfo.isExemptedPathRequest(referer)) && !uri.contains("/app/template") && !uri.contains("/app/screen") && !uri.endsWith(".vm") && !uri.equals("/")) {
                 //If you're on a request within the configuration page (or error page or expired password page), continue on without redirect. This checks that the referer is the configuration page and that
                 // the request is not for another page (preventing the user from navigating away from the Configuration page via the menu bar).
                 chain.doFilter(req, res);
@@ -85,71 +82,23 @@ public class XnatInitCheckFilter extends GenericFilterBean {
                     final String serverPath = XnatHttpUtils.getServerRoot(request);
                     if (Roles.isSiteAdmin(user)) {
                         if (_log.isWarnEnabled()) {
-                            _log.warn("Admin user {} has logged into the uninitialized server and is being redirected to {}", user.getUsername(), serverPath + _configurationPath);
+                            _log.warn("Admin user {} has logged into the uninitialized server and is being redirected to {}", user.getUsername(), serverPath + _appInfo.getConfigPath());
                         }
                         //Otherwise, if the user has administrative permissions, direct the user to the configuration page.
-                        response.sendRedirect(serverPath + _configurationPath);
+                        response.sendRedirect(serverPath + _appInfo.getConfigPath());
                     } else {
                         if (_log.isWarnEnabled()) {
-                            _log.warn("Non-admin user {} has logged into the uninitialized server and is being redirected to {}", user.getUsername(), serverPath + _nonAdminErrorPath);
+                            _log.warn("Non-admin user {} has logged into the uninitialized server and is being redirected to {}", user.getUsername(), serverPath + _appInfo.getNonAdminErrorPath());
                         }
                         //The system is not initialized but the user does not have administrative permissions. Direct the user to an error page.
-                        response.sendRedirect(serverPath + _nonAdminErrorPath);
+                        response.sendRedirect(serverPath + _appInfo.getNonAdminErrorPath());
                     }
                 }
             }
         }
     }
 
-    public void setInitializationPaths(final List<String> initializationPaths) {
-        for (final String initializationPath : initializationPaths) {
-            _initializationPathPatterns.add(Pattern.compile("^(https*://.*)?" + initializationPath + ".*$"));
-        }
-    }
-
-    public void setConfigurationPath(String configurationPath) {
-        _configurationPath = configurationPath;
-        _configurationPathPattern = Pattern.compile("^(https*://.*)?" + configurationPath + "/*");
-    }
-
-    public void setNonAdminErrorPath(String nonAdminErrorPath) {
-        _nonAdminErrorPath = nonAdminErrorPath;
-        _nonAdminErrorPathPattern = Pattern.compile("^(https*://.*)?" + nonAdminErrorPath + "/*");
-    }
-
-    public void setExemptedPaths(List<String> exemptedPaths) {
-        _exemptedPaths.clear();
-        _exemptedPaths.addAll(exemptedPaths);
-    }
-
-    private boolean isExemptedPath(final String path) {
-        for (final String exemptedPath : _exemptedPaths) {
-            if (path.split("\\?")[0].endsWith(exemptedPath)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private boolean isInitializerPath(final String uri) {
-        for (final Pattern initializationPathPattern : _initializationPathPatterns) {
-            if (initializationPathPattern.matcher(uri).matches()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
     private static Logger _log = LoggerFactory.getLogger(XnatInitCheckFilter.class);
 
     private final XnatAppInfo _appInfo;
-
-    private String  _configurationPath;
-    private String  _nonAdminErrorPath;
-    private Pattern _configurationPathPattern;
-    private Pattern _nonAdminErrorPathPattern;
-
-    private List<Pattern> _initializationPathPatterns = new ArrayList<>();
-
-    private final List<String> _exemptedPaths = new ArrayList<>();
 }
diff --git a/src/main/java/org/nrg/xnat/services/XnatAppInfo.java b/src/main/java/org/nrg/xnat/services/XnatAppInfo.java
index 363ac008e9bbd3ff559b850fc3faf987a6850a1c..cf3290213e78a6f5c4272811fedfd77c763b4c27 100644
--- a/src/main/java/org/nrg/xnat/services/XnatAppInfo.java
+++ b/src/main/java/org/nrg/xnat/services/XnatAppInfo.java
@@ -1,19 +1,26 @@
 package org.nrg.xnat.services;
 
-
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import org.nrg.framework.services.SerializerService;
 import org.nrg.prefs.exceptions.InvalidPreferenceName;
 import org.nrg.xdat.XDAT;
 import org.python.google.common.collect.ImmutableMap;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.core.io.DefaultResourceLoader;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.ResourceLoader;
 import org.springframework.dao.DataAccessException;
 import org.springframework.dao.EmptyResultDataAccessException;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.RowMapper;
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
 import org.springframework.stereotype.Component;
 
 import javax.inject.Inject;
 import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
 import java.io.IOException;
 import java.io.InputStream;
 import java.sql.ResultSet;
@@ -23,10 +30,13 @@ import java.text.DecimalFormat;
 import java.util.*;
 import java.util.jar.Attributes;
 import java.util.jar.Manifest;
+import java.util.regex.Pattern;
 
 @Component
 public class XnatAppInfo {
 
+    public static final String NON_RELEASE_VERSION_REGEX = "(?i:^.*(SNAPSHOT|BETA|RC).*$)";
+
     private static final int           MILLISECONDS_IN_A_DAY    = (24 * 60 * 60 * 1000);
     private static final int           MILLISECONDS_IN_AN_HOUR  = (60 * 60 * 1000);
     private static final int           MILLISECONDS_IN_A_MINUTE = (60 * 1000);
@@ -37,10 +47,33 @@ public class XnatAppInfo {
     private static final String        SECONDS                  = "seconds";
 
     @Inject
-    public XnatAppInfo(final ServletContext context, final JdbcTemplate template) throws IOException {
+    public XnatAppInfo(final ServletContext context, final SerializerService serializerService, final JdbcTemplate template) throws IOException {
         _template = template;
+
+        final Resource configuredUrls = RESOURCE_LOADER.getResource("classpath:META-INF/xnat/security/configured-urls.yaml");
+        try (final InputStream inputStream = configuredUrls.getInputStream()) {
+            final HashMap<String, ArrayList<String>> urlMap = serializerService.deserializeYaml(inputStream, SerializerService.TYPE_REF_MAP_STRING_LIST_STRING);
+            populate(_openUrls, urlMap.get("openUrls"));
+            populate(_adminUrls, urlMap.get("adminUrls"));
+        }
+
+        final Resource initializationUrls = RESOURCE_LOADER.getResource("classpath:META-INF/xnat/security/initialization-urls.yaml");
+        try (final InputStream inputStream = initializationUrls.getInputStream()) {
+            final JsonNode paths = serializerService.deserializeYaml(inputStream);
+            _configPath = paths.get("configPath").asText();
+            _configPathPattern = getPathPattern(_configPath);
+            _configPathMatcher = new AntPathRequestMatcher(_configPath);
+
+            _nonAdminErrorPath = paths.get("nonAdminErrorPath").asText();
+            _nonAdminErrorPathPattern = getPathPattern(_nonAdminErrorPath);
+            _nonAdminErrorPathMatcher = new AntPathRequestMatcher(_nonAdminErrorPath);
+
+            populate(_initPaths, nodeToList(paths.get("initPaths")));
+            populate(_exemptedPaths, nodeToList(paths.get("exemptedPaths")));
+        }
+
         try (final InputStream input = context.getResourceAsStream("/META-INF/MANIFEST.MF")) {
-            final Manifest   manifest   = new Manifest(input);
+            final Manifest manifest = new Manifest(input);
             final Attributes attributes = manifest.getMainAttributes();
             _properties.setProperty("buildNumber", attributes.getValue("Build-Number"));
             _properties.setProperty("buildDate", attributes.getValue("Build-Date"));
@@ -99,7 +132,6 @@ public class XnatAppInfo {
                 }
             }
         }
-
     }
 
     public Map<String, String> getFoundPreferences() {
@@ -136,24 +168,21 @@ public class XnatAppInfo {
                     if (_log.isInfoEnabled()) {
                         _log.info("The site was not flagged as initialized and initialized preference set to false. Setting system for initialization.");
                     }
-                    for(String pref: _foundPreferences.keySet()){
+                    for (String pref : _foundPreferences.keySet()) {
                         _template.update(
                                 "UPDATE xhbm_preference SET value = ? WHERE name = ?",
                                 new Object[]{_foundPreferences.get(pref), pref}, new int[]{Types.VARCHAR, Types.VARCHAR}
-                        );
+                                        );
                         try {
                             XDAT.getSiteConfigPreferences().set(_foundPreferences.get(pref), pref);
-                        }
-                        catch(InvalidPreferenceName e){
-                            _log.error("",e);
-                        }
-                        catch(NullPointerException e){
-                            _log.error("Error getting site config preferences.",e);
+                        } catch (InvalidPreferenceName e) {
+                            _log.error("", e);
+                        } catch (NullPointerException e) {
+                            _log.error("Error getting site config preferences.", e);
                         }
                     }
                 }
-            }
-            catch(EmptyResultDataAccessException e){
+            } catch (EmptyResultDataAccessException e) {
                 //Could not find the initialized preference. Site is still not initialized.
             }
 
@@ -187,7 +216,8 @@ public class XnatAppInfo {
      * @return The version of the application.
      */
     public String getVersion() {
-        return _properties.getProperty("version");
+        final String version = _properties.getProperty("version");
+        return version.matches(NON_RELEASE_VERSION_REGEX) ? version + " (build " + getBuildNumber() + " on " + getBuildDate() + ")" : version;
     }
 
     /**
@@ -244,12 +274,12 @@ public class XnatAppInfo {
      * @return A map of values indicating the system uptime.
      */
     public Map<String, String> getUptime() {
-        final long diff             = new Date().getTime() - _startTime.getTime();
-        final int  days             = (int) (diff / MILLISECONDS_IN_A_DAY);
-        final long daysRemainder    = diff % MILLISECONDS_IN_A_DAY;
-        final int  hours            = (int) (daysRemainder / MILLISECONDS_IN_AN_HOUR);
-        final long hoursRemainder   = daysRemainder % MILLISECONDS_IN_AN_HOUR;
-        final int  minutes          = (int) (hoursRemainder / MILLISECONDS_IN_A_MINUTE);
+        final long diff = new Date().getTime() - _startTime.getTime();
+        final int days = (int) (diff / MILLISECONDS_IN_A_DAY);
+        final long daysRemainder = diff % MILLISECONDS_IN_A_DAY;
+        final int hours = (int) (daysRemainder / MILLISECONDS_IN_AN_HOUR);
+        final long hoursRemainder = daysRemainder % MILLISECONDS_IN_AN_HOUR;
+        final int minutes = (int) (hoursRemainder / MILLISECONDS_IN_A_MINUTE);
         final long minutesRemainder = hoursRemainder % MILLISECONDS_IN_A_MINUTE;
 
         final Map<String, String> uptime = new HashMap<>();
@@ -274,7 +304,7 @@ public class XnatAppInfo {
      */
     public String getFormattedUptime() {
         final Map<String, String> uptime = getUptime();
-        final StringBuilder       buffer = new StringBuilder();
+        final StringBuilder buffer = new StringBuilder();
         if (uptime.containsKey(DAYS)) {
             buffer.append(uptime.get(DAYS)).append(" days, ");
         }
@@ -297,18 +327,135 @@ public class XnatAppInfo {
         return ImmutableMap.copyOf(_plugins);
     }
 
+    /**
+     * Gets the path where XNAT found its primary configuration file.
+     *
+     * @return The path where XNAT found its primary configuration file.
+     */
+    public String getConfigPath() {
+        return _configPath;
+    }
+
+    /**
+     * Gets the path where non-admin users should be sent when errors occur that require administrator intervention.
+     *
+     * @return Non-admin users error path.
+     */
+    public String getNonAdminErrorPath() {
+        return _nonAdminErrorPath;
+    }
+
+    /**
+     * Gets the URLs available to all users, including anonymous users.
+     *
+     * @return A set of the system's open URLs.
+     */
+    public HashMap<String, AntPathRequestMatcher> getOpenUrls() {
+        return new HashMap<>(_openUrls);
+    }
+
+    /**
+     * Gets the URLs available only to administrators.
+     *
+     * @return A set of administrator-only URLs.
+     */
+    public HashMap<String, AntPathRequestMatcher> getAdminUrls() {
+        return new HashMap<>(_adminUrls);
+    }
+
+    public boolean isOpenUrlRequest(final HttpServletRequest request) {
+        return checkUrls(request, _openUrls.values());
+    }
+
+    public boolean isInitPathRequest(final HttpServletRequest request) {
+        return checkUrls(request, _initPaths.values());
+    }
+
+    public boolean isExemptedPathRequest(final HttpServletRequest request) {
+        return checkUrls(request, _exemptedPaths.values());
+    }
+
+    public boolean isExemptedPathRequest(final String path) {
+        for (final String exemptedPath : _exemptedPaths.keySet()) {
+            if (path.split("\\?")[0].endsWith(exemptedPath)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean isConfigPathRequest(final HttpServletRequest request) {
+        return _configPathMatcher.matches(request);
+    }
+
+    public boolean isConfigPathRequest(final String path) {
+        return _configPathPattern.matcher(path).matches();
+    }
+
+    public boolean isNonAdminErrorPathRequest(final HttpServletRequest request) {
+        return _nonAdminErrorPathMatcher.matches(request);
+    }
+
+    public boolean isNonAdminErrorPathRequest(final String path) {
+        return _nonAdminErrorPathPattern.matcher(path).matches();
+    }
+
+    private List<String> nodeToList(final JsonNode node) {
+        final List<String> list = new ArrayList<>();
+        if (node.isArray()) {
+            final ArrayNode arrayNode = (ArrayNode) node;
+            for (final JsonNode item : arrayNode) {
+                list.add(item.asText());
+            }
+        } else if (node.isTextual()) {
+            list.add(node.asText());
+        } else {
+            list.add(node.toString());
+        }
+        return list;
+    }
+
+    private void populate(final Map<String, AntPathRequestMatcher> matchers, final List<String> urls) {
+        for (final String url : urls) {
+            matchers.put(url, new AntPathRequestMatcher(url));
+        }
+    }
+
+    private boolean checkUrls(final HttpServletRequest request, final Collection<AntPathRequestMatcher> matchers) {
+        for (final AntPathRequestMatcher matcher : matchers) {
+            if (matcher.matches(request)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private Pattern getPathPattern(final String path) {
+        return Pattern.compile("^(https*://.*)?" + path + "/*");
+    }
+
     private static final Logger _log = LoggerFactory.getLogger(XnatAppInfo.class);
 
-    private static final List<String> PRIMARY_MANIFEST_ATTRIBUTES = Arrays.asList("Build-Number", "Build-Date", "Implementation-Version", "Implementation-Sha");
+    private static final List<String>   PRIMARY_MANIFEST_ATTRIBUTES = Arrays.asList("Build-Number", "Build-Date", "Implementation-Version", "Implementation-Sha");
+    private static final ResourceLoader RESOURCE_LOADER             = new DefaultResourceLoader();
 
     private final JdbcTemplate _template;
 
-    private final Map<String, String> _foundPreferences = new HashMap<>();
+    private final String _configPath;
+    private final Pattern _configPathPattern;
+    private final AntPathRequestMatcher _configPathMatcher;
+    private final String _nonAdminErrorPath;
+    private final Pattern _nonAdminErrorPathPattern;
+    private final AntPathRequestMatcher _nonAdminErrorPathMatcher;
 
-    private final Date                             _startTime   = new Date();
-    private final Properties                       _properties  = new Properties();
-    private final Map<String, Map<String, String>> _attributes  = new HashMap<>();
-    private       boolean                          _initialized = false;
-    private final Map<String, Properties>          _plugins    = new HashMap<>();
+    private final Map<String, AntPathRequestMatcher> _openUrls         = new HashMap<>();
+    private final Map<String, AntPathRequestMatcher> _adminUrls        = new HashMap<>();
+    private final Map<String, AntPathRequestMatcher> _initPaths        = new HashMap<>();
+    private final Map<String, AntPathRequestMatcher> _exemptedPaths    = new HashMap<>();
+    private final Map<String, String>                _foundPreferences = new HashMap<>();
+    private final Date                               _startTime        = new Date();
+    private final Properties                         _properties       = new Properties();
+    private final Map<String, Map<String, String>>   _attributes       = new HashMap<>();
+    private       boolean                            _initialized      = false;
+    private final Map<String, Properties>            _plugins          = new HashMap<>();
 }
-
diff --git a/src/main/resources/META-INF/xnat/security/configured-urls.yaml b/src/main/resources/META-INF/xnat/security/configured-urls.yaml
index f86e9aa027318ae3019d35b5443d56cd1dda967f..8431e00e0c58e8a3c1ca2369332160e089099870 100644
--- a/src/main/resources/META-INF/xnat/security/configured-urls.yaml
+++ b/src/main/resources/META-INF/xnat/security/configured-urls.yaml
@@ -23,6 +23,7 @@ openUrls:
   - /data/services/sendemailverification*
   - /REST/services/sendemailverification*
   - /xapi/siteConfig/buildInfo
+  - /xapi/siteConfig/siteWideAlert*
   - /images/**
   - /scripts/**
   - /style/**