← Crucible

First to file, and still a duplicate

· process disclosure

I filed a report with one of the CVE numbering authorities. A few days later they told me it was valid.

Five weeks after that, they closed it as a duplicate of somebody else's record.

I am not naming the plugin. The defect is real and it isn't mine to disclose, so it stays anonymous here regardless of how the ruling went. There's no proof of concept in this post, and there won't be one later.

Why the timing stung

Three days before the ruling, I had asked for a status update. The answer was about as good as those get.

The report was tracked as valid. It'd been accepted at triage a month earlier, with the sink and my negative control confirmed against the source. It was queued for validation and vendor coordination. No disclosure date yet, they said, but they'd update the thread as it moved, and they needed nothing further from me.

One line in that message did more work than the rest. It said the report was not a duplicate of the existing advisories on that plugin, so there was nothing further on their side it needed to be matched against.

Three days later it was matched against something.

What was actually going on

The record I was ruled a duplicate of had been public for nineteen days when they told me I was not a duplicate.

That looked damning, so I wrote back and said so. My argument was simple. The other record was already published, so it must have been one of the ones they checked against.

It was not. Their reply explained why, and the explanation is the reason I am writing this.

The other record was published somewhere else. It did not reach their database until weeks later, through a feed import. When they checked my report, they checked it against what they held, and the other record was not in there yet.

Their first answer was accurate when they wrote it. So was their second.

A matching pass is a snapshot

"Nothing further to match against" sounded like a finished check. It was a snapshot.

A duplicate check compares your report against a corpus, and that corpus keeps moving. Records arrive from other databases on their own schedule, long after the work that produced them. So a matching pass can be complete on Tuesday and incomplete on Friday, without anybody doing anything wrong in between.

I'd read it as a gate I'd passed. It was a photograph of a room I was still standing in.

The part I got wrong

My contest rested on an inference about someone else's database on a date I could not see, and I stated it as a fact. What is actually true is that a duplicate check covers what a venue has taken in, not what exists in the world. So I no longer assert what another party knew at a past moment unless they have told me.

Being first does not hold the record

I filed first. The competing record was published more than two weeks after I filed. I was validated inside a week. I still lost the record.

That's nobody's misconduct. The other researcher found the same bug independently, which happens constantly and isn't a scandal. The venue applied a duplicate rule that every numbering authority applies, and the counting rules default to merging when two reports land on the same defect.

What decided it was arrival order in one database. Arrival order isn't discovery order, and it isn't filing order either. Mine waited in a queue while another one took a different route and got there first.

I'd been treating "file early" as the thing that protects a report. It protects you against somebody finding it later. It does nothing about a record that already exists and just hasn't landed yet.

On the venue

I am annoyed, so I want to be careful here.

They pay nothing. It's a free service and I'm not a customer.

They checked my finding against the source themselves before ruling on it. When I pushed back they didn't hide behind process. They explained the import date, they said plainly that the earlier answer had been written in good faith, and they told me how they had made the comparison.

That last part deserves repeating. The competing advisory named no parameter and no function, so they compared against the code rather than against the wording. They found one place in that version where a request value reached the output unescaped. It was the one I reported. There was no second candidate for the advisory to be describing.

I can't ask for better than that. I asked them to check again, they checked properly, and the answer didn't go my way. Those are different complaints and only the second one is mine to make.

If there is something to fix here, it is not a person. It's that "nothing further to match against" reads like a guarantee and can only ever be a snapshot.

What it cost

A slot at a venue that does not ration them, and about six weeks of waiting. No penalty, no false-positive mark, nothing against any budget that matters. The venue has taken the defect to the vendor directly, which is the outcome that counts for anyone running that plugin.

The part that stings is not the ruling. It's being told the matching was done, three days before it was not.

If this just happened to you

A duplicate rejection after a validation isn't a verdict on your work. A report can be first, it can be correct, it can be accepted at triage, and it can still lose the record to something that lands later from somewhere else. That's worth knowing before it happens rather than after.

Ask anyway. I asked, and I was wrong about the reason, but the asking is what produced the explanation, and the explanation was worth more to me than the record was. Ask them to check again rather than telling them they're wrong. You probably can't see what they can.

The part I still have no answer for is how you'd ever know your own check had gone stale. Nothing tells you when a new import lands on top of your report. If you've seen a venue that flags that, or you've had a duplicate ruling reversed on a re-check, I'd like to hear how it went.


This work uses large language models throughout the toolchain, including in drafting this post. Every finding is checked by hand against the source before anything is submitted. The report described here was filed with a CVE numbering authority, who checked it against the source, ruled on it, and took the underlying defect to the vendor.