Block Web Access to Code/Java Source Files

Thu Feb 19 10:49:45 EST 2026

Last year, while developing Jakarta Modules, I realized that there's a path to accessing Java source files by path in normal NSF apps. This ended up being tracked as a Defect Article, but has unfortunately since been deferred to an unspecified future time. I think it's worth fixing before such a time, though, so I set about doing that.

TL;DR

If you have a file in Code/Java in Designer named "com.mycompany.MyClass", the source is accessible via "foo.nsf/xsp/com/mycompany/MyClass.java". There are a couple ways to patch this:

  • Set up a web substitution rule for /*.nsf/xsp/*.java to /doesnotexist.html or the like. That won't cover non-Java files (like translation.properties, etc.), but it'd at least prevent your source code from being visible. It'd also be good to set one up for plugin.xml
  • Install my new project Code/Java blocker

Further Explanation

The specific problem here is the way the "foo.nsf/xsp/*" URL namespace works. That is essentially the "webapp version" of your NSF, and URLs coming in here are processed as Servlets and, failing that, static resources. When a request comes in matching that, the XPages runtime looks for IServletFactory implementations to handle it first - if one of those matches, it hands the request off to the matched Servlet. If none matches, it then moves on to some code that handles static resources like a classic Java web app would. I'm not quite sure why it does this, but I'd guess it's probably a holdover from traditional web behavior and not actually really useful. Still, it may be load-bearing after so many years, so I can see why HCL wouldn't want to outright remove this.

Anyway, the problem arises from the fact that the virtual filesystem used by the "static resource" search includes all file-resource-like entities that don't start with /WEB-INF. Java classes stored as Code/Java resources are this type of file, and so their conceptual file path is included in the pool. Thus, if you know the name of a Java class inside an NSF and have web access to that NSF, you can get its source via URL. This is admittedly a bit of a stretch as an attack vector: it being a problem relies on someone a) knowing the full name of a Java class and b) that Java class containing damaging information. If you have your app set to show stack traces on errors (not the default), someone could potentially glean some local class names, and from there walk the tree by looking at imports and class references, but it's still a long walk.

Long walk or no, though, it's worth fixing.

The first fix - the web redirection rule - should cover the bulk of what you'd want. There's an off chance that it might run afoul of some edge case where there actually is a Servlet that's intentionally serving up files that end in ".java", but that's pretty unlikely.

Because I like writing code, I made a small project that does the job a little more specifically. The way the plugin works is that it contributes a IServletFactory to the XPages runtime for all NSFs that builds a collection of Code/Java files and then, when a request comes in that matches that or some other vetoed paths, then returns a stock Servlet that returns 404 in the same way that other non-matched paths in that namespace do. That should make it so that the source files are not accessible and also don't "leak" their presence at all.

Either way, I suggest applying a fix for this until it's done in the product.

New Comment