Search This Blog


Monday, September 20, 2010

Clojure Swank Server is Insecure by Default : Use a Firewall

As far as the maven clojure plugin goes, which is what I personally use, this issue is fixed in version 1.3.4, which is now publicly available. 

I'm told that modern leiningen setups open local ports, and that Phil has patched swank-clojure so that a local port is the default, so as long as you use latest versions of things this issue should be dead.

If you start your swank servers from old pom.xmls or project.cljs, you should probably still be careful just in case they pull in old versions of swank-clojure and clojure-maven-plugin. Update them if you can.

Well done to Phil and Mark, who fixed this within hours of it being noticed. Thanks guys!

A warning to anyone using SLIME/SWANK with clojure.

clojure-swank appears to open its server on the public port 4005 by default.
Note, not the loopback port 4005, the real one, visible to everyone.

If you don't have a firewall set up, then you're not only giving everyone on your local network the ability to execute arbitrary code on your machine, you're giving them a very nice interface with which to do it.

This appears to be the default behaviour of:

(swank.swank/start-server "/tmp/swank-port")
Connection opened on local port  34633
#<ServerSocket ServerSocket[addr=,port=0,localport=34633]>

If you want a loopback port, then you have to say:

(swank.swank/start-server "/tmp/swank-port" :host "localhost")
Connection opened on local port  47233
#<ServerSocket ServerSocket[addr=localhost/,port=0,localport=47233]>

And this behaviour appears to be inherited by the maven-clojure-plugin, and by leiningen using certain project files.

It does appear that a newly-created leiningen project opens the loopback port, but that's a property of project.clj, not of the leiningen tool itself.

If you're using swank and clojure, run a firewall, because you really don't want to open this port by accident on a hostile network:

Under Ubuntu, that's a simple as:

$ sudo ufw enable

To block everything, and:

$ sudo ufw allow 22

To reopen port 22 to allow ssh connections.

You can still use a local emacs to interact with a remote machine using this command to tunnel the remote port 4005 to your local port 4005 before using M-x slime-connect.

$ ssh -2 -N -f -L 4005:localhost:4005 user@remotebox


  1. The heroic talios has committed a patch to the maven-clojure-plugin which makes the server open on a loopback port instead. It's currently on a separate branch, but will presumably get merged and released soon.

  2. > And this behaviour appears to be inherited by the maven-clojure-plugin, and by leiningen using certain project files.

    Could you elaborate on this? I don't know of a way to get lein swank to bind to port without asking specifically for it.

    swank-clojure is actually a network server. It happens to be integrated into development tools, but by itself it's not a dev tool.

    Normally when you start a network server, it's accessible to the network unless you specifically specify an interface to bind to, just like clojure.contrib.socket-repl. I'm not sure why you would expect embedding a swank server to be different.

    But it appears that people are being confused about this, so I've changed the behaviour of the zero-arity version of start-repl.

  3. Hi Phil,

    Thanks for making the change!

    I noticed the open port when I downloaded penumbra, which has the following project.clj file:

    (defproject penumbra "0.6.0-SNAPSHOT"
    :description "An idiomatic wrapper for OpenGL"
    :dependencies [[slick-util "1.0.0"]
    [cantor "0.2.1"]
    [org.clojure/clojure "1.2.0"]
    [org.clojure/clojure-contrib "1.2.0"]]
    :native-dependencies [[penumbra/lwjgl "2.4.2"]]
    :dev-dependencies [[native-deps "1.0.4"]
    [autodoc "0.7.1"]
    [lein-clojars "0.5.0-SNAPSHOT"]
    [leiningen/lein-swank "1.1.0"]])

    Running lein swank made a publicly accessible swank port, which freaked me out a bit when I realized. Then I noticed that mvn clojure:swank did the same thing.

    I've only ever used swank to collaborate with slime. I'm not sure how else it would be used.

    From this restricted point of view, it occurs to me that the failure mode if the port is local would be 'Oh, I have to use ssh to tunnel in from outside', whereas the failure mode if it's open and you aren't running a firewall could be bad.

    By the way, what is the difference between the technomancy/swank-clojure and the jochu/swank-clojure versions? I see that technomancy is the version on clojars, so presumably the one that everyone will use by default.

    Anyway, it's all marvellous! Thank you very much for making it!

  4. OK, it sounds like penumbra is just depending on an old version of swank-clojure; this has been fixed in the context of Leiningen since April. Good point about the failure modes; definitely good to err on the safe side.

    > I've only ever used swank to collaborate with slime. I'm not sure how else it would be used.

    Right, but if you are embedding swank in your application you are presumably doing it to share a repl with Emacs outside the context of local development, since with local development it's more convenient to use your build tool.

    The jochu version is just an old version; it's been deprecated since I took over maintenance of the project a year or so ago.