Top
Best
New

Posted by carlos-menezes 4/12/2025

YAML: The Norway Problem (2022)(www.bram.us)
222 points | 164 comments
azernik 4/13/2025|
Even worse is the all-decimal MAC problem.

Some genius decided that, to make time input convenient, YAML would parse HH:MM:SS as SS + 60×MM + 60×60×HH. So you could enter 1:23:45 and it would give you the correct number of seconds in 1 hour, 23 minutes, and 45 seconds.

They neglected to put a maximum on the number of such sexagesimal places, so if you put, say, six numbers separated by colons like this, it would be parsed as a very large integer.

Imagine my surprise when, while working at a networking company, we had some devices which failed to configure their MAC addresses in YAML! After this YAML config file had been working for literal years! (I believe this was via netplan? It's been like a decade, I don't remember.)

Turns out, if an unquoted MAC address had even a single non-decimal hex digit, it would do what we expected (parse as a string). This is not only by FAR the more common case, but also we had an A in our vendor prefix, so we never ran into this "feature" during initial development.

Then one day we ran out of MAC addresses and got a new vendor prefix. This time it didn't have any letters in it. Hilarity ensued.

(This behavior has thankfully been removed in more recent YAML standards.)

weinzierl 4/13/2025||
Perl has a Poland Problem. The customary file extension for Perl files is *.pl. This worked well until Apache introduced content negotiation and the convention to add a language code as file extension. It had index.html.en, index.html.de, for example.

index.html.pl is where the problem started and the reason why the officially recommended file extension for Perl files used to be (still is?) *.plx.

I don't have the Camel book at hand, but Randal Schwartz's Learning Perl 5th edition says:

"Perl doesn't require any special kind of filename or extension, and it's better not to use an extension at all. But some systems may require an extension like plx (meaning PerL eXecutable); see your system's release notes for more information."

dtech 4/13/2025||
That sounds more like an Apache problem than a Perl problem. It's their mistake and it's not even relevant outside Apache context
maxloh 4/13/2025|||
That should be marked as a breaking change on Apache side IMO. It would be a security nightmare if server code were leaked to public.
weinzierl 4/13/2025|||
It should have been an Apache problem, yes. Not only did it turn out that at least the language negotiation part of content negotiation wasn't the best idea but the way Apache handled it was problematic apart from the pl problem. In the end the Perl community took the issue upon them, so historically I'd say it was a Perl problem (of choice).
ginko 4/13/2025||
Also, Prolog has the Perl problem. :)
weinzierl 4/14/2025||
Yes, I think Prolog had pl even before Perl came around, but Perl snatched it away,
gnabgib 4/13/2025||
Related

The YAML document from hell (566 points, 2023, 353 comments) https://news.ycombinator.com/item?id=34351503

That's a Lot of YAML (429 points, 2023, 478 comments) https://news.ycombinator.com/item?id=37687060

No YAML (Same as above) (152 points, 2021, 149 comments) https://news.ycombinator.com/item?id=29019361

mdaniel 4/13/2025|
And some light commentary a few days ago: https://news.ycombinator.com/item?id=43648263 - Apr 2025 (51 comments)
pkkm 4/13/2025||
Programming with string templates, in a highly complex and footgun-rich markup language, is one of the things I find most offputting about the DevOps ecosystem.
sph 4/13/2025||
I believe Satan itself decided to mix YAML, Jinja and Turing-complete logic when it created Ansible. It truly is the sendmail of the modern era.
senderista 4/13/2025|||
Several years ago when I was writing a deployment system for a cloud distributed database, I tried to automate everything with Ansible playbooks and the Ansible "API" (LOL). I pretty quickly gave up on implementing anything but the most trivial logic in templated YAML and switched to Python (wrapping maximally-dumb Ansible playbooks) for everything nontrivial.
Fizzadar 4/13/2025|||
You might like pyinfra.
mdaniel 4/13/2025||
Just about every time someone complains about ansible, there's a comment to plug this project but pyinfra seems to opt-out of the cloud provisioning part, instead delegating to its terraform connector, which drags in all the nonsense that entails. That makes it not only less useful but (IMHO) a horrible name for a project that only does "remote execution" and not infrastructure. The fact that it's even missing @aws @azure @gcp connectors further solidifies "who is the audience for this thing?"
sph 4/14/2025|||
Not everyone runs cloud servers. pyinfra seems to fit my needs like a glove, so I guess I am the intended audience.

I never liked the provisioning overlap Ansible has with Terraform, so it makes sense to me: provisioning servers with tf, configure them with another tool, whether it’s ansible or pyinfra. Well, at least in theory

Fizzadar 4/18/2025||||
There’s a lot more to infra than the cloud, pyinfra is designed to work in any of these environments not just the over-abstracted, over-hyped cloud. There’s plenty of good tools for setting up the infra, any pyinfra can easily be integrated.
sofixa 4/14/2025|||
> Just about every time someone complains about ansible, there's a comment to plug this project but pyinfra seems to opt-out of the cloud provisioning part

Which Ansible is absolutely atrocious at, so that makes sense. Use the best tool for the job (so Terraform, maybe Pulumi/tfcdk if you hate your future self/future teammates for infra.

nicktelford 4/13/2025||
This is why I generally use Terraform for Kubernetes. It's not perfect, but it's miles better than the various different YAML-templating solutions (Kustomize, Helm) popular in the Kubernetes ecosystem.
mdaniel 4/13/2025||
Two different stateful recordkeeping control planes with disparate opinions about the current state of the world. What can go wrong.
sofixa 4/14/2025||
To be fair one of the most common ways of managing Kubernetes clusters and what is deployed on them is to use ArgoCD, which gives you the same issue of dual stateful control planes.

Even more fun is if you then run your Kubernetes cluster on top of a VM orchestrator such as vSphere, that way you have multiple layers of stateful control planes and compute orchestrators fighting each other.

anvandare 4/13/2025||
"The limits of my keyboard mean the limits of my programming language."

If only they had had ⊥ and ⊤ somewhere on their keys to work with Booleans directly while designing the languages. In another branch of history, perchance.[1]

[1] https://en.wikipedia.org/wiki/APL_(programming_language)#/me...

tossandthrow 4/13/2025||
⊥ and ⊤ is not entirely congruent to false and true.

Boolean and propositional logic is not the same.

Q6T46nT668w6i3m 4/13/2025||
For _ordinary_ two‑valued classical propositional logic, e.g., YAML, they are congruent.
rusk 4/13/2025||
I have an emacs macro for this
whacko_quacko 4/13/2025||
Pandas has a Nigeria problem, where NA -> NaN.

It's not that bad, because you can explicitly turn that behavior off, but ask me how I know =(

orangewindies 4/13/2025||
That's a Namibia problem, Nigeria is NG.
whacko_quacko 4/14/2025||
Damn, you're right ^^' Thanks for pointing that out
trueismywork 4/13/2025||
How?
whacko_quacko 4/14/2025||
For example when reading a CSV. Try using `read_csv` on a file that contains two letter country codes including NA.
alkonaut 4/13/2025||
Always quote all yaml strings. If you have a yaml file that has something that isn't a simple value (number, boolean) such as for example a date, time, ip-address, mac address, country code, phone number, server name, configuration name, etc. etc. then you are asking for trouble. Just DON'T DO THAT. It's pretty simple.

"Yeah but it's so convenient"

"Yeah but the benefit of yaml is that you don't need quotes everywhere so that it's more human readable"

DON'T

ohgr 4/13/2025|
Yeah that.

00,01,02,03,04,05,06,07,OH SHIT

ashishb 4/13/2025||
How often do people even encounter this issue? I have been using YAML for 5+ years and have never had it before. Further, I use `yamllint` which points this out as a lint issue "truthy value should be one of [false, true]".
tetha 4/13/2025||
I don't recall encountering the norway problem in the wild.

Ansible has a pretty common issue with file permissions, because pretty much every numeric representation of a file mode is a valid number in YAML - and most of them are not what you want.

Sure, we can open up a whole 'nother can of worms if we should be programming infrastructure provisioning in YAML, but it's what we have. Chef with Ruby had much more severe issues once people started to abuse it.

Plus, ansible-lint flags that reliably.

hinkley 4/13/2025|||
Fractions are discriminatory when they happen to one individual or group every time or even just the first time.

See also p95 but the same couple of users always see the p99 time, due to some bug.

ashishb 4/13/2025||
Indeed, based on the comments, it is a scissor-bug. Most people never encountered it while some encountered it a lot.
rat87 4/13/2025|||
I have when getting an openapi yaml file from someone else.
jeltz 4/13/2025|||
I have seen it twice but I work in Sweden where we often do things also for the Norwegian market.
mongol 4/13/2025|||
Has been encountered where I work. A global website with lots of country-specific config.
speedgoose 4/13/2025|||
I have encountered it once, though I live in Norway and worked in IT there for a decade.
Y-bar 4/13/2025|||
Never experienced it for the past 10+ years since the bug was fixed in the spec.
Y_Y 4/13/2025|||
I don't think false is truthy.
peanut-walrus 4/13/2025||
I for one did encounter exactly this problem when configuring a list of countries via ansible for geoip whitelisting.
quechimba 4/13/2025||
We had this issue many years ago when people from Norway couldn't sign up. Took us a while to figure out
dmckeon 4/13/2025||
Narrow escape for people from Yemen (YE).
magicalhippo 4/13/2025|||
As a Norwegian I'm very curious, where in the pipeline were you using YAML? And why?

I've only seen it used for configuration.

StableAlkyne 4/13/2025|||
I've seen teams use it as a replacement for JSON because it has the perception of being more "modern"
bornfreddy 4/13/2025|||
While JSON is annoying because it lacks some pretty basic features (comments, trailing comma), at least its spec is short. YAML is huuuge - there are way too many ways to do the same thing.
quechimba 4/13/2025||||
We were using a fork of https://github.com/carmen-ruby/carmen/tree/master/iso_data/b... with our own translations. We used the data in the signup form.
tough 4/13/2025|||
usually locale's paths gone wrong
TZubiri 4/13/2025|||
I usually think of yaml for internal config files, would never think of yaml for user data.

Don't ask me why though, might have something to do with how it's written like a python file, no user would want to write their data in yaml format.

nurgasemetey 4/13/2025||
Probably, OP didn't keep user data in YAML, but I think there was config that kept allowed countries to sign up.
duxup 4/13/2025||
Or were they from Noway ...
umanwizard 4/13/2025|
“Be liberal in what you accept” rears its ugly head once more.
eyelidlessness 4/13/2025||
Being liberal in what you accept, also known as the “robustness principle”, doesn’t mean being ambiguous or surprising about how you accept it. If anything, robustness requires a great deal more precision and clarity (at least with your own reasoning, then with how you communicate what to expect from it).
kazinator 4/13/2025||
Postel's Law does not deserve to be nicknamed the Robustness Principle.

Robustness has a meaning and it refers to handling bad inputs gracefully. An example of a lack of robustness is allowing a malicious actor to execute arbitrary code by supplying a datum larger than some buffer limit.

Trying to make sense of invalid inputs and do something with them isn't robustness. It's just example of making an extension to a spec. The extension could be robust or not.

Postel's Law amounts to "have extensions and hacks to handle incorrectly formatted data, rather than rejecting them. So, OK, yes, that entails being robust to certain bad inputs that are outside of the spec, but which land into onto one of the extensions. It doesn't entail being robust to inputs that fall outside of the core spec and all hacks/extensions.

Cherry picking certain bad inputs and giving them a meaning isn't, by itself, bona fide robustness; robustness means handling all bad inputs without crashing or allowing security to be compromised.

hinkley 4/13/2025|||
Pandering to customers will make you a lot of money today but very narrow margins tomorrow. If you’re in startup mentality your bosses may be 100% fine with that. But you will likely be stuck supporting that crap because you didn’t become wealthy in the IPO/merger.
munch117 4/13/2025|||
Postel's law isn't about accepting arbitrary invalid inputs. It's about inputs that are technically invalid but the intent is obvious from looking at it, and handling those according to intent.

In a distributed non-adversarial setting, this is exactly what you want for robustness.

The problem, as we've come to realise in the time since Postel's law was formulated, is that there is no such thing as a distributed non-adversarial setting. So I get what you're saying.

But your definition of robustness is too narrow as well. There's more to robustness than security. When Outlook strips out a certificate from an email for alleged security reasons, then that's not robustness, that's the opposite, brokenness: You had one job, to deliver an attachment from A to B, and you failed.

Robustness and security can be at odds. It's quite OK to say, "on so and so occasion I choose to make the system not robust, because the robust solution would not be sufficiently secure".

kazinator 4/13/2025|||
> intent is obvious from looking at it

Ouch, no. Dragons be there. Famous last words.

The only area in which is it acceptable to reason this way is graphical user interfaces. (And only if you've provided an API already for reliable automation, so that nobody has to automate the application through its GUI.). Is say graphical, because, no, not in command interfaces.

Even in the area of GUIs, new heuristics about intent cause annoyances to the users. But only annoyances and nothing more.

Like for example when you update your operating system, and now the window manager thinks that whenever you move a window so that its title bar happens to touch the top of the screen, you must be indicating the intent to maximize it.

I suppose the ship has sailed now that people are deploying LLMs in this way and that and those things intuit intent. They are like Postel's Law on amphetamines. There is a big cost to it, like warming the planet, and the systems become fragile for their lack of specification.

> When Outlook strips out a certificate from an email for alleged security reasons

I would say it's being liberal in what it accepts, if it's an alternative to rejecting the e-mail for security reasons.

It has taken a datum with a security problem and "fixed" it, so that it now looks like a datum without that security problem.

(I can't find references online to this exact issue that you're referring to, so I don't have the facts. Are you talking about incoming or outgoing? Is it a situation like an expired or otherwise invalid certificate not being used when sending an outgoing mail? That would be "conservative in what you send/do".)

inopinatus 4/13/2025||||
You are spot on in regards to consideration of adversarial context; however, it is instructive to review the nuanced difference between the RFC761 (1980) statement, viz. "be conservative in what you do, be liberal in what you accept from others" and the substitution of "send" for "do" in RFC1122 (1989). The latter is, with hindsight, an error, since it refocused the attention of some rigid thinkers entirely onto protocol mechanics and away from implementation behaviour, despite the commentary beneath that admonishes such a mindset and concurs wholly with your point.

Or to put it otherwise, Postel was right to begin with, albeit perhaps just a little too cryptic, and has been frequently misquoted and misinterpreted ever since.

kazinator 4/13/2025||
The "liberal in what you accept" part is what is flat out wrong; is that being misquoted?
inopinatus 4/13/2025||
It’s not wrong, because it doesn’t stand alone, and yes, if you’re cherry picking half a statement, then you’re like the Australian politicians calling it a “lucky country”, perpetuating a gross misrepresentation of both the letter and the sentiment of the original statement.

This is especially ironic given that the constructive argument against Postel’s law is generally based on the value of a strict interpretation of specification. If you’re intentionally omitting half of the law, then you have an implementation problem.

Furthermore, none of this has much to do with YAML being a shitty design.

kazinator 4/14/2025||
I think the other half of the law is more or less good, so I don't have any reason to bring it up. I don't exactly know what it means to be conservative, but it sounds safe, like staying away from generating inputs for other programs that exercise dark corner cases. I don't really have anything to discuss about that half of the law.

The world doesn't need principles that are half good.

inopinatus 4/14/2025||
> I don't exactly know what it means to be conservative

That could undoubtedly lead to misapprehension. As the GP indicated, and as the word itself means, it references systemic stability and self-preservation behaviour. Reciprocally, however, the obligation to be liberal absolutely does not mean absolving faulty inputs of their flaws. For example, it would not excuse a dud response to an SSH handshake like trying to negotiate RC4. Both Steve Crocker and Eric Allman have been at pains to unpack the understanding of robustness, forgiveness, and format canonicalisation in security context, and they're hardly wrong. It's also why I'm particularly an advocate of the "do", not the "send", formulation. This is a much more systemic and contextual verb in its consequences for implementatation.

> staying away from generating inputs for other programs that exercise dark corner cases

This is exactly the kind of focus-solely-on-the-wire misdirection that I identified above as a common misinterpretation. Conforming to the most precise and unambiguous interpretation of a protocol, if there is one, in regards to what an implementation puts on the wire, can most certainly be a part of that, but that isn't always what being conservative looks like, and processing is equally if not more important.

The introduction of Explicit Congestion Notification (ECN) aka RFC 3168 (2001) springs to mind. RFC 791 (1981) defined bits 14 & 15 of the IPv4 header as "reserved for future use" and diagrammatically gave them as zero. RFC 1349 (Type of Service, 1992, now obsoleted) named them "MBZ" (Must Be Zero) bits but gave them to be otherwise ignored. RFC 2474 (DSCP, 1998) did much the same with what it termed the "Currently Unused field". When ECN was introduced, making use of those bits as a supposedly backwards-compatible congestion signalling mechanism, we discovered a significant proportion of IP implementations aboard endpoints, routers, and middleboxes were rejecting (by discard or reset) datagrams with nonzero values in those bits. Consequently, ECN has taken two decades to fully enable, and this is where both sides of the principle prove their joint and inseparable necessity; to this day many ECN-aware TCP/IP stacks are passive, stochastic, or incremental with their advertisement of ECN, and equally forgiving if the bits coming back don't conform, because an implementation that resets a connection under the circumstances where the developer comprehends the impedance mismatch would be absurd. Thus fulfilling both sides of the maxim in order to promote systemic stability and practical availability and giving ECN a path to the widespread interoperability it has today.

The exposition on page 13 of RFC 1122 (Requirements for Internet Hosts, 1989) broadly anticipated this entire scenario, even though the same section misquotes Postel (or, rather, uses the "send" restatement that I find too reductive).

The statement of the robustness principle is an integrated whole. A partial reading is, perhaps ironically, nonconformant; as with Popper's paradox of tolerance, one thing it cannot be liberal about is itself.

kazinator 4/14/2025||
Yes, rejecting must-be-zero-reserved-bits due to being nonzero is obviously incorrect.

"Must be zero" means that when the datum is being constructed, they must be initialized to zero, not that when the datum is being consumed, they must also be validated to be zero.

Violating either rule will cause that implementation not to interoperate properly when it is still found deployed in a future in which the bits have now been put to use.

Rejecting must-be-initialized-to-zero fields for not being zero is not an example of a flaw caused by neglecting to be "liberal in what you accept". It's an example of failing to accept what is required: the requirement is to accept the datum regardless of what is in those reserved bits. It is arguably an instance of failing to "be conservative in what you do". If you are conservative, you stay away from reserved bits. You don't look at them, until such a time as when they have a meaning, accompanied by required (or perhaps optional) processing rules.

Now, I see the point that reading Postel's law might steer some designer away from putting in that harmful check for zero, specifically due to the "be liberal" part of it. But that's just a case of two wrongs accidentally making right. That same designer might refer to "be liberal" again in some other work, and do something stupid in that context.

The only thing that will really help is clear specs which spells out requirements like "the implementation shall not examine these bits for any purpose, including validating their value".

umanwizard 4/13/2025|||
> It's about inputs that are technically invalid but the intent is obvious from looking at it, and handling those according to intent.

Surely someone at some point thought it was obvious that “No” should mean “false”, and that’s why we’re now in this mess.

senderista 4/13/2025|||
That works only when everyone is trying in good faith to follow the standard, i.e. basically never. My version of Postel's Law:

If you accept crap, then eventually you will receive only crap.

inopinatus 4/13/2025||
This has little to do with the robustness principle, however mis-stated. It's just shitty design. But if someone was still hell-bent on invoking it, then if anything, it's a straight-up violation of the adjacent words "be conservative in what you do"¹, and further disregards the commentary in RFC1122²:

    ... assume that the network is
    filled with malevolent entities that will send in packets
    designed to have the worst possible effect ...
[1] https://datatracker.ietf.org/doc/html/rfc761#section-2.10

[2] https://datatracker.ietf.org/doc/html/rfc1122#page-12

More comments...