Skip to content

Commit df6ee42

Browse files
ralyodioclaude
andcommitted
feat(dns filter): add ThreatFox C2 and malware domains as a default list
New category c2: abuse.ch ThreatFox's host file (~30,000 botnet C2 and payload domains reported in the last days), on by default beside URLhaus malware. Existing configs keep their categories; only a fresh 'dns filter on' or 'filter add c2' turns it on, and 'dns filter update' fetches it like the others. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 02e4f5b commit df6ee42

3 files changed

Lines changed: 13 additions & 5 deletions

File tree

‎README.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2147,7 +2147,7 @@ names that exist only to advertise, track, mine or phish, before a connection is
21472147
ever opened. Nothing is filtered until you ask for it.
21482148

21492149
```sh
2150-
moshcode dns filter on # ads, malware, phishing, mining
2150+
moshcode dns filter on # ads, malware, c2, phishing, mining
21512151
moshcode dns filter update # fetch the lists — nothing downloads on its own
21522152
moshcode dns filter # what is on, and what it has blocked
21532153
moshcode dns filter test ads.example.com # would this be blocked, and by which rule
@@ -2158,6 +2158,7 @@ moshcode dns filter allow news.example # never block it, whatever any list s
21582158
|---|---|
21592159
| `ads` | ads and trackers — StevenBlack unified, on by default |
21602160
| `malware` | hosts serving malware — URLhaus, on by default |
2161+
| `c2` | botnet command-and-control and payload domains — ThreatFox, on by default |
21612162
| `phishing` | Phishing Army, on by default |
21622163
| `mining` | in-browser cryptominers, on by default |
21632164
| `adult` `gambling` `social` `fakenews` | opt in by name with `filter add <list>` |

‎src/dns-filter.mjs‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ export const FILTER_CATALOG = [
5555
url: "https://urlhaus.abuse.ch/downloads/hostfile/",
5656
note: "URLhaus, abuse.ch — hosts serving malware payloads right now",
5757
},
58+
{
59+
id: "c2",
60+
title: "Botnet C2 and malware hosts",
61+
format: "hosts",
62+
url: "https://threatfox.abuse.ch/downloads/hostfile/",
63+
note: "ThreatFox, abuse.ch — command-and-control and payload domains reported in the last days",
64+
},
5865
{
5966
id: "phishing",
6067
title: "Phishing",
@@ -102,11 +109,11 @@ export const FILTER_CATALOG = [
102109
export const CATALOG_BY_ID = new Map(FILTER_CATALOG.map((entry) => [entry.id, entry]));
103110

104111
/**
105-
* What `filter on` turns on when told nothing else: the four categories that
112+
* What `filter on` turns on when told nothing else: the five categories that
106113
* block things nobody asks for. Everything that blocks content a person might
107114
* actually want — adult, gambling, social, fakenews — is opt-in by name.
108115
*/
109-
export const DEFAULT_CATEGORIES = ["ads", "malware", "phishing", "mining"];
116+
export const DEFAULT_CATEGORIES = ["ads", "malware", "c2", "phishing", "mining"];
110117

111118
/**
112119
* How a blocked name is answered.

‎test/dns-filter-cli.test.mjs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ test("`on` writes the default categories and names the ones never fetched", asyn
5555
const dir = await tempDir(t);
5656
const { code, text } = await run(["on"], dir);
5757
assert.equal(code, 0);
58-
assert.match(text, /filtering on — ads, malware, phishing, mining/);
58+
assert.match(text, /filtering on — ads, malware, c2, phishing, mining/);
5959
// The state that would otherwise read as protection.
6060
assert.match(text, /never been fetched/);
6161
assert.match(text, /moshcode dns filter update/);
@@ -93,7 +93,7 @@ test("`off` keeps the lists and the rules", async (t) => {
9393
const config = await readConfig(dir);
9494
assert.equal(config.enabled, false);
9595
assert.deepEqual(config.block, ["tracker.example"]);
96-
assert.deepEqual(config.categories, ["ads", "malware", "phishing", "mining"]);
96+
assert.deepEqual(config.categories, ["ads", "malware", "c2", "phishing", "mining"]);
9797
});
9898

9999
test("an unknown mode or list is refused rather than half-applied", async (t) => {

0 commit comments

Comments
 (0)