7ce0ba7 docs(carriers): the third verdict exists, and publishing an alias is what takes it away 302625e fix(conformance): the tag carrier has no output: label, and our blocker claimed it did fe5e6b2 docs(conventions): the merge button is off for a reason, and the reason now lives in the repo 2d86151 fix(divergence): our own iframe number read 3x low, and the reported cause was not the cause daa7ba4 release(0.4.0): two values moved by two mechanisms, and the difference is the release 2eee7e1 feat(lexicon): both unbounded rows narrow to [^><]*, and the mechanism is new here d467324 feat(signatures): the staleness we disclosed is closed by reading the module, not the message 4187715 docs(divergence): our own form has a number now, and it is quadratic 0e765a0 docs(security): the attack surface here is data, so the report route had to say where a wrong entry gets fixed d96fbbf docs(divergence): the span row had one witness; llm-security measured five more git-subtree-dir: scanners/commons git-subtree-split: 7ce0ba706cadd032ec3c16622dcfdb5ce4dc32d6
7.2 KiB
Security policy
This repository ships no runnable code — no package, no build, no dependency tree, nothing that executes on your machine. So the usual question, can this be exploited, has an unusual answer here: the attack surface is the data.
Seven data files here carry the detection material — pattern tables, code-point carriers, calibration thresholds, an OWASP mapping — and several independent runtimes read them at the same time. A wrong code point, a mis-escaped regex, a fixture that expects a miss: none of that crashes anything. It produces a detector that looks like it works and is not looking. That is the vulnerability class this policy is about, and a report of one is welcome even though no code changes as a result.
Reporting
Do not open a public issue. A report here usually names an input that gets past a detector, and that is a working bypass against every consumer until it is closed.
Report privately by email:
- hello@fromaitochitta.com, with
SECURITYat the start of the subject.
Pull requests are not the channel either — they are switched off on the canonical repository, and not as an oversight. This repository is vendored into independent runtimes that pin a tag; a change to detection data changes what those runtimes find. Such a change has to be coordinated with each consumer before it exists, which a merge button does not do. Fork-and-own is the supported path.
Please include:
- the file and the entry — its
name,orderorid, whichever that file uses; - the tag you read (
v0.3.0, not "main"); - the input that should have matched and does not, or the input that matches and should not;
- what a consuming runtime actually does today, if you have measured it.
Obfuscate live payloads. Do not send a working credential or a live carrier. Spell
invisible characters as code points the way the tables do ("U+200B"), and use placeholder
key material — a report should not itself be a delivery mechanism.
What counts as a vulnerability here
In scope — all of these are real reports:
- A detection entry that is a silent false negative. A wrong code point, a regex whose escaping is wrong for the declared dialect, missing or wrong flags, a pattern that fails to compile in a documented engine and gets skipped rather than reported.
- A conformance fixture that sanctions a miss.
expected.jsonis ground truth: a runtime that disagrees with it is deemed wrong. A fixture that expects too little makes every conforming runtime wrong identically, and the corpus will not catch it. - A normative clause that mandates unsafe behaviour. The
spec/files bind the implementations that consume them, so a weak rule propagates to all of them. - A real secret or personal data in the repository or its history. The history is public in full.
- Data that has gone stale against its declared source in a way that under-detects.
Each data file names its source in a
provenanceblock. If that source has since added or corrected an entry, the copy here under-matches, and a consumer vendoring it is less protected than the runtime it was taken from.
Out of scope — documented boundaries, not vulnerabilities. See Known limitations and Non-goals in README.md:
- a detection class absent from the tables entirely (coverage is the union of what the seed implementations detected, not of what exists);
- a table implemented by only one runtime, and cases marked
not-applicablefor the others; - disagreement about a
calibration.jsonthreshold — the thresholds are published, the policy built on them belongs to the consumer; - a divergence already recorded in
docs/lexicon-port-divergence.md; - the five data files no fixture constrains, and the finite homoglyph map.
If you are unsure which side something falls on, report it privately anyway.
Why a confirmed defect is usually not fixed here first
This is the part that differs from an ordinary repository, and it is worth reading before you conclude that a fix is being stalled.
Most data here is an extraction: a copy of a table that lives in a runtime, kept behaviour-identical to it on purpose. Correcting an entry here — even a genuinely wrong one — would make the copy disagree with the implementation it was taken from. Two implementations answering differently on the same input is precisely the failure this repository exists to prevent, so producing one as a fix would be self-defeating.
A confirmed defect in extracted data therefore travels:
- the report reaches the maintainer here, privately;
- the owning runtime is identified — every data file names it in
provenance.source_repo— and the report is routed there; - the decision is taken there, where the pattern is under test against a real suite;
- once the source has moved, this repository re-extracts from a pinned public commit and tags a release;
- consumers pull that tag on their own schedule.
Stated plainly, because it affects you: fix latency is bounded by the owning runtime's schedule and by each consumer's pull, not by this repository's. If you need protection sooner than that, the fix belongs in your own runtime; this repository is where it becomes shared, not where it becomes real.
Two things do not take that route:
- A real secret in the repository or its history (class 4) is handled here, immediately.
- Data authored in this repository rather than extracted — it is flagged as such where
it occurs, for example
authored_payloadsinconformance/manifest.json— is this repository's own to correct.
The precedent is on the record. In v0.3.0 a detection pattern changed value here for the
first time, and it changed because the owning runtime had changed its own and this
repository re-read the source — not because a reviewer here judged the old value wrong.
docs/lexicon-port-divergence.md records a row where two runtimes still disagree and this
repository deliberately did not pick a winner. Provenance is the ground for moving a
value. Merit is not, and the day it becomes the ground, the guarantee is gone.
Supported versions
Pre-1.0. Only the latest tag is fixed; there are no back-ported branches.
Consumers vendor this repository (git subtree, or a pinned copy) rather than installing
it, so a fix reaches a consumer only when that consumer pulls the new tag. There is no CI in
this organisation and nothing polls for updates. When a fix changes detection data, the
maintainer notifies the known consumers directly — but their upgrade is their own action, on
their own schedule.
Read the CHANGELOG.md entry before upgrading rather than the version number: in 0.x, a
change to what a conforming runtime finds is still a minor bump.
Disclosure
There is no formal embargo SLA here. The maintainer will acknowledge the report, agree a fix
and disclosure timeline with the reporter, and credit the reporter in the CHANGELOG.md
entry unless they prefer to remain anonymous.
If the report is a false negative in a table that has already shipped, the changelog entry will say what slipped through, in enough detail that a consumer still pinned to the older tag can judge whether it is exposed. Naming it is the point of fixing it.