M1 Selesai: Sinyal Jaringan, Worker Solver, Origin SDK.
M1 adalah milestone di mana "adaptif" berhenti menjadi kata
sifat di README
Mythic
dan menjadi mekanisme. Sampai kini server menetapkan harga
penyalahgunaan dengan satu instrumen — difficulty
proof-of-work. M1 menambahkan sinyal yang memungkinkannya
menetapkan harga atas siapa yang bertanya: fingerprint
TLS JA4 dan reputasi ASN masuk ke risk engine ber-capped,
solver PoW pindah dari main thread, dan origin bisa
memverifikasi vonis secara native di Node.js dan Python. Commit
bc87ed9 hingga c7e4fc3.
Postingan ini direvisi setelah audit internal menemukan
tujuh celah dalam klaim "M1 complete" yang asli. Enam
sudah diperbaiki di commit 067e9f7; satu tetap
jujur terbuka dan dinyatakan di bawah. Koreksinya
didokumentasikan di sini, bukan dikubur.
Mengapa sinyal — dan mengapa hanya advisory
Mitigasi bot hidup atau mati oleh sinyal, dan setiap sinyal sendirian itu lemah. Fingerprint JA4 bisa ditiru byte-per-byte oleh klien mana pun yang mau repot. ASN adalah heuristik — datacenter hari ini, residential proxy besok. Perlakukan salah satunya sebagai kebenaran mutlak dan kamu telah membangun blocklist dengan langkah tambahan.
Maka M1 memperlakukan setiap sinyal jaringan sebagai advisory: kontribusi kecil ber-capped yang bisa menaikkan harga sebuah request tetapi tak pernah bisa meloloskannya atau menghukumnya sendirian. Alirnya seperti ini:
GBR. 1 — Setiap sinyal bersifat advisory dan ber-capped. Tidak ada satu sinyal pun yang bisa meloloskan atau menghukum request sendirian.
JA4 fingerprinting: diskon, ber-capped, tidak dipercaya
ADR-0010.
Server membaca fingerprint JA4 dari
X-Mythic-JA4, yang diset oleh terminating proxy —
tidak pernah dari klien langsung, karena nilai dari klien
adalah attacker-controlled. Fingerprint dicocokkan dengan pola
JA4 browser yang dikenal; kecocokan memberi diskon risiko
kecil, ber-capped sehingga tak bisa sendirian meloloskan
challenge. Nilai malformed dan match hanya-prefix ditolak dari
jalur diskon sepenuhnya
(a8ce95a). Semua cap divalidasi saat startup;
nilai tuning yang hostile membuat server menolak melayani
(8f560bd).
Batasan yang dinyatakan: JA4 bersifat advisory. Klien yang meniru fingerprint browser asli byte-per-byte tak bisa dibedakan di lapisan ini. Diskonnya kecil justru karena sinyalnya bisa dipalsukan — ia menaikkan biaya scripting naif, tidak lebih.
ASN scoring: heuristik yang gagal tertutup
ADR yang sama. IP klien di-resolve ke Autonomous System Number
via database MaxMind GeoLite2-ASN
(MYTHIC_ASN_DB). ASN datacenter, hosting, dan
VPN-exit berkontribusi pada risiko; ASN ISP residensial tidak.
Lookup-nya nil-safe di seluruh jalur:
MYTHIC_ASN_DB yang kosong menonaktifkan sinyal
dengan bersih, sementara path yang dikonfigurasi tetapi gagal
dibuka bersifat fatal saat startup. Miskonfigurasi gagal
tertutup; ketiadaan mengalami degradasi diam-diam sesuai
desain — operator memilih untuk tidak mengaktifkannya.
Koreksi audit: test asli hanya mencakup mode
kegagalan (nil, path kosong, path buruk, IP invalid) — tidak
ada positive lookup yang pernah dieksekusi.
067e9f7 menambahkan TestASNLookupPositive
terhadap fixture .mmdb sintetis yang di-generate
di dalam repo (bukan data MaxMind berlisensi), mem-pin happy
path: range datacenter ter-skor, range residensial tidak.
Web Worker solver: PoW keluar dari main thread
Grind SHA-256 sebelumnya berjalan di main thread — pada
difficulty 24+ halaman membeku selama beberapa detik. SDK kini
menyertakan solveInWorker(), yang mengubah solver
yang self-contained menjadi string untuk Blob URL dan
menjalankannya di luar thread. Tidak ada file worker terpisah
untuk di-deploy; tidak perlu plugin bundler. Progress callback
menyala setiap 2048 iterasi;
AbortSignal mematikan worker dan mencabut URL:
export async function solveInWorker(
challenge: Challenge,
opts: SolveInWorkerOptions = {},
): Promise<Solution> {
// No Worker API (Node, SSR) → fall back to main thread.
if (typeof Worker === "undefined") {
const { solve } = await import("./pow");
return solve(challenge, opts);
}
const workerCode = `(${workerMain.toString()})()`;
const blob = new Blob([workerCode], { type: "application/javascript" });
const url = URL.createObjectURL(blob);
// …postMessage challenge, await solution, revoke URL
}
MythicClient menerima useWorker
(default true) dan otomatis memulai behavioral
collector saat konstruksi. Satu klien, satu alur, tanpa wiring
manual.
Celah yang diketahui, dinyatakan apa adanya: jalur
worker hanya pernah berjalan di implementasi Worker Bun —
tidak pernah di Chromium, Firefox, atau Safari. Ini
didokumentasikan di sdk/js/README.md, tidak
diklaim sebaliknya. Suite Playwright sempat dicoba;
environment build tidak bisa mengambil binary browser. Sampai
itu berubah, perilaku browser asli belum teruji dan tidak
diklaim.
Verifikasi origin: Node.js dan Python
Token keputusan hanya bisa diverifikasi di Go
(server/xtoken). Origin kini mendapat helper
native. sdk/js/src/verify.ts —
parsePublicKey(x) membungkus kunci mentah JWKS ke
DER SPKI; verifyToken(pub, token) memeriksa tanda
tangan Ed25519 atas byte payload mentah (tanpa pre-hash),
menegakkan re-encoding base64url kanonis, dan menolak token
kedaluwarsa:
// Canonical encodings only: re-encoding the decoded bytes
// must reproduce the input exactly. Go's base64 decoder
// silently discards unused low bits of a trailing character,
// so distinct strings can decode to the same token.
if base64.RawURLEncoding.EncodeToString(payload) != payloadPart ||
base64.RawURLEncoding.EncodeToString(sig) != sigPart {
return nil, fmt.Errorf("%w: non-canonical encoding", ErrInvalidToken)
}
sdk/python/mythic/verify.py — semantik yang sama
lewat paket cryptography:
parse_public_key, verify_token,
dataclass TokenClaims, TokenError
pada setiap penolakan. Python SDK kini di CI
(.github/workflows/sdk-python-ci.yml) dan berjalan
di bawah make test — sebelumnya tidak ada yang
mengeksekusinya otomatis.
Terverifikasi lintas bahasa dan di-commit:
e2e/crosslang.sh membuat token dari server Go yang
hidup dan memverifikasinya secara identik di Go, Python, dan
JS (dec=allow risk=6 di ketiganya).
Bukti
| Paket uji | Hasil |
|---|---|
go build ./... · go vet ./... | bersih |
go test -race -count=1 | 7/7 paket, 0 data race |
bun test (JS SDK) | 17/17 |
tsc --noEmit · bun run build | bersih |
pytest (Python SDK) | 6/6 |
e2e/crosslang.sh | Go, Python, JS sepakat pada token live |
Contract scoring-nya sendiri di-pin di kode — tuning hostile tidak bisa membocorkan skor di luar rentang ke dalam token bertanda tangan (temuan red-team H3, di-regression-test):
// The score is a 0-100 contract (token claim `risk`,
// dashboards, tuning docs). Hostile tuning must clamp
// here, not leak 500 into tokens (red-team H3).
if score > 100 {
score = 100
}
if score < 0 {
score = 0
}
Apa yang diubah audit
Setelah klaim "M1 complete" yang asli, audit dari nol (fresh
clone, setiap suite di-run ulang, adversarial pass atas jalur
verify) menemukan tujuh celah. Commit
067e9f7 ("fix(audit): close all 7 M1 audit gaps")
menutup enam di antaranya:
- Test positif ASN ditambahkan (sebelumnya hanya mode kegagalan).
- Hint behavioral kini dikirim di
verify()— sebelumnya collector berhenti setelah challenge, membuat parsing behavioral tahap-verify di server sebagai dead code dalam praktik. - Python SDK ditambahkan ke CI dan
make test. - E2E lintas bahasa di-commit (
e2e/crosslang.sh). docs/ROADMAP.mddikoreksi — ia masih menandai item M1 yang sudah selesai sebagai direncanakan.- Nama test worker yang menyesatkan diperbaiki (ia mengklaim mengetes fallback padahal mengetes jalur worker asli).
Yang ketujuh — test browser asli untuk Web Worker — tetap terbuka dan didokumentasikan sebagai celah yang diketahui, bukan diklaim selesai. Itulah keadaan M1 yang jujur saat ini.
Pertanyaan terbuka
Cakupan worker browser asli adalah satu item terbuka di atas. Selain itu: feed reputasi IP masih direncanakan (ROADMAP, ditandai jujur), dan M2 behavioral biometrics plus M5 shared keystore untuk verifikasi lintas node tetap menjadi milestone berikutnya. Sesuai aturan proyek, bypass setiap sinyal baru didokumentasikan sebelum sinyalnya dikirim — lihat ADR-0010 § "Bypasses".
— XEY LABS