From f9ac829160bcba902b12db50f851cd82cfafe24c Mon Sep 17 00:00:00 2001 From: labkey-jeckels Date: Mon, 26 Jan 2026 18:29:30 -0800 Subject: [PATCH 1/3] 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 From 438b9871c07d0e26c1afb1f5ee718604cf31360d Mon Sep 17 00:00:00 2001 From: labkey-jeckels Date: Tue, 27 Jan 2026 19:22:17 -0800 Subject: [PATCH 2/3] Remove unneeded override --- .../org/labkey/core/webdav/ModuleStaticResolverImpl.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/core/src/org/labkey/core/webdav/ModuleStaticResolverImpl.java b/core/src/org/labkey/core/webdav/ModuleStaticResolverImpl.java index c9be47136a4..737e2d121f2 100644 --- a/core/src/org/labkey/core/webdav/ModuleStaticResolverImpl.java +++ b/core/src/org/labkey/core/webdav/ModuleStaticResolverImpl.java @@ -425,12 +425,6 @@ public String getExecuteHref(ViewContext context) return PageFlowUtil.staticResourceUrl(getPath().encode()); } - @Override - public WebdavResolver getResolver() - { - return ModuleStaticResolverImpl.this; - } - Map getChildren() { synchronized (_lock) From fb14aa1ecd4a36c554ec7ddda2b62d40759c7206 Mon Sep 17 00:00:00 2001 From: labkey-jeckels Date: Wed, 28 Jan 2026 09:59:48 -0800 Subject: [PATCH 3/3] Totally unrelated generics cleanup --- api/src/org/labkey/api/query/QueryChangeListener.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/src/org/labkey/api/query/QueryChangeListener.java b/api/src/org/labkey/api/query/QueryChangeListener.java index 59d96dc79ee..776c57392ff 100644 --- a/api/src/org/labkey/api/query/QueryChangeListener.java +++ b/api/src/org/labkey/api/query/QueryChangeListener.java @@ -144,7 +144,7 @@ public static void handleQueryNameChange(@NotNull String oldValue, String newVal if (oldValue.equals(newValue)) return; - QueryChangeListener.QueryPropertyChange change = new QueryChangeListener.QueryPropertyChange<>( + QueryChangeListener.QueryPropertyChange change = new QueryChangeListener.QueryPropertyChange<>( QueryService.get().getUserSchema(user, container, schemaPath).getQueryDefForTable(newValue), QueryChangeListener.QueryProperty.Name, oldValue, @@ -160,7 +160,7 @@ public static void handleSchemaNameChange(@NotNull String oldValue, String newVa if (oldValue.equals(newValue)) return; - QueryChangeListener.QueryPropertyChange change = new QueryChangeListener.QueryPropertyChange<>( + QueryChangeListener.QueryPropertyChange change = new QueryChangeListener.QueryPropertyChange<>( null, QueryChangeListener.QueryProperty.SchemaName, oldValue,