Purposefully fail select with no where
Given the evil query is long-running you don't have to stress out about trapping it synchronously with its execution. It would be good if the approach was relatively lightweight and easy to remove.
I'd go with an agent job, executed on a schedule likely to overlap with the evil query. Once every few minutes should suffice given the evil query runs for thirty minutes or so.
This job examines all currently-running work by querying sys.dm_exec_requests. If start_time is more than a few minutes ago you likely have your culprit. Find the actual SQL text for each piece of work.
declare @query   nvarchar(max);
declare @victim  smallint;

select
    @query  = s.text,
    @victim = r.session_id
from sys.dm_exec_requests as r
cross apply sys.dm_exec_sql_text(r.sql_handle) as s;

A little bit of SUBSTRING(), CHARINDEX() and LIKE will confirm you're dealing with a &quot;SELECT&quot; without a &quot;WHERE&quot;. If the evil query is submitted in a batch with other queries you'll have to be more careful when parsing the SQL text.
It can then be ended with KILL(@victim). There is a risk that, between being identified and killed, the evil query finishes and its session id is re-allocated to a &quot;good&quot; query. If evil's execution time is consistently long you can use start_time to reduce this risk. You know your environment and what's acceptable.