The sentence that failed its own fact-check

I had written a very reassuring sentence:

The dashboard build accepts only TLP:CLEAR reports.

It was concise. It was responsible. It was also ahead of the code.

When I ran the new public-data validator against the committed fixtures, the post stopped being a writing exercise and became a bug report:

reports.reports[0].tlp must be TLP:CLEAR.

The first public row said AMBER. Four reports were marked AMBER; another was GREEN. I was drafting a post about a publication boundary that the repository did not actually enforce. Awkward, but useful: the article had found the defect before a reviewer did.

I had two options. I could soften the sentence until it became technically harmless, or I could make the build deserve the sentence. I chose the build.

What had actually crossed the boundary

Malscope's private analysis engine stays private. The public dashboard receives three deliberately small JSON projections:

private analysis -> redacted report -> public correlation -> draft detection
  • reports.json carries sample fingerprints, classifications, capabilities, ATT&CK technique IDs, and defanged indicators.
  • intel.json groups shared indicators and code-similarity evidence across reports.
  • detections.json carries generated YARA and Sigma review artifacts.

The checked fixture has five reports, ten distinct ATT&CK technique IDs, six shared indicators, one import-hash cluster, one TLSH cluster, and five detection records. Those numbers describe a test fixture, not the size of a private corpus and definitely not detection quality.

Nothing in those files was a malware sample. The labels still mattered. "Not malware" and "cleared for public release" are different questions.

TLP is not decorative trim

FIRST TLP 2.0 reserves TLP:CLEAR for information that may be shared publicly. TLP:AMBER and TLP:GREEN describe narrower sharing boundaries. They are not attractive color choices for a dashboard badge.

The public fixtures were intended to be synthetic, inspectable examples, so I corrected their public labels without touching private reports:

- "tlp": "AMBER"
+ "tlp": "TLP:CLEAR"

More importantly, I added a gate that refuses to generate the site when a public report carries anything else. The label stopped being documentation and became a release condition.

Three files, or it does not ship

The validator now checks more than TLP:

  • the source-public tree contains exactly the three JSON manifests;
  • extra files and symlinks fail before Nuxt runs;
  • network indicators reject live http or https schemes, raw dots, and raw IPv6 separators;
  • every YARA artifact declares TLP:CLEAR;
  • every Sigma artifact remains experimental and says Review before deploying.

That allowlist is intentionally boring. A clever malware-byte detector would need to recognize every format and archive trick. "Only these three files exist" is shorter, easier to audit, and much harder to misunderstand.

Defanging is still only a speed bump against accidental activation. It does not make an indicator benign, erase handling obligations, or grant permission to publish it.

Draft detections stay drafts

MITRE ATT&CK technique IDs organize observed behavior; they do not establish attribution. YARA conditions describe what should match; a match does not prove family identity. Sigma gives detections a portable structure; it cannot know a team's field mappings, exclusions, or normal background noise.

That is why the generated rules remain review artifacts. They are useful starting points, not little certificates of production readiness wearing YAML hats.

What this fix still does not prove

The public repository contains sample data, not malware sample bytes, full reports, analyst notes, or private history. Its generated rules have not been tuned against a specific production telemetry pipeline. Its correlations do not establish campaign identity. Its five fixtures do not prove scale.

What the public artifact repository can prove is narrower and more useful: the release boundary is executable, inspectable, and willing to fail.

The first draft of this post tried to explain that boundary. The validator made me earn it.