Summary

  • AFRINIC’s current WHOIS Crypt page declares a POST form whose password-labelled control is type="text" and whose submitted field is named plaintextpassword. No password was entered in this research and no live submission was made.
  • That design is not evidence of a leak. It is evidence of a receiving boundary that the public documentation should make auditable, especially because AFRINIC’s member guide says only the hash should be shared with AFRINIC and the member should securely keep the plaintext.

The interesting moment in a password hash is not the moment after it has been produced. It is the moment immediately before. A BCRYPT string may be fit to store in an auth: attribute; it says nothing by itself about the route taken by the password that produced it. That route is a separate control surface.

AFRINIC publishes a WHOIS utilities page that directs members to a separate Crypt application. The application’s HTML, captured on 14 September 2026, is unusually legible. It declares a form with the identifier myForm, sets method="POST", and gives the form a relative action, ?lang=en#cli. Inside is a control labelled “Password”. The control is not declared as an HTML password field. It is type="text", with both its identifier and submitted name set to plaintextpassword. The button says “Generate hash”.

Those details should be read precisely. A relative action on that page resolves to the same whois-web.afrinic.net origin. The HTML standard describes a form as a set of controls whose supplied data may be sent to a server for processing, and uses an HTTP POST body as a normal example. The markup therefore instructs the browser to submit an application-level plaintext password to the AFRINIC web endpoint if a user activates the form. We did not activate it. We did not enter a credential, synthetic or otherwise. The evidence is the declared path, not an observed transaction.

That distinction matters because “plaintext” is often allowed to do too much rhetorical work. The tool URL is HTTPS. TLS is designed to prevent eavesdropping and tampering between endpoints. Nothing in the captured material supports the claim that the password travels as readable text on the network. Yet transport encryption does not make an application value disappear at the receiving endpoint. An encrypted tunnel and a local-only generator are different architectures. Both may be defensible; they require different receipts.

The input type supplies another, smaller distinction. In HTML, type="password" is the state whose control obscures data entry. AFRINIC’s captured control is type="text". That is a visible-entry declaration, not proof that anyone looked over a user’s shoulder, not proof of disclosure, and not a verdict on the strength of the eventual hash. It is still a consequential choice for a page whose principal input is meant to remain secret. Visibility at the keyboard, transmission to a receiver and storage in a log are three separate questions.

The strongest counterweight comes from AFRINIC’s own member guide. Its maintainer section advises members to generate a BCRYPT hash of their plaintext password. It then states that only the hash value should be shared with AFRINIC and that members should securely keep their plaintext password. Read generously, this could be shorthand for the final WHOIS update: submit the hash in the object, do not submit the source password as the stored auth: value. But a user following the linked public generator is also being asked to provide the source password to an AFRINIC-hosted form. The guide and the tool may be reconcilable. The reconciliation is not published at the point of use.

That is the article’s narrow finding. It is not that AFRINIC has exposed a password, nor that remote hashing is inherently unsafe. It is that the documentation promises an outcome—AFRINIC receives only the hash—while the generator declares an intermediate data flow in which an AFRINIC endpoint receives the password for processing. A control record should say whether the guide refers only to the database object, or also to the generation path.

The page’s scripts add a second boundary. The captured HTML loads Cloudflare Turnstile from challenges.cloudflare.com and local copies or routes for jQuery, Mustache and main.js. Third-party JavaScript deserves explicit treatment because code executing in a page can, in principle, interact with that page’s document. OWASP’s guidance describes remotely supplied scripts as a change-control and sensitive-data boundary. It does not prove that this Turnstile script reads the password. Presence is not exfiltration.

The local main.js narrows one part of the question. In the captured version, it does not contain myForm, plaintextpassword, BCRYPT, or a crypt-generator hook. Its initialized view is attached to a different create-container interface for editing WHOIS objects, with code for loading templates and sending an object plus an editor password to an object-save endpoint. Those are not the fields or the form on the Crypt page. That inspection prevents a false claim that the visible local script hashes the Crypt password in the browser. It also cannot certify every other loaded library, an extension, a future script, a dynamic response, or the server-side handler.

The public privacy policy is positive evidence, not a substitute for the missing receipt. It identifies AFRINIC as controller, names WHOIS services among its collection surfaces, limits staff access, addresses safeguards imposed on third parties, and says data is retained for organisational or legal purposes. Those are governance commitments. They do not tell a member whether the Crypt handler records request bodies, whether a reverse proxy excludes the named field, whether the plaintext exists only for the duration of one hash calculation, or whether Turnstile is isolated from the input.

This is where a small technical page becomes an accountability surface. The hash result can be perfectly valid while the creation path is poorly described. BCRYPT protects a verifier against a class of storage and guessing risks; it cannot retroactively constrain every system that handled the source password. The tool’s purpose and the tool’s custody chain are different propositions.

Logging is the most concrete example. OWASP’s logging guidance places authentication passwords among values that should usually not be recorded directly; it recommends removal, masking, sanitisation, hashing or encryption where a relevant event must be logged. We did not inspect AFRINIC’s logs, so no assertion about actual logging follows. But the form gives operators a precise field name that a test can follow: plaintextpassword should not survive in application, proxy, error, observability or analytics records. “We use HTTPS” would not answer that test.

Nor would changing the input to type="password" settle the issue. That would improve the default visual treatment and make the control’s purpose clearer to the browser, but it would not change a POST receiver into local computation. Masking is a user-interface control. The decisive architectural question remains where the hash is computed and which principals can access the preimage during that computation.

There are at least two coherent answers. AFRINIC could make generation local to the browser and publish the auditable code path, while separating the sensitive field from third-party script privilege. Or it could retain server-side generation and say so plainly: the endpoint receives a new, non-reused password over HTTPS, hashes it, excludes it from logs and traces, retains no plaintext, and limits any processor access. A server-side generator can be legitimate. Its legitimacy becomes stronger when the receiver, duration and deletion properties are observable rather than implied.

The member guidance should then match the chosen architecture. If “only the hash should be shared” means only the value placed in the WHOIS object, that scope should be stated. If it means the plaintext should never leave the member’s device, a remote POST form is the wrong implementation. The present materials do not establish which promise AFRINIC intends.

A useful receipt also needs a version and a clock. The form, Turnstile integration, reverse proxy, error collector and analytics layer can change independently. A result obtained against one combination cannot silently certify the next. After a material change, an authorised synthetic marker can be followed through the new path, with the covered components and exceptions recorded. The marker and internal configuration need not be published; the public object is the boundary and the date to which it applies.

That record would join three documents that currently speak at different levels. The privacy policy allocates broad responsibility. The member guide describes how a maintainer should handle its credential. The engineering receipt describes the lifecycle of one named field. Each can be accurate while leaving a gap between them. Cross-references and a shared architectural vocabulary would make the promise coherent without exposing defensive detail.

There is also a difference between assurance and observation. “We do not log passwords” is an assurance. A controlled result showing that the synthetic marker is absent from each named sink is an observation. Neither should be inflated into proof about every future version, but together they give members something stronger than a hash string whose provenance cannot be read.

Sources