From f9ac829160bcba902b12db50f851cd82cfafe24c Mon Sep 17 00:00:00 2001 From: labkey-jeckels Date: Mon, 26 Jan 2026 18:29:30 -0800 Subject: [PATCH] Include /.well-knonwn/security.txt --- .../labkey/core/security/BlockListFilter.java | 2 +- .../core/webdav/ModuleStaticResolverImpl.java | 46 +++++++++---------- core/webapp/.well-known/security.txt | 5 ++ 3 files changed, 29 insertions(+), 24 deletions(-) create mode 100644 core/webapp/.well-known/security.txt diff --git a/core/src/org/labkey/core/security/BlockListFilter.java b/core/src/org/labkey/core/security/BlockListFilter.java index 55e7f31ac3a..bee41f69984 100644 --- a/core/src/org/labkey/core/security/BlockListFilter.java +++ b/core/src/org/labkey/core/security/BlockListFilter.java @@ -180,7 +180,7 @@ public static boolean isSuspicious(String request_path, String query, String use return true; for (String part : path) { - if (part.startsWith(".") || part.startsWith("\">") || part.startsWith("wp-") || (part.startsWith("admin")&&!isActionURL)) + if ((part.startsWith(".") && !part.equals(".well-known")) || part.startsWith("\">") || part.startsWith("wp-") || (part.startsWith("admin")&&!isActionURL)) return true; if (part.endsWith("-inf")) return true; diff --git a/core/src/org/labkey/core/webdav/ModuleStaticResolverImpl.java b/core/src/org/labkey/core/webdav/ModuleStaticResolverImpl.java index cfd06de1c21..c9be47136a4 100644 --- a/core/src/org/labkey/core/webdav/ModuleStaticResolverImpl.java +++ b/core/src/org/labkey/core/webdav/ModuleStaticResolverImpl.java @@ -24,6 +24,7 @@ import org.labkey.api.cache.Cache; import org.labkey.api.cache.CacheListener; import org.labkey.api.cache.CacheManager; +import org.labkey.api.collections.CaseInsensitiveHashSet; import org.labkey.api.collections.CaseInsensitiveTreeMap; import org.labkey.api.files.FileSystemDirectoryListener; import org.labkey.api.files.FileSystemWatcher; @@ -57,12 +58,14 @@ import java.io.InputStream; import java.nio.file.WatchEvent; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -181,16 +184,15 @@ private LookupResult resolve(Path path) for (int i=0 ; i> map = shortcuts.get(rParent.getPath()); - if (null == map) - { - map = new HashMap<>(); - shortcuts.put(rParent.getPath(), map); - } + Map> map = shortcuts.computeIfAbsent(rParent.getPath(), k -> new HashMap<>()); map.put(from.getName(), new Pair<>(target,indexPage)); } @@ -387,6 +384,15 @@ public boolean shouldIndex() } } + private static final Set ALLOWED_DOT_NAMES = Collections.unmodifiableSet(new CaseInsensitiveHashSet(Arrays.asList(".well-known"))); + + private boolean isAllowableName(String name) + { + return !"WEB-INF".equalsIgnoreCase(name) && + !"META-INF".equalsIgnoreCase(name) && + (!name.startsWith(".") || ALLOWED_DOT_NAMES.contains(name)); + } + private static final Cache> CHILDREN_CACHE = CacheManager.getCache(1000, CacheManager.DAY, "Static resources"); private class StaticResource extends _PublicResource implements SupportsFileSystemWatcher @@ -425,12 +431,6 @@ public WebdavResolver getResolver() return ModuleStaticResolverImpl.this; } - @Override - public boolean canList(User user, boolean forRead) - { - return true; - } - Map getChildren() { synchronized (_lock) @@ -447,7 +447,7 @@ Map getChildren() for (FileLike fo : files) { String name = fo.getName(); - if (name.startsWith(".") || name.equals("WEB-INF") || name.equals("META-INF")) + if (!isAllowableName(name)) continue; if (!map.containsKey(name)) map.put(name, new ArrayList<>()); @@ -459,7 +459,7 @@ Map getChildren() { Path path = getPath().append(e.getKey()); List alternates = e.getValue(); - if (alternates.get(0).isFile()) + if (alternates.getFirst().isFile()) children.put(e.getKey(), new StaticResource(this, path, alternates.subList(0,1), null)); else children.put(e.getKey(), new StaticResource(this, path, e.getValue(), null)); @@ -518,7 +518,7 @@ public File getFile() { if (!exists()) return null; - return _files.get(0).toNioPathForRead().toFile(); + return _files.getFirst().toNioPathForRead().toFile(); } @Override @@ -537,7 +537,7 @@ public boolean exists() @Override public boolean isCollection() { - return exists() && _files.get(0).isDirectory(); + return exists() && _files.getFirst().isDirectory(); } @Override @@ -549,7 +549,7 @@ public WebdavResource find(Path.Part name) @Override public boolean isFile() { - return exists() && _files.get(0).isFile(); + return exists() && _files.getFirst().isFile(); } @Override @@ -572,7 +572,7 @@ public long getLastModified() public InputStream getInputStream(User user) throws IOException { if (isFile()) - return _files.get(0).openInputStream(); + return _files.getFirst().openInputStream(); return null; } @@ -586,7 +586,7 @@ public long copyFrom(User user, FileStream in) public long getContentLength() { if (isFile()) - return _files.get(0).getSize(); + return _files.getFirst().getSize(); return 0; } diff --git a/core/webapp/.well-known/security.txt b/core/webapp/.well-known/security.txt new file mode 100644 index 00000000000..2b332e13de9 --- /dev/null +++ b/core/webapp/.well-known/security.txt @@ -0,0 +1,5 @@ +Contact: https://www.labkey.com/about/contact-us/ +Expires: 2030-01-01T00:00:00.000Z +Preferred-Languages: en +Policy: https://www.labkey.org/Documentation/wiki-page.view?name=securityFixEvaluation +Acknowledgements: https://www.labkey.org/Documentation/wiki-page.view?name=securityFixEvaluation