hashview / hashview/hashview

Audit: latin-1 usage — 1 data-corruption bug on hashfile download + cleanups

Open
#357 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug python
Dominant language
Python
Stars
399
Forks
52
Avg merge
21h 39m
Merged PRs (30d)
79

Description

Summary

A fan-out code review of every latin-1/encoding call site was done to answer "is latin-1 ever the right choice?" It is correct in exactly one place (lossless $HEX[...] byte handling) but is a real data-corruption bug on the hashfile download path and a couple of low-priority cleanups elsewhere.

Motivating case: international customer pwdumps whose cracked plaintext/usernames contain non-Latin-1 characters (emoji, CJK, Cyrillic).

1. HIGH — silent data corruption on hashfile download

hashview/hashfiles/routes.py:271

buf = io.BytesIO(body.encode('latin-1', errors='replace'))

body contains cracked plaintext/usernames stored as real Unicode (post hex→UTF-8 backfill). Any codepoint > U+00FF is silently replaced with ? — irreversible loss in the exported file, no error surfaced. errors='replace' masks the wrong-codec choice.

Fix: buf = io.BytesIO(body.encode('utf-8')) and set charset=utf-8 on the download send_file mimetype (~line 274).

2. LOW — misleading dead code

hashview/jobs/routes.py:726 — commented-out bytes.fromhex(c[1].username).decode('latin-1') contradicts the current UTF-8 plain-text storage contract; running it today would ValueError on non-hex usernames. The live path (jobs_assign_notification_hashes, ~routes.py:776-810) already handles this correctly.

Fix: Delete the commented block; optionally leave a one-line pointer to jobs_assign_notification_hashes.

3. INFO — consistency wart (not a bug)

hashview/auth/service.py:95, hashview/users/routes.py:190, hashview/users/routes.py:260.decode('latin-1') on bcrypt output. Bcrypt output is pure ASCII (verified: 0/300 random hashes had a byte > 0x7F), so this is byte-identical to utf-8 — zero runtime/security effect — but it misleadingly implies non-ASCII and diverges from hashview/setup/__init__.py:318 (utf-8).

Fix (optional, behavior-preserving): align the three sites to .decode('utf-8').

Sites confirmed correct — no change needed

  • hashview/utils/utils.py:585 — latin-1 fallback decode of non-UTF-8 $HEX[...] bytes for length/char-class analysis. The one legitimate use: latin-1 is the only 8-bit codec that round-trips all 256 byte values 1:1, never crashes, never corrupts.
  • hashview/utils/utils.py:457 & :488 — UTF-16LE + surrogatepass for NTLM/MSSQL hashing (correctly avoids latin-1).
  • hashview/utils/utils.py:611 + hashview/api/routes.py:1834 — ingestion via surrogateescape + $HEX (correctly avoids latin-1; never crashes on international pwdumps).
  • migrations/versions/a671bad25f89_fix_schema_drift.py:67mysql_default_charset='latin1' in downgrade() only, matching legacy schema for drift reconciliation.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with hashview/hashfiles/routes.py:271-274 and verify that downloaded international plaintext and usernames remain intact with a UTF-8 charset. Then review the commented block near hashview/jobs/routes.py:726 and the bcrypt decode sites in hashview/auth/service.py:95 and hashview/users/routes.py:190,260. Done means the corruption path uses UTF-8, misleading dead code is removed, and the optional decode cleanups are behavior-preserving.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
62/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.