We blocked an IP that was downloading extensions in a loop

Hi all,

While analysing a jump in our CloudFront costs, we found a single client downloading the same Lucee extensions from ext.lucee.org over and over, around the clock:

  • Source: one IP address from Primus Telecommunications, a Canadian ISP
  • What it downloaded: cfspreadsheet-3.0.5.lex, image-extension-2.0.0.26.lex and chart-extension-2.0.0.1.lex, about 2,500 times each per day, so one full set roughly every 35 seconds
  • Volume: 7,775 requests and 73.4 GB on a single day (Oct 16). A similar pattern showed up from Sep 12 to 21.
  • Cost: about $4–6 per day for this one client, which adds up fast for an open source project

The pattern looks like a Lucee server or Docker container stuck in a restart loop, reinstalling those three extensions on every start (for example via LUCEE_EXTENSIONS or .CFConfig.json), with no user agent set.

We’ve blocked that IP on ext.lucee.org for now, so it gets a 403. If this is your server, or you’ve noticed extension installs failing with a 403 since Oct 18, please let us know here and we’ll help you sort it out. The fix is usually to install extensions once at image build time, or to cache them, instead of on every start.

We’ll also add general download limits per IP soon, to protect the CDN from loops like this. Normal use, including CI, won’t be affected.

Thanks,
Gian

I don’t think this is exactly related, but I can’t download these recently updated extensions, they seem to return a 403 forbidden from any IP I tried. Other extensions I use download fine

https://ext.lucee.org/mail-extension-1.1.0.17.lex
https://ext.lucee.org/esapi-extension-3.1.0.1.lex

Thanks @nmdange, and you’re right, it’s not related to the IP block. The flat ext.lucee.org/<name>-<version>.lex path was never a documented or guaranteed location, so newer releases aren’t published there. Please use one of the supported locations instead:

  1. Lucee CDN: https://cdn.lucee.org/org/lucee/<name>/<version>/<name>-<version>.lex
    e.g. mail-extension-1.1.0.17.lex
  2. Maven Central: https://repo1.maven.org/maven2/org/lucee/<name>/<version>/<name>-<version>.lex
    e.g. mail-extension-1.1.0.17.lex and esapi-extension-3.1.0.1.lex
  3. GitHub Releases of the matching extension repo, e.g. extension-mail 1.1.0.17

Ah, thanks sorry if I missed an announcement.

I’m download the extensions while building a container image

I did a temporary workaround using the download links from the website like so:

ADD https://download.lucee.org/download.cfm?groupId=org.lucee&artifactId=esapi-extension&version=3.1.0.1 \

/opt/lucee/server/lucee-server/deploy/esapi-extension-3.1.0.1.lex

I assume the preference is to use Maven when downloading extensions as part of CI builds?

No worries @nmdange, there wasn’t an announcement for this. Yes, Maven is the preferred way. Starting in November, only final releases are deployed to Maven Central, with no betas or RCs there. Final releases are also attached to GitHub Releases, so for a plain download link that’s a good option too.

The best approach is to declare the extensions as Maven dependencies in your build. You can list several repositories there, so if one isn’t reachable the next one is used. Lucee itself resolves extensions the same way. A tiny example pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0">
  <modelVersion>4.0.0</modelVersion>
  <groupId>local</groupId>
  <artifactId>lucee-extensions</artifactId>
  <version>1</version>
  <packaging>pom</packaging>

  <repositories>
    <repository><id>central</id><url>https://repo1.maven.org/maven2/</url></repository>
    <repository><id>lucee</id><url>https://maven.lucee-services.com/</url></repository>
  </repositories>

  <dependencies>
    <dependency>
      <groupId>org.lucee</groupId>
      <artifactId>mail-extension</artifactId>
      <version>1.1.0.17</version>
      <type>lex</type>
    </dependency>
    <dependency>
      <groupId>org.lucee</groupId>
      <artifactId>esapi-extension</artifactId>
      <version>3.1.0.1</version>
      <type>lex</type>
    </dependency>
  </dependencies>
</project>

Then in your image build:

mvn -q dependency:copy-dependencies -DoutputDirectory=/opt/lucee/server/lucee-server/deploy

We’ll also write a recipe for this on docs.lucee.org and link it from the download page.

Thanks this is helpful. I was able to add a multistage build to my Dockerfile using the maven image on dockerhub to run the mvn command, then copy the output into the Lucee container image I’m building. Initial testing looks good.

I can see that it’s possible to browse the repositories directly which makes it easy for me to figure out what the correct extension names and versions are

https://repo1.maven.org/maven2/org/lucee/
https://maven.lucee-services.com/org/lucee/

Edit: I do see some extensions don’t match between the two (e.g. the administrator-extension has 1.0.0.9 on maven, but only two snapshot releases on lucee-services). I assume as all extensions get updated over time that discrepancy will go away.