HN user

unscaled

2,500 karma
Posts0
Comments676
View on HN
No posts found.

It doesn't even have to be something as bare-bones as pass. You can have a full-fledged password manager that is open-source and local-first. KeepassXC (and the OG Keepass) were always OSS and local-first. The original version of Keepass 1.0 for Windows was released long before Lastpass or 1Password[1], so we had an open-source local-first password manager before we had commercial cloud-based managers.

[1] To be more accurate, although it was always proprietary, 1Password was also local-only at first, with syncing only supported by putting it on something like Dropbox. They only added native cloud syncing later and eventually made it cloud-first.

"supposed" is doing a lot of heavy-lifting here. According to who? The FIDO2 or Webauthn standards? Or in a perfect world?

FIDO 1.0 started as two different standards: UAF and U2F. U2F was for USB keys used as second factors (so almost always stored in a TPM-like chip and device-bound, but not provided by your platform and there could be multiple of them). UAF were either provided by your platform or by any software and there was no requirement for them to be stored in TPM. Back in the day, very few platform had any FIDO support built-in, so in practice UAF was always done in software (usually based on whatever biometrics/TPM the hardware provided).

So competing options were the default for early FIDO, getting a default platform option is something that came later.

Passkeys is basically a brand name for "discoverable credentials" (a Webauthn term). They do a little more than that technically, but in practice their purpose is what you said. Replace passwords. Or more accurately usernames and password pairs. This is in contrast from 2FA, but even before Apple started marketing Passkeys the FIDO standard supported the concept of Passwordless authentication, alongside 2FA.

Passkeys came together with multi-device syncing when Apple introduced them and IIRC it was pushed as their killer feature by Apple back then, but passkeys can also be completely device-bound. The marketing around this was all quite confusing, but it's a bit too late to fix now.

What we got, as far as the average consumer should be concerned, is that "passkey" is any authentication mechanism (not the actual credential) that can replace a password. And it's still confusing.

The FIDO set of standards (UAF, U2F which predated passwords and passkeys) haven't even started as enterprise standards. There are multiple origins for what became FIDO, but the main ones I know are:

1. PayPal was looking for a physical authentication solution for their users, Michael Barrett was their CISO at that point and he became the president of FIDO.

2. Google developed Gnubby (which was internal, and therefore enterprise) and they wanted to push a similar authentication to their end-users, supported directly on Chrome. They wanted this to become a standards, so donated the underpinnings of the Gnubby technology which became FIDO U2F.

I might be wrong but at least these are the two parts I know.

And while the original FIDO could be called dual-use, Webauthn and especially Passkeys were developed to be first and foremost a customer-facing standard.

It doesn't mean they are not confusing, but they are clearly designed with end users in mind.

Stop Using JWTs 1 month ago

For what? For just authenticating a client application to a server without getting access to any user data? By all means. You usually don't need the client credentials in OAuth 2.0 if you don't want to use it.

But if you want access to user information, you can't just give access to an app that has a shared secret key to a all user data for every single users in the planet. You need to authenticate the user somehow, and sharing the user's password directly with the app is not a good idea for many reasons.

Even if you trust the app to be "written without any bugs", the moment you allow the password grant in OAuth, your service cannot use CAPTCHA, MFA or Passkeys efficiently. The password grant does not allow any of these, so this app that you've let through becomes the weakest link for all cybercrime groups that want to attack your service.

Stop Using JWTs 1 month ago

PKCE, OAuth 2.0 for Native Apps and the Device Code flow are a thing. In practice all of these clients work so well with OAuth 2.0, that the implicit and resource owner password credential grants have been removed from OAuth 2.1 and are the latest OAuth 2.0 BCP forbids the password grant and strongly recommends against the implicit grant.

Stop Using JWTs 1 month ago

I wish I was young. Did I explicitly said TLS __1.3__ or did I not?

A lot of effort was put into making TLS 1.3 a stronger, less agile and more misuse-resistant standard than its previous iterations. And that effort worked.

Stop Using JWTs 1 month ago

True. But XSS stealing your token (which is always possible with localStorage) is still worse than XSS using your token. It's the principle of least privilege all over again.

Stop Using JWTs 1 month ago

The main reason I don't like the id token is that I've seen way too many instances of the ID token being used as a trusted identity assertion sent across multiple services or to third parties. This is very dangerous, since ID tokens tend to have longish expiry (several hours), are not revocable, and generally do not carry any concept of authorization (e.g. restricted scope).

It would have been better if instead of implementing ID tokens, OIDC only supported the authorization code flow and returned a JSON payload of claims (which nobody would incorrectly assume to be trustworthy).

Stop Using JWTs 1 month ago

The OP was talking about sessions (which include session cookies and API tokens). I'd argue these use cases are far more common for the average programmer than tokens and signatures that are used for federation, but I'll bite the bullet here:

JWT is a serviceable solution for service trust and federation. This use case often just requires a very-short-term token, so lack of revocation support is not an issue. Replay attacks are still an issue, but they can also be prevented with single-use nonces that are included in the token claims.

The OP's take (and my take as well) is that JWT is rarely the BEST solution for this use case. You kinda have to use it if you need to implement a standard that mandates JWT such as OpenID Connect. But OpenID Connect is a great example for a place where JWT was used, but was never really necessary. If you do use the authorization code flow securely (on the server side, with a strong client secret and proper CSRF protection) you don't need the ID token. In fact, you don't need to use any cryptography at all! Just like random session IDs, you've got a stateful solution that works reliably without any cryptography.

If you cannot do a series of authenticated network requests between HTTPS endpoints to verify trust, then a signed payload could be useful, but you've got better standards than JWS/JWT for that. That's all.

Stop Using JWTs 1 month ago

PASETO and TLS 1.3 were also written by humans. TLS libraries (which are several orders of magnitude more complicated than JWT libraries) are also written by humans.

If you passionately care about security and misuse-resistance you CAN write a spec that will lead to fewer implementation issues.

Stop Using JWTs 1 month ago

If memory serves me right, cookies were designed by Netscape in 1994 before JavaScript was even a thing. They were released in an early beta of Netscape (0.9 something), while Javascript was only added in Netscape 2.0. SSL 2.0 was only added in Netscape 1.0. So the HttpOnly/Secure attributes were not relevant to the first cookie design, which wasn't even a standard.

When the first cookie standard (RFC 2109) was released, the Secure attribute was added. You could argue they missed HttpOnly, but JavaScript itself was highly non-standard and underspecified mess during this period (and for a while later too). Almost nobody was thinking about XSS as far as I can tell, and that term was probably only coined at least 2 or 3 years later (by Microsoft researchers[1]). At 1997, the people who even considered XSS, probably only saw this as an HTML injection issue that can be fixed at the injection site and doesn't require any special protections against JavaScript code.

If you really want to point a finger at issues in the early cookie design, then you could talk about domain matches. Not making the port part of the matched domain and not allowing an explicit way to trigger an exact domain match with a specified domain was a mistake. And the confusing leading dot rules (probably for optimizing a substring match without parsing the domain components) was also a mistake.

But RFC 2109 was replaced with RFC 6265 and now RFC 6265bis (which is not released yet, but is mostly implemented by the big browsers). These RFCs fix most of the big issues we had with cookies, and do not shy away from breaking existing behavior: setting SameSite=Lax as the default and restricting SameSite=None to secure contexts broke A LOT of sites for improve security. The changes made in RFC 6265 to forbid multiple cookies in one header also broke many sites.

An equivalent approach in the JWT spec would be a new RFC that does the following:

1. Forbids implementing Unsecured tokens and removes alg="none".

2. Removes RSA and ECDSA (or at least deprecate them) and make Ed25519 the "Recommended+" signature algorithm. If we allow RSA and ECDSA for compatibility, they must be explicitly enabled with feature flags or some other marker that signals their insecurity and security advisories on their potential vulnerabilities must be attached.

3. Removes the entirity of JWE as it is currently implemented (to be replaced with encryption else that is NOT orthogonal to authentication).

3. Requires that HMAC secrets are specified as binary base64url data. They SHOULD be generated by a CSPRNG or a derived using a safe derivation method (such as HKDF-SHA256 with safe key material) and MUST be at least as long as the "security size" for the algorithm (i.e. 32 bytes for HS256, 48 bytes for HS384 and 64 bytes for HS512).

4. Makes the "exp" claim mandatory to set, and mandatory to verify.

5. Add a section with strict implementation guidelines for libraries, e.g. `parse()` functions that skip verifying the token should have a clear name like `inspect_without_verification()` or `dangerously_parse_without_verifying()` and `verify()` function should always receive a key that is strictly typed to a specific algorithm.

6. Remove or restrict the usage of fields that allow the JWT sender to dictate the keys used for verifying it, like "jku" or "x5c". For instance, the standard can mandate that when implementing these fields, the verifier MUST NOT accept any JWKS URLs that do not match one of the explicitly allowed patterns or X.509 certificates that are not signed by an explicitly trusted CA.

[1] https://www.youtube.com/watch?v=mKAWpFdVcPY

Stop Using JWTs 1 month ago

Wow, Fortune 500 companies are using an insecure technology, get hacked and exploited by cryptominers and PII burglars and then just patch their vulnerabilities and call it a day? This never happened before! /sarcasm

Just because a certain practice is popular, doesn't mean it's good for security, and it definitely does not mean the companies who do this never get hacked. Popular != Unhackable. I don't believe this needs to be stated.

Cases in point:

- Passwords limited to 8 characters

- Passwords hashed with a fast, single-iterated hash (with or without salt, that's not the main point, we are not in 2003 anymore goddamnit, and GPUs are a thing!)

- Passwords stored in cleartext

- Using old-style C/C++ without bounds checking and fuzzing and treating stack overflow exploits as just a fact of life we'd have to live with, while most other languages don't get anymore (and if you have to use C/C++ for reasons there are ways to prevent this).

- Injecting unverified user input directly into SQL strings.

- Using ancient software without ever patching or updating vulnerable versions.

Stop Using JWTs 1 month ago

A non-exhuastive list of CVEs from this year alone:

CVE-2026-28802, CVE-2026-29000, CVE-2026-1529, CVE-2026-22817/8, CVE-2026-34950, CVE-2026-23993, CVE-2026-32597.

Most of them are the same classic alg=none, signature verification bypass and algorithm confusion issues.

Stop Using JWTs 1 month ago

JWT libraries had poor defaults because the spec was poorly designed.

Of course JWT can be implemented securely. Even XMLDSig can be implemented securely. But if the spec is not designed with security and misuse-resistance as a tier 1 priority, you will get more issues. The fact that we didn't see the same sheer volume of issues with PASETO or macaroon libraries (admittedly, the later are far less numerous). I can find only one CVE for a PASETO library from 2020, and this is an issue that has nothing to do with the algorithm itself (JPaseto < 0.3.0 switched the order of two arguments in their hash function call, generating weaker hashes).

The reason PASETO won't have the same issues as JWT is the design (especially with v3/v4). There is no alg=none, symmetric keys are fixed size (so no weak keys can be used) and algorithm confusion is prevented by an explicit implementation guide[1] that strongly mandates that keys for different algorithm version have different types, and verification functions MUST reject a key of the wrong type.

Is JWT safe now? Maybe. A lot of issues have been fixed, but new issues keep coming all the time. We're not even halfway into this year and I can count at least the following serious 2026 CVEs: CVE-2026-28802, CVE-2026-29000, CVE-2026-1529, CVE-2026-22817/8, CVE-2026-34950, CVE-2026-23993, CVE-2026-32597, just to name a few. Most of them are the same classic alg=none, signature verification bypass and algorithm confusion issues.

The issues is that new libraries are coming all the time and the vulnerability elimination process for existing libraries is just a random scattershot. If a security researcher has happened across a vulnerability in library X and reported it, it's solved. If nobody has found it yet: though luck. Unless you pick a library that has been officially audited for these issues, you don't really know if it's truly safe. If you use a PASETO library, it's probably not audited either, but the chance of it having these common types of issues (and other issues, like psychic signatures[2]) are close to nil.

---

[1] https://github.com/paseto-standard/paseto-spec/blob/master/d...

[2] https://www.securecodewarrior.com/article/psychic-signatures

Stop Using JWTs 1 month ago

I think both you and GP are somewhat misrepresenting the OP is saying. OP's argument is three-fold:

1. JWTs are not a good fit for a session token (although there are several RFCs that are trying to shoe-horn JWTs into this use).

TLDR: JWTs should not be used for keeping your user logged in. They are not designed for this purpose, they are not secure, and there is a much better tool which is designed for it: regular cookie sessions.

2. JWTs have other "valid" use cases that only need a very short-lived token (e.g. a transit token or a request signature) and don't need to care about user authentication, revocation, XSS etc.

3. But JWT should not be used even for the "valid" use cases, since you have better (read: less outrageously insecure) alternatives nowadays.

Also note that "valid" usecases for JWTs at the end of the video can also be easily handled by other, better, and more secure tools. Specifically, PASETO

You've noted these issues yourself. There are many common vulnerabilities with JWT: alg=none, algorithm confusion and weak key brute-forcing, mandating weaker algorithms like RSA and ECDSA while making the best, fastest and easiest to implement algorithms like EdDSA "optional".

There are also other design deficiencies that JWT makes by trying to be a generic cryptographic envelope format rather than a token format: e.g. expiration can be omitted and this feature that caused some libraries to not verify expiration by default or have a different (and confusing) set of token parsing methods that do not enforce the expiry. PASETO is a better design that is secure against all of these issues. Sure, there are a few minor qualms I can find with PASETO (e.g. no mandatory key ID and no support for non-JSON payloads), but it's unlikely to face the same avalanche of CVEs we got with JWT libraries.

Ok, I think I misunderstood you. Lightweight policing, not policy. I guess this happens in the US, but in most countries cops wouldn't stop you for a traffic violation with a gun in their hand. In some countries (e.g. the UK) the police aren't even carrying guns. As far as I'm concerned is not lightweight policing but normal policing. The US is the outlier here, not Korea.

That's interesting. I didn't know any other country in East Asia that showed this level of restrictive policy that sets up a cascade of problematic tooling and technologies.

Japanese Internet was pretty bad in the 2010s, but this was all self-inflicted done by the private sector. The government had very little do with it. And even then, ActiveX controls were very rare. My main pain point with online banking was ugly sites, back buttons that don't work and passwords limited to 8 or 12 characters "for security reasons". But those problems are not specific to Japanese or Asian banking sites. The only Japan-specific woes I can think of are frequent maintenance windows where most banking functionality is done (mostly eliminated on my bank) and weird 2FA methods like Security Cards (just a paper card with a table of codes for challenges, also completely gone now).

I don't think it's a dystopia. Hanlon's razor still applies. But I beg to differ on your classification of North Korean policies as "lightweight". Korean internet policies usually mandate a very specific technology (like SEED, or apparently this new model now) and weave a web of highly-detailed, Korea-specific regulations that end up creating a monopoly or oligopoly of objectively inferior and highly insecure software.

This is not lightweight. Even the much maligned Online Safety Act in the UK that forced age verification is a far more lightweight policy than what Korea does. It doesn't mandate a specific software or hardware, it doesn't mandate a specific cipher or protocol. Even the list of methods acceptable methods for age verification is explicitly non-exhaustive[1]. And this is the current poster-child of government overreach in the west!

My example of extremely lightweight digital policies (for most things) would be Japan. Vague requirements, non-exhaustive examples, copious exceptions ("you don't have to implement X if it's technologically cumbersome"), everything can be done either manually or in a fully automated way. Is this good? I think Japan is sometimes far too lenient (e.g. on security requirements), but objectively speaking this is lightweight. Korean digital policy is not lightweight by any definition of that word. If not sending tanks to catch every revenge porn distributor is "lightweight" for you that's fine, but which country does that? If we judge a heavyweight policy by its restrictiveness, then there are probably only a handful countries that can compete with Korea.

[1] https://www.ofcom.org.uk/siteassets/resources/documents/onli...

This sounds to me like a repeat of what happened with SEED[1]. The recipe is the same: a real problem followed by a hasty (and probably inferior) NIH solution, a single implementation forced down everybody's throats followed by years of technological stagnation.

Hopefully this mandate wouldn't end up being as far reaching as the SEED mandate did (forcing South Korean web to run on older Internet Explorer versions with custom insecure ActiveX controls for everything).

[1] https://archive.is/ermII

It's not "JWT is broken". The cryptography is fine. The tymondesigns/jwt-auth package is fine. The concept of using JWT as your app's session is what's broken.

If only that was true. JWT came with a lot of questionable cryptographic choices. It went hard on fine-grained cryptographic agility like it was 1995 all over again. It started with the wrong suite of outdated ciphers like RSA and no good security requirements and implementation guides, and even the notorious "none" algorithm. The end result is a string of CVEs that affected a wide swath of JWT libraries.

JWT has many other ill-conceived features such as embedded JWK, token-declared URLs and the complex mess that is JWE (which you'll need if you want encryption). This complexity, useless features (the "none" algorithm), together with picking algorithms that are hard to implement correctly[1] and not setting any kind of security requirements made vulnerable libraries spread like wildfire, and introduced at least 5 different classes of vulnerabilities[2].

The craziest thing, is that easiest vulnerability to abuse (the "none" algorithm), is a required by the JWT RFC, you read it too literally:

  Of the signature and MAC algorithms specified in JSON Web Algorithms
  JWA], only HMAC SHA-256 ("HS256") and "none" MUST be implemented by
  conforming JWT implementations.
Now, the RFC writers obviously meant that conforming JWT libraries, should support "none" if explicitly requested, but did not mean that the libraries have to accept the "none" aglorithm by default. In fact, it's clearly stated:
  An Unsecured JWS uses the "alg" value "none" and is formatted
  identically to other JWSs [...]

  Implementations that support Unsecured JWSs MUST NOT accept such
  objects as valid unless the application specifies that it is
  acceptable for a specific object to not be integrity protected.
  Implementations MUST NOT accept Unsecured JWSs by default.  In order
  to mitigate downgrade attacks, applications MUST NOT signal
  acceptance of Unsecured JWSs at a global level, and SHOULD signal
  acceptance on a per-object basis
Or in another section:
  Unsecured JWSs (JWSs that use the "alg" value "none") provide no
  integrity protection.  Thus, they must only be used in contexts in
  which the payload is secured by means other than a digital signature
  or MAC value, or they need not be secured.
Unfortunately, the JWA spec is huge and complex because it needs to definy many useful, secure and totally not bonkers algorithms like PBES2-HS256+A128KW and RSAES-PKCS1-v1_5, and the very important(?) reasons for storing the coefficients for RSA. So I guess the end result is that almost nobody ever read the JWA RFC, and somehow half of the first crop of JWT libraries let anyone strip the signature, change "alg" to "none" in the header and freely manipulate the token. Good times.

So yes, stateless tokens are a bad tradeoff for many (if not most) web applications. But even if they weren't, there many formats that would do much better than JWT[3]. If you end up going with JWT, it's really better to thoroughly review your library, and stick to safer algorithms that doesn't result in a 5kb token (I'm looking at you RSA). Ed25519 is now supported by a decent amount of libraries.

[1] https://neilmadden.blog/2022/04/19/psychic-signatures-in-jav...

[2] https://pentesterlab.com/blog/jwt-vulnerabilities-attacks-gu...

[3] https://fly.io/blog/api-tokens-a-tedious-survey/

OP mentions backward compatibility and popular YAML libraries as the reason why the "Norway problem" is still an issue, but I'm a little bit doubtful about this explanation.

It's been 10 years, if not more, since I've seen YAML configuration files using "yes/no" or "on/off". Even back in the day, these alternative boolean values were never extremely popular: the community more or less settled on true/false.

The libraries issue is real, but my issue is with the word "popular". These are libraries that used to be very popular, and kinda stuck on as the default, even though most of them semi-abandoned and (at least in my opinion) shouldn't really be used by any new project.

PyYAML's last major release was in 2021, and it's only seen security fixes since then. Even the last major release in 2021 was only a major release becasue Python 2.7 support was removed. Before that there were some API changes in 5.1 released in 2019 (only because the PyYAML defaults have been ridiculously insecure and everyone has been complaining about this for years), and between 2008 and 2019 there were barely any worthwhile changes. tl;dr: PyYAML has been in maintenance mode since 2008.

Libyaml (which PyYAML is based on) hasn't seen a new release since 2020, and while it introduced some YAML 1.2 support, the development pace on this library has been glacial since 2009. Between 2009 and 2020, the project had 3 commits touching actual code per year on average, and since then the number went down to 1 commit on average.

It's a sad state that both libyaml and PyYAML are part of the official YAML project, but hasn't budged forward in supporting YAML 1.2. There is something to be said about open-source project being feature complete and requiring only light maintenance, but if they don't support the latest major YAML spec version that was released all the way back in 2009, I don't think we can call them feature-complete.

There are newer libraries out there for all these languages that support 1.2, are more well-maintained and often offer better and safer API, like libfyaml for C, yaml-cpp for C++, ruaemel for Python and goccy/yaml for Go (not the same as the original go-yaml, does support most of YAML 1.2, but has strangely chosen to keep the "Norway booleans").

LDAP might have won over DAP, but it's still heavily based on the X.500-family of standards. Unlike SMTP (which is a completely different standard), LDAP is strongly based on DAP and other X.500 family standards.

Besides LDAP and X.509, you've got old standards that were very successful for a while. I'm perhaps a little bit too young for this, but I vaguely remember X.25 practically dominated large-scale networking, and for a while inter-network TCP/IP was often run over X.25. X.25 eventually disappeared because it was replaced by newer technology, but it didn't lose to any contemporary standard.

And if you're looking for new technology, CTAP (X.1278) is a part of the WebAuthn standard, which does seem to be winning.

I'm pretty sure there are other X-standards common in the telco industry, but even if we just look at the software industry, some ITU-T standards won out. This is not to say they weren't complex or that we didn't have simpler alternatives, but sometimes the complex standards does win out. The "worse is better" story is not always true.

The OP article is definitely wrong about this:

“Of all the things OSI has produced, one could point to X.400 as being the most successful,

There are many OSI standards that are more successful than X.400, by the seer virtue of X.400 being an objective failure. But even putting that aside, there are X-family standards that are truly successful and ubiquitous.X.500 and X.509 are strong contenders, but the real winner is ASN.1 (the X.680/690 family, originally X.208/X.209).

ASN.1 is everywhere: It's obviously present in other ITU-T based standards like LDAP, X.509, CTAP and X.400, but it's been widely adopted outside of ITU-T in the cryptography world. PKCS standards (used for RSA, DSA, ECDSA, DH and ECDH key storage and signatures), Kerberos, S/MIME, TLS. It's also common in some common non-cryptographic protocols like SNMP and EMV (chip and pin and contactless payment for credit cards). Even if your using JOSE or COSE or SSH (which are not based on ASN.1), ASN.1-based PKCS standards are often still used for storing the keys. And this is completely ignoring all the telco standards. ASN.1 is everywhere.

Unlike many other developed countries, foreign employees working in cleaning and maintenance are still a minority. This is gradually changing, but I believe the main issue is that young people are completely uninterested in this kind of work. Most people working in these industries in Japan are old rather than foreign. The average is probably over 50+, and there are quite a few people working past retirement.

And this makes the entire application server and Servlet model the wrong abstraction. Microprofile simplifies things, but in the end I feel Java EE is just pushing the wrong abstractions here. Cloud native microservices are meant to be small, and receive their "cloud native dependency injection" through standard Unix interfaces like environment variables standard input and output, command line arguments and sometimes files. Cloud native apps are close in spirit to twelve-factor applications (which is a stricter rendition of that).

Jakarta EE, even with its latest updates, comes from a different world. Standardized library API with interchangeable implementations that are injected by the application server. But wait! We flip the script by embedding the application server inside a fat JAR and shipping everything in a single docker/OCI container. A lot of the stuff that used to happen in the application server (load balancing, shared connection pooling, configuration, service discovery, service bus) happens now at the cloud infrastructure level.

You can still use a MicroProfile-based framework, and Quarkus (which is based on MicroProfile) is very popular nowadays, but once you went along with a certain framework, you're not very likely to replace it. Standardization was the selling point of Java EE in the past, but in the microservice world when you're only betting a smallish microservice on Framework X, people are not so concerned about putting all their eggs in one basket anymore.

I remember all the excitement about Spring Cloud... But that was back in 2017.

I never thought of Spring (or Spring Boot) as good technology, but even for the right audience Spring boot is as exciting as React is exciting for frontend developers or C is exciting for kernel developers. It's a pretty established technology that was new and cool at one point and has just become commonplace and boring for better or worse (I would argue worse, but that's just me).

You probably had a CoE (Certificate of Eligibility to Reside in Japan, 在留資格認定証明書). This piece of paper needs to be taken to your local embassy or consulate and be converted to a visa there, which then gets stamped on your passport.

But Japan is working quite differently from other countries here, so you're probably not the first person to be confused, although I don't think any country issues a long-term visa that is not stamped on your passport.

Oh, Yes. Windows 10 had big issues on arrival. But this is also selective Amnesia. The Windows 8 UI was nearly unusable on release. Windows Vista was so legendarily broken on release, that even after it became stable, the majority of technical users refused to give up Windows XP went straight to Windows 7. And even Windows XP that everybody fondly remembers was quite a mess when it came out. Most home users migrated from the Windows 9x line of Windows, so they probably didn't notice the instability so much, but a lot of power users who were already on Windows 2000 held up until SP2 came out. And let's not even talk about Windows ME.

The only major Windows version release that wasn't just a point upgrade that was stable in the last century was Window 7 and even then some people would argue this was just a point upgrade for Windows Vista.

I'm sure that Microsoft greatly reducing their dedicated QA engineers in 2014 had at least some lasting impact on quality, but I don't think we can blame it on bad releases or bungled Patch Tuesdays without better evidence. Windows 10 is not a good proof for, consider Vista had 10 times as many issues with fully staffed QA teams in the building.

The lost art of XML 6 months ago

SGML was designed for documents, and it can be written by hand (or by a machine). HTML (another descendant of SGML) is in fact written by hand regularly. When you're using SGML descendants for what they were meant for (documents) they're pretty good for this purpose. Writing documents — not configuration files, not serialized data, not code — by hand.

XML can still be used as a very powerful generic document markup language, that is more restricted (and thus easier to parse) than SGML. The problems started when people started using XML for other things, especially for configuration files, data interchange and even for programming language.

So I don't think GP is wrong. The authors of the original XML spec probably envisioned people writing this by hand. But XML is very bad for writing by hand the things that it eventually got used for.

The lost art of XML 6 months ago

JSON has no such mechanism built into the format. Yes, JSON Schema exists, but it is an afterthought, a third-party addition that never achieved universal adoption.

This really seems like it's written by someone who _did not_ use XML back in the day. XSD is no more built-in than JSON Schema is. XSD was first-party (it was promoted by W3C), but it was never a "built-in" component of XML, and there were alternative schema formats. You can perfectly write XML without XSD and back in the heyday of XML in the 2000s, most XML documents did not have XSD.

Nowadays most of the remaining XML usages in production rely heavily on XSD, but that's a bit of a survivorship bias. The projects that used ad-hoc XML as configuration files, simple document files or as an interchange format either died out, converted to another format or eventually adopted XSD. Since almost no new projects are choosing XML nowadays, you don't get an influx of new projects that skip the schema part to ship faster, like you get with JSON. When new developers encounter XML, they are generally interacting with long-established systems that have XSD schemas.

This situation is purely incidental. If you want to get the same result with JSON, you can just use JSON Schema. But if we somehow magically convince everybody on the planet to ditch JSON and return to XML (please not), we'll get the same situation we have had with JSON, only worse. We'll just get to wear we've been in the early 2000s, and no, this wasn't good.