diff --git a/src/db/storage.cpp b/src/db/storage.cpp
index 0a84560..bfa6b97 100644
--- a/src/db/storage.cpp
+++ b/src/db/storage.cpp
@@ -409,52 +409,6 @@ namespace db
       }
     }
 
-    //! \return a single instance of compiled-in checkpoints for lws
-    cryptonote::checkpoints const& get_checkpoints()
-    {
-      struct initializer
-      {
-        cryptonote::checkpoints data;
-
-        initializer()
-          : data()
-        {
-          data.init_default_checkpoints(lws::config::network);
-
-          std::string const* genesis_tx = nullptr;
-          std::uint32_t genesis_nonce = 0;
-
-          switch (lws::config::network)
-          {
-          case cryptonote::TESTNET:
-            genesis_tx = std::addressof(::config::testnet::GENESIS_TX);
-            genesis_nonce = ::config::testnet::GENESIS_NONCE;
-            break;
-
-          case cryptonote::STAGENET:
-            genesis_tx = std::addressof(::config::stagenet::GENESIS_TX);
-            genesis_nonce = ::config::stagenet::GENESIS_NONCE;
-            break;
-
-          case cryptonote::MAINNET:
-            genesis_tx = std::addressof(::config::GENESIS_TX);
-            genesis_nonce = ::config::GENESIS_NONCE;
-            break;
-
-          default:
-            MONERO_THROW(lws::error::bad_blockchain, "Unsupported net type");
-          }
-          cryptonote::block b;
-          cryptonote::generate_genesis_block(b, *genesis_tx, genesis_nonce);
-          crypto::hash block_hash = cryptonote::get_block_hash(b);
-          if (!data.add_checkpoint(0, epee::to_hex::string(epee::as_byte_span(block_hash))))
-            MONERO_THROW(lws::error::bad_blockchain, "Genesis tx and checkpoints file mismatch");
-        }
-      };
-      static const initializer instance;
-      return instance.data;
-    }
-
     //! \return Current block hash at `id` using `cur`.
     expect<crypto::hash> do_get_block_hash(MDB_cursor& cur, block_id id) noexcept
     {
@@ -469,7 +423,7 @@ namespace db
       cursor::blocks cur = MONERO_UNWRAP(lmdb::open_cursor<cursor::close_blocks>(txn, tbl));
 
       std::map<std::uint64_t, crypto::hash> const& points =
-        get_checkpoints().get_points();
+        storage::get_checkpoints().get_points();
 
       if (points.empty() || points.begin()->first != 0)
         MONERO_THROW(lws::error::bad_blockchain, "Checkpoints are empty/expected genesis hash");
@@ -558,7 +512,7 @@ namespace db
         return success();
       };
 
-      const std::uint64_t checkpoint = get_checkpoints().get_max_height();
+      const std::uint64_t checkpoint = lws::db::storage::get_checkpoints().get_max_height();
       const std::uint64_t anchor = lmdb::to_native(out.back().id);
 
       for (unsigned i = 1; i <= max_internal; ++i)
@@ -1155,6 +1109,51 @@ namespace db
     return nullptr;
   }
 
+  cryptonote::checkpoints const& storage::get_checkpoints()
+  {
+    struct initializer
+    {
+      cryptonote::checkpoints data;
+
+      initializer()
+        : data()
+      {
+        data.init_default_checkpoints(lws::config::network);
+
+        std::string const* genesis_tx = nullptr;
+        std::uint32_t genesis_nonce = 0;
+
+        switch (lws::config::network)
+        {
+        case cryptonote::TESTNET:
+          genesis_tx = std::addressof(::config::testnet::GENESIS_TX);
+          genesis_nonce = ::config::testnet::GENESIS_NONCE;
+          break;
+
+        case cryptonote::STAGENET:
+          genesis_tx = std::addressof(::config::stagenet::GENESIS_TX);
+          genesis_nonce = ::config::stagenet::GENESIS_NONCE;
+          break;
+
+        case cryptonote::MAINNET:
+          genesis_tx = std::addressof(::config::GENESIS_TX);
+          genesis_nonce = ::config::GENESIS_NONCE;
+          break;
+
+        default:
+          MONERO_THROW(lws::error::bad_blockchain, "Unsupported net type");
+        }
+        cryptonote::block b;
+        cryptonote::generate_genesis_block(b, *genesis_tx, genesis_nonce);
+        crypto::hash block_hash = cryptonote::get_block_hash(b);
+        if (!data.add_checkpoint(0, epee::to_hex::string(epee::as_byte_span(block_hash))))
+          MONERO_THROW(lws::error::bad_blockchain, "Genesis tx and checkpoints file mismatch");
+      }
+    };
+    static const initializer instance;
+    return instance.data;
+  }
+
   storage storage::open(const char* path, unsigned create_queue_max)
   {
     return {
@@ -1454,6 +1453,12 @@ namespace db
 
         if (*hash != chain.front())
         {
+          if (current <= get_checkpoints().get_max_height())
+          {
+            MERROR("Attempting rollback past last checkpoint; invalid daemon chain response");
+            return {lws::error::bad_blockchain};
+          }
+
           MONERO_CHECK(rollback_chain(this->db->tables, txn, *blocks_cur, db::block_id(current)));
           break;
         }
diff --git a/src/db/storage.h b/src/db/storage.h
index 43e2446..d958348 100644
--- a/src/db/storage.h
+++ b/src/db/storage.h
@@ -41,6 +41,7 @@
 #include "lmdb/key_stream.h"
 #include "lmdb/value_stream.h"
 
+namespace cryptonote { class checkpoints; }
 namespace lws
 {
 namespace db
@@ -167,6 +168,10 @@ namespace db
     {}
 
   public:
+
+    //! \return A single instance of compiled-in checkpoints for lws
+    static cryptonote::checkpoints const& get_checkpoints();
+
     /*!
       Open a light_wallet_server LDMB database.
 
diff --git a/tests/unit/db/chain.test.cpp b/tests/unit/db/chain.test.cpp
index 54e0cbc..aed7da8 100644
--- a/tests/unit/db/chain.test.cpp
+++ b/tests/unit/db/chain.test.cpp
@@ -28,6 +28,7 @@
 #include "chain.test.h"
 
 #include <cstdint>
+#include "checkpoints/checkpoints.h" // monero/src
 #include "db/storage.test.h"
 #include "error.h"
 
@@ -112,6 +113,23 @@ LWS_CASE("db::storage::sync_chain")
       lws_test::test_chain(lest_env, MONERO_UNWRAP(db.start_read()), last_block.id, fchain);
       EXPECT(get_account().scan_height == lws::db::block_id(std::uint64_t(last_block.id) + 1));
     }
+
+    SECTION("Fork past checkpoint")
+    {
+      const auto& checkpoints = lws::db::storage::get_checkpoints();
+      const auto& points = checkpoints.get_points();
+      EXPECT(!points.empty());
+
+      auto point = points.begin();
+      const crypto::hash fchain[3] = {
+        point->second,
+        crypto::rand<crypto::hash>(),
+        crypto::rand<crypto::hash>()
+      };
+
+      const auto sync_result = db.sync_chain(lws::db::block_id(point->first), fchain);
+      EXPECT(sync_result == lws::error::bad_blockchain);
+    }
   }
 }
 
diff --git a/tests/unit/scanner.test.cpp b/tests/unit/scanner.test.cpp
index c2d239a..dd4ca0b 100644
--- a/tests/unit/scanner.test.cpp
+++ b/tests/unit/scanner.test.cpp
@@ -282,8 +282,6 @@ namespace
 
 LWS_CASE("lws::scanner::sync and lws::scanner::run")
 {
-   mlog_set_log_level(4);
-
   cryptonote::account_keys keys{};
   crypto::generate_keys(keys.m_account_address.m_spend_public_key, keys.m_spend_secret_key);
   crypto::generate_keys(keys.m_account_address.m_view_public_key, keys.m_view_secret_key);