diff --git a/Data/Hashable.hs b/Data/Hashable.hs
--- a/Data/Hashable.hs
+++ b/Data/Hashable.hs
@@ -27,6 +27,9 @@
 
 module Data.Hashable
     (
+      -- * Hashing and security
+      -- $security
+
       -- * Computing hash values
       hash
     , Hashable(..)
@@ -219,3 +222,45 @@
 -- >         s `hashWithSalt`
 -- >         yr `hashWithSalt`
 -- >         mo `hashWithSalt` dy
+
+-- $security
+-- #security#
+--
+-- Applications that use hash-based data structures to store input
+-- from untrusted users can be susceptible to \"hash DoS\", a class of
+-- denial-of-service attack that uses deliberately chosen colliding
+-- inputs to force an application into unexpectedly behaving with
+-- quadratic time complexity.
+--
+-- This library uses the SipHash algorithm to hash strings. SipHash
+-- was designed to be more robust against collision attacks than
+-- traditional hash algorithms, while retaining good performance.
+--
+-- To further mitigate the risk from collision attacks, this library
+-- provides an environment variable named @HASHABLE_SALT@ that allows
+-- the default salt used by the 'hash' function to be chosen at
+-- application startup time.
+--
+-- * In the normal case, the environment variable is not set, and a
+--   fixed salt is used that does not vary between runs. (This choice
+--   can be made permanent by building this package with the
+--   @-ffixed-salt@ flag.)
+--
+-- * If the value is the string @random@, the system's cryptographic
+--   pseudo-random number generator will be used to supply a salt.
+--   While this may offer added security, it can also violate the
+--   assumption of some Haskell libraries that expect the results of
+--   'hash' to be stable across application runs. Choose this
+--   behaviour with care (and testing)!
+--
+-- * When the value is an integer (prefixed with @0x@ for hexadecimal),
+--   it will be used as the salt.
+--
+-- If @HASHABLE_SALT@ cannot be parsed, then the first time that a
+-- call to 'hash' is made, the application will halt with an
+-- informative error message.
+--
+-- (Implementation note: while SipHash is used for strings, a
+-- faster&#8212;and almost certainly less secure&#8212;algorithm is
+-- used for numeric types, on the assumption that strings are much
+-- more likely as a hash DoS attack vector.)
diff --git a/Data/Hashable/Class.hs b/Data/Hashable/Class.hs
--- a/Data/Hashable/Class.hs
+++ b/Data/Hashable/Class.hs
@@ -107,8 +107,12 @@
 #endif
 
 #ifndef FIXED_SALT
+import Control.Exception (tryJust)
+import Control.Monad (guard)
 import Data.Hashable.RandomSource (getRandomBytes_)
 import Foreign.Marshal.Alloc (alloca)
+import System.Environment (getEnv)
+import System.IO.Error (isDoesNotExistError)
 #endif
 
 #include "MachDeps.h"
@@ -121,20 +125,32 @@
 -- | A default salt used in the implementation of 'hash'.
 --
 -- To reduce the probability of hash collisions, the value of the
--- default salt will vary from one program invocation to the next
+-- default salt may vary from one program invocation to the next
 -- unless this package is compiled with the @fixed-salt@ flag set.
-defaultSalt :: Int
+defaultSalt, fixedSalt :: Int
 
+fixedSalt = 0xdc36d1615b7400a4
+{-# INLINE fixedSalt #-}
+
 #ifdef FIXED_SALT
 
-defaultSalt = 0xdc36d1615b7400a4
+defaultSalt = fixedSalt
 {-# INLINE defaultSalt #-}
 
 #else
 
-defaultSalt = unsafePerformIO . alloca $ \p -> do
-                getRandomBytes_ "defaultSalt" p (sizeOf (undefined :: Int))
-                peek p
+defaultSalt = unsafePerformIO $ do
+  let varName = "HASHABLE_SALT"
+  msalt <- tryJust (guard . isDoesNotExistError) $ getEnv varName
+  case msalt of
+    Right "random" -> alloca $ \p -> do
+      getRandomBytes_ "defaultSalt" p (sizeOf (undefined :: Int))
+      peek p
+    Right s -> case reads s of
+                 [(salt, "")] -> return salt
+                 _            -> fail $ "Fatal: cannot parse contents of " ++
+                                        varName ++ " environment variable"
+    Left _ -> return fixedSalt
 {-# NOINLINE defaultSalt #-}
 
 #endif
@@ -182,16 +198,9 @@
 -- | Return a hash value for the argument. Defined in terms of
 -- 'hashWithSalt' and a default salt.
 --
--- At application startup time, the default salt is initialized with a
--- new value from the system's cryptographic pseudo-random number
--- generator. This means that the result of 'hash' will vary from one
--- application run to the next.
---
--- If you need hashes that do not vary from run to run, use
--- 'hashWithSalt' instead, and supply a salt of your choosing. (Be
--- aware that if you hash untrusted, uncontrolled input data using a
--- fixed salt, you may expose your application to hash collision
--- attacks.)
+-- (See the \"Hashing and security\" section of the
+-- "Data.Hashable#security" documentation for an important note on
+-- working safely with untrusted user input.)
 hash :: Hashable a => a -> Int
 hash = hashWithSalt defaultSalt
 
diff --git a/benchmarks/Benchmarks.hs b/benchmarks/Benchmarks.hs
--- a/benchmarks/Benchmarks.hs
+++ b/benchmarks/Benchmarks.hs
@@ -78,10 +78,12 @@
         fnvHash (PS fp off len) =
             inlinePerformIO . withForeignPtr fp $ \ptr ->
             return $! fnv_hash (ptr `plusPtr` off) (fromIntegral len) 2166136261
-#ifdef HAVE_SSE
+#ifdef HAVE_SSE2
         sse2SipHash (PS fp off len) =
             inlinePerformIO . withForeignPtr fp $ \ptr ->
             return $! sse2_siphash k0 k1 (ptr `plusPtr` off) (fromIntegral len)
+#endif
+#ifdef HAVE_SSE41
         sse41SipHash (PS fp off len) =
             inlinePerformIO . withForeignPtr fp $ \ptr ->
             return $! sse41_siphash k0 k1 (ptr `plusPtr` off) (fromIntegral len)
@@ -201,7 +203,7 @@
           , bench "512" $ whnf cSipHash24 bs512
           , bench "2^20" $ whnf cSipHash24 bs1Mb
           ]
-#ifdef HAVE_SSE
+#ifdef HAVE_SSE2
         , bgroup "sse2SipHash"
           [ bench "5" $ whnf sse2SipHash bs5
           , bench "8" $ whnf sse2SipHash bs8
@@ -211,6 +213,8 @@
           , bench "512" $ whnf sse2SipHash bs512
           , bench "2^20" $ whnf sse2SipHash bs1Mb
           ]
+#endif
+#ifdef HAVE_SSE41
         , bgroup "sse41SipHash"
           [ bench "5" $ whnf sse41SipHash bs5
           , bench "8" $ whnf sse41SipHash bs8
@@ -261,9 +265,11 @@
     :: CInt -> CInt -> Word64 -> Word64 -> Ptr Word8 -> CSize -> Word64
 foreign import ccall unsafe "hashable_siphash24" c_siphash24
     :: Word64 -> Word64 -> Ptr Word8 -> CSize -> Word64
-#ifdef HAVE_SSE
+#ifdef HAVE_SSE2
 foreign import ccall unsafe "hashable_siphash24_sse2" sse2_siphash
     :: Word64 -> Word64 -> Ptr Word8 -> CSize -> Word64
+#endif
+#ifdef HAVE_SSE41
 foreign import ccall unsafe "hashable_siphash24_sse41" sse41_siphash
     :: Word64 -> Word64 -> Ptr Word8 -> CSize -> Word64
 #endif
diff --git a/cbits/siphash.c b/cbits/siphash.c
--- a/cbits/siphash.c
+++ b/cbits/siphash.c
@@ -109,8 +109,10 @@
 
     if (edx & (1 << 26))
 	_siphash24 = hashable_siphash24_sse2;
+#if defined(HAVE_SSE41)
     else if (ecx & (1 << 19))
 	_siphash24 = hashable_siphash24_sse41;
+#endif
     else
 	_siphash24 = plain_siphash24;
 }
diff --git a/hashable.cabal b/hashable.cabal
--- a/hashable.cabal
+++ b/hashable.cabal
@@ -1,5 +1,5 @@
 Name:                hashable
-Version:             1.2.0.2
+Version:             1.2.0.3
 Synopsis:            A class for types that can be converted to a hash value
 Description:         This package defines a class, 'Hashable', for types that
                      can be converted to a hash value.  This class
@@ -31,6 +31,10 @@
   Description: Do we use a single fixed salt every time the program runs?
   Default: False
 
+Flag sse41
+  Description: Do we want to assume that a target supports SSE 4.1?
+  Default: False
+
 Library
   Exposed-modules:   Data.Hashable
   Other-modules:     Data.Hashable.Class
@@ -53,9 +57,13 @@
                      cbits/siphash.c
   if arch(i386)
     C-sources:       cbits/siphash-sse2.c
-                     cbits/siphash-sse41.c
-    CC-options:      -msse2 -msse4.1
+    CC-options:      -msse2
 
+    if flag(sse41)
+      CPP-Options:   -DHAVE_SSE41
+      CC-options:    -msse41
+      C-sources:     cbits/siphash-sse41.c
+
   Ghc-options:       -Wall
   if impl(ghc >= 6.8)
     Ghc-options: -fwarn-tabs
@@ -117,11 +125,16 @@
     benchmarks/cbits/inthash.c
 
   if arch(i386) || arch(x86_64)
-    cpp-options: -DHAVE_SSE
-    cc-options: -msse2 -msse4.1
+    cpp-options: -DHAVE_SSE2
+    cc-options: -msse2
     c-sources:
       cbits/siphash-sse2.c
-      cbits/siphash-sse41.c
+
+    if flag(sse41)
+      cpp-options: -DHAVE_SSE41
+      cc-options: -msse4.1
+      c-sources:
+        cbits/siphash-sse41.c
 
   Ghc-options:       -Wall -O2
   if impl(ghc >= 6.8)
