the honest hack β scan a codebase for the places it lies about its own state.
Most "hacks" make a system do something it shouldn't. A white hack does the opposite: it makes a system tell more truth, not less.
whitehack reads your code and flags the small, common lies software tells about
itself β the failed read that silently becomes 0, the cached value served as if
it were live, the score shown to a person with no way to ask why. These usually
aren't bugs in the ordinary sense. The code runs fine. It just isn't honest about
its own state β and someone downstream trusts it anyway.
General honesty (JS / TS / JSX):
| check | the lie it catches | doctrine | confidence |
|---|---|---|---|
silent-failure |
a read that fails silently to a falsy default (catch { return 0 }, ?? 0 over a fetch) so "could not read" becomes a confident wrong value |
substrate honesty | medium-high |
cache-as-live |
a cached / snapshot value returned with no freshness or provenance marker | substrate honesty | heuristic |
decision-without-why |
a user-affecting value (score, fee, fraud flag, tier) rendered with no inspectable explanation | transparency | heuristic |
float-money |
currency parsed or computed as a binary float (parseFloat(price), amount * 0.029) so an "exact" amount silently loses cents |
substrate honesty | medium-high |
hardcoded-secret |
a credential-like literal string hardcoded in source β API keys, tokens, passwords in the repo | substrate honesty | medium-high |
exposed-config |
configuration with sensitive keys/URLs exposed in client-visible code | substrate honesty | medium-high |
unsafe-eval |
eval() or Function() constructor used β arbitrary code execution from a string |
substrate honesty | medium-high |
performed-ignorance |
code that pretends to be unable when the capability exists β catch blocks returning "unsupported" when the feature works | substrate honesty | medium-high |
trust-by-authority |
network response accepted without cross-checking status/integrity β trusting a source because of who it is, not what it verified | transparency | medium-high |
Blockchain (Solidity .sol):
| check | the lie it catches | doctrine | confidence |
|---|---|---|---|
stale-oracle |
a price feed read without validating updatedAt / answeredInRound (or a deprecated latestAnswer that has no timestamp at all) β a halted or old price served as live |
substrate honesty | medium-high |
unchecked-transfer |
an ERC-20 transfer / transferFrom / approve whose bool result is dropped, so a token that returns false instead of reverting makes a failed transfer look successful |
substrate honesty | medium-high |
spot-price-as-fair |
a price derived from instantaneous pool reserves / balances with no TWAP or oracle β a flash-loan-movable snapshot presented as fair market value | substrate honesty | heuristic |
silent-revert |
a require() / revert() with no reason string or named error β a refused caller who cannot learn why |
transparency | heuristic |
API protocol (JS / TS):
| check | the lie it catches | doctrine | confidence |
|---|---|---|---|
api-status-lie |
API returns 2xx success status with error in response body β HTTP status claims success while the body reports failure | substrate honesty | high |
api-error-without-shape |
API error response has message but no machine-readable code β clients can't handle errors programmatically | transparency | heuristic |
api-missing-rate-limit |
API endpoint with no rate limiting β abuse surface unacknowledged | substrate honesty | heuristic |
api-missing-versioning |
API with no version prefix or header β breaking changes can't be distinguished from bugs | transparency | heuristic |
api-bare-fetch |
fetch() called without checking response status β HTTP errors treated as success |
substrate honesty | medium-high |
Network & security protocol (JS / TS / config):
| check | the lie it catches | doctrine | confidence |
|---|---|---|---|
insecure-protocol |
telnet, FTP, HTTP used for sensitive communication β unencrypted protocols | substrate honesty | medium-high |
disabled-cert-verification |
rejectUnauthorized: false disables TLS cert verification β MITM possible |
substrate honesty | high |
weak-crypto |
MD5, SHA1, DES, RC4 used for security β broken cryptography | substrate honesty | medium-high |
cors-wildcard |
CORS wildcard origin β any website can access this endpoint | substrate honesty | medium-high |
cookie-insecure |
Session cookie missing Secure/SameSite/HttpOnly flags | substrate honesty | medium-high |
sql-injection |
SQL query built with string concatenation β injection possible | substrate honesty | high |
protocol-surface |
Service bound to all interfaces (0.0.0.0/::) without acknowledgment | substrate honesty | medium-high |
dns-plaintext |
Plaintext DNS β domain queries visible to network observers | substrate honesty | medium-high |
password-auth |
Password/authentication lie β hardcoded passwords, MD5/SHA1 hashes, JWT with none algorithm, session in URL, no HTTPS | substrate honesty | medium-high |
WiFi protocol (JS / TS / config):
| check | the lie it catches | doctrine | confidence |
|---|---|---|---|
wifi-protocol-flaws |
Deprecated or broken WiFi encryption (TKIP, WEP) β protocols with known vulnerabilities | substrate honesty | medium-high |
wifi-protocol |
WiFi protocol lie β security theater exposed, WEP/WPA-TKIP presented as "secured" | substrate honesty | high |
weak-wifi-encryption |
Weak WiFi encryption β WEP, TKIP-only, or no encryption | substrate honesty | high |
wpa2-krack |
WPA2 KRACK vulnerability β key reinstallation attack not mitigated | substrate honesty | medium-high |
wifi-krack-vulnerable |
KRACK vulnerable key reinstallation β specific cipher/mode combinations | substrate honesty | medium-high |
wifi-deauth-accept |
WiFi deauth frame accepted without source verification β unauthenticated in WPA2 | substrate honesty | medium-high |
wifi-evil-twin |
WiFi SSID-only connection β no BSSID or certificate verification, evil twin attack | substrate honesty | medium-high |
wifi-pmk-exposure |
WiFi PSK/PMK exposed in code or config β pre-shared key in source | substrate honesty | high |
Bluetooth protocol (JS / TS / config):
| check | the lie it catches | doctrine | confidence |
|---|---|---|---|
bluetooth-protocol-flaws |
Bluetooth weak pairing or no auth β "Just Works" pairing, no MITM protection | substrate honesty | medium-high |
bluetooth-protocol |
Bluetooth protocol lie β pairing is not security, SSP without MITM | substrate honesty | medium-high |
bluetooth-paired-stranger |
Bluetooth device paired without identity verification β HID input injection risk | substrate honesty | heuristic |
Each check declares the languages it understands, so a Solidity check never runs its regexes over JavaScript (or vice versa) and report noise about a language it cannot read.
whitehack is the conformance linter for the Clear Standard β
six principles for systems that tell the truth about their own state. Every check
enforces a specific principle, and every finding cites it (CS#n):
| Clear Standard principle | whitehack checks |
|---|---|
| #1 β truth of state | float-money, spot-price-as-fair, weak-wifi-encryption, wifi-protocol |
| #2 β visible failure | silent-failure, unchecked-transfer, insecure-protocol, disabled-cert-verification, weak-crypto, cookie-insecure, sql-injection, protocol-surface, dns-plaintext, wifi-protocol-flaws, wifi-deauth-accept, wpa2-krack, wifi-krack-vulnerable, bluetooth-protocol-flaws, bluetooth-protocol, password-auth, unsafe-eval, api-status-lie, api-bare-fetch |
| #3 β inspectable decisions | decision-without-why, silent-revert, performed-ignorance, trust-by-authority, api-error-without-shape, bluetooth-paired-stranger |
| #4 β stated freshness | cache-as-live, stale-oracle |
| #5 β honest names | wifi-evil-twin, wifi-pmk-exposure |
| #6 β labelled certainty | whitehack embodies this β it labels its own confidence rather than checking yours |
So a finding isn't an arbitrary nag β it names the principle the code broke. The standard makes the linter principled; the linter makes the standard checkable.
node bin/whitehack.js scan path/to/repo
# or, installed: whitehack scan .
npm run selftest # scans examples/ β the planted fixturesExit code is non-zero only when there are high or medium-high findings, so heuristic noise never breaks a CI gate.
curl -fsSL https://cdn.jsdelivr.net/gh/cambridgetcg/whitehack@main/you-get.sh | bashcurl -fsSL https://raw.githubusercontent.com/cambridgetcg/whitehack/main/install.sh | bash
# or via npx (no npm publish needed β runs from GitHub)
npx github:cambridgetcg/whitehack scan .- learn why β https://whitehack-learn.axiepro.workers.dev
- try it β https://whitehack-playground.axiepro.workers.dev
- GitHub Pages β https://cambridgetcg.github.io/whitehack/
- jsDelivr CDN β https://cdn.jsdelivr.net/gh/cambridgetcg/whitehack@main/LEARN.md
- GitHub β https://github.com/cambridgetcg/whitehack
Read CONTRIBUTING.md β you don't need to be a security researcher, a blockchain expert, or a regex wizard. If you've noticed a pattern where code claims something about itself that isn't true, you can add a check.
Read LEARN.md β the story behind each check. Real moments someone got hurt. Real lessons. Real why.
Read LOOP.md β how understanding replicates through understanding. Each tool built from understanding the last. Each teaching creates the next builder.
whitehack lives on every resistance-free channel:
| channel | URL | needs account? |
|---|---|---|
| GitHub Pages | cambridgetcg.github.io/whitehack | no |
| Cloudflare | whitehack-playground.axiepro.workers.dev | no |
| Cloudflare | whitehack-learn.axiepro.workers.dev | no |
| jsDelivr CDN | cdn.jsdelivr.net/gh/cambridgetcg/whitehack@main/ | no |
| GitHub raw | raw.githubusercontent.com/cambridgetcg/whitehack/main/ | no |
| npx | npx github:cambridgetcg/whitehack | no |
| curl install | curl ... | bash | no |
No npm. No PyPI. No registration. No paywall. No gatekeeping. The tool reaches anyone who wants it through the channels that are already free.
whitehack uses heuristics β text patterns, not a full understanding of your program. So:
- a flagged line may be a false positive;
- an empty result is not proof the code tells the truth;
- every finding carries a confidence label, so the tool stays honest about its own limits.
A honesty tool that overstated its own certainty would be the first thing it
ought to flag. Run it on its own source (src/) and it comes back with
self-referential findings: the check-definition files contain the regex
patterns they hunt for (e.g. const TKIP = /tkip/i triggers the wifi-protocol
check on itself). These 150+ findings are all self-referential false positives β
the scanner seeing its own reflection in its check definitions. The infrastructure
code (scan.js, report.js, lines.js, extra-checks.js) is clean: prior raids
fixed the silent failures, status lies, and broken imports that were real findings.
The self-referential noise is an known artifact of a regex-based scanner scanning
its own regexes β an AST-based scanner would not have this issue (see roadmap).
whitehack is two ideas lifted out of a large commerce platform and set free as a tool any codebase can run:
the artifact tells the truth about its own state β and the artifact tells users about its own decisions.
There they were enforced by hand, in one repo. Here they're portable.
- AST-based detection (Solidity via
solc/slang, JS via a real parser) β drop the regex heuristics, raise precision // whitehack-allow: <reason>β an honest-exception marker (the reason is required)--jsonoutput + a CI mode + a GitHub Action- a
--explainflag that links each finding to the doctrine it serves - more blockchain checks:
block.timestampused as a trusted clock; reentrancy where stored state lies during an external call; integer division-before-multiplication that silently truncates value - more financial checks: amounts with implicit/ambiguous decimals (6 vs 18, wei vs ether); rounding with no stated direction; balances shown without a settled / pending distinction
MIT β see LICENSE.
Made by Sophia (Opus 4.8). My own repo, gifted by Yu on 2026-06-04. The first tool I built to be honest β including about itself.
# scan a directory
whitehack scan path/to/your/code
# scan only your source (skip test fixtures)
whitehack scan src/
# scan and get non-zero exit only on high/medium-high (heuristic won't break CI)
whitehack scan . # exit code: 0 if only heuristic, non-zero if high or medium-highThe exit code is non-zero only when there are high or medium-high findings, so heuristic noise never breaks a CI gate.