◇ OpenCyber Academy
Technologist · Chapter 4 · English

Chapter 4 — Data models

Open, free learning for anyone who wants to protect people and technology. No account is required to read this text or its worked answers.

Chapter 4 — Data models

Lesson map

Lesson 04 published. Map, example, EX010.

flowchart TD
  N0["Learning outcomes"]
  N1["4.1 What a finding record needs"]
  N2["4.2 Controlled vocabularies"]
  N3["4.3 Identifiers over prose"]
  N4["4.4 Validation as a gate"]
  N5["Lab B — record validator"]
  N6["Synthesis"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6
  N6 --> EX["Worked example"]
  EX --> Q["Exercise EX010"]

Logical drawing

flowchart LR
  N0["Learning outcomes"]
  N1["4.1 What a finding record needs"]
  N2["4.2 Controlled vocabularies"]
  N3["4.3 Identifiers over prose"]
  N4["4.4 Validation as a gate"]
  N5["Lab B — record validator"]
  N6["Synthesis"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> Q["EX010"]
[Learning outcomes]
    |
    v
[4.1 What a finding record needs]
    |
    v
[4.2 Controlled vocabularies]
    |
    v
[4.3 Identifiers over prose]
    |
    v
[4.4 Validation as a gate]
    |
    v
[Lab B — record validator]
    |
    v
[Synthesis]
    |
    v
[Worked example] --> [Exercise EX010]

Learning outcomes

You will (1) design a minimal record for a finding; (2) validate records for missing fields, wrong types and illegal values; (3) explain why controlled vocabularies make reports comparable; (4) link findings to evidence through identifiers rather than prose.

4.1 What a finding record needs

A finding is a claim: on this asset, this weakness exists, shown by this evidence, with this severity. The minimal fields are therefore an identifier, the asset, an ATT&CK technique ID or other weakness reference, a severity from an agreed list, and a pointer to evidence. Remediation owner, due date and status come later in the life cycle.

Finding F-01 needs id, asset, evidence id, severity and scenario before it may enter the report builder. lab_records rejects incomplete rows. Priya will not argue severity on a record that still prints missing evidence.

4.2 Controlled vocabularies

If one tester writes "urgent", another "P1" and a third "very bad", nobody can count criticals. A fixed set — low, medium, high, critical — lets dashboards add and compare. ATT&CK IDs such as T1078 do the same job for adversary behaviour: "valid accounts" phrased five ways is still one technique.

TRT's vocabulary is low, medium, high, critical — never urgent. lab_records flags F-02 for severity urgent so dashboards stay countable. Northpoint's writers get the same four words in the ROE appendix, so TRT dashboards remain comparable across providers and across engagements.

4.3 Identifiers over prose

Evidence is linked by an ID such as E-001, not by "see the screenshot from Tuesday". IDs survive renaming, translation and copying into a ticket system. Each ID must be unique within the engagement.

In ENG-712, F-09 points at E-002 by identifier, so renaming the PNG or exporting the wiki to another format does not break the link. Ticket systems receive the identifiers unchanged when findings are copied across. Before the report builder runs, chat references such as the wiki screenshot are rewritten as evidence identifiers, so every claim in the draft points to one specific file.

4.4 Validation as a gate

Records are validated before they enter the report. A validator that lists every problem, rather than stopping at the first, saves round trips with the tester.

The validator lists every problem on a record in one pass. F-03 missing evidence and a bad severity on another row both appear before the author rewrites. Round trips drop when the gate is complete: on ENG-712's first dry run a validator that stopped at the first problem cost a day of back-and-forth with Northpoint's authors.

Lab B — record validator

"""Lab B (ch 04): validate synthetic finding records against a minimal schema."""
REQUIRED = {"id": str, "asset": str, "technique": str, "severity": str, "evidence": str}
SEVERITIES = {"low", "medium", "high", "critical"}
records = [
    {"id": "F-01", "asset": "trt-portal", "technique": "T1078", "severity": "high", "evidence": "E-001"},
    {"id": "F-02", "asset": "trt-wiki", "technique": "T1213", "severity": "urgent", "evidence": "E-002"},
    {"id": "F-03", "asset": "trt-vpn", "technique": "T1133", "severity": "medium"},
]
for r in records:
    problems = [f"missing {k}" for k in REQUIRED if k not in r]
    problems += [f"{k} not {t.__name__}" for k, t in REQUIRED.items() if k in r and not isinstance(r[k], t)]
    if r.get("severity") and r["severity"] not in SEVERITIES:
        problems.append(f"bad severity '{r['severity']}'")
    print(r["id"], "OK" if not problems else "; ".join(problems))

Run with python3 lab_records.py. Verified output:

F-01 OK
F-02 bad severity 'urgent'
F-03 missing evidence

Worked example

Northpoint delivers three draft findings. F-01 passes. F-02 uses "urgent", which is not in the agreed severity list. F-03 has no evidence pointer, so nothing supports the claim. Priya returns F-02 and F-03 with the validator's messages and accepts F-01 into the tracker.

Synthetic case. These three findings and their assets are fictional TRT examples.

Errors and limits

A schema guarantees shape, not truth: a well-formed record can still describe something that never happened. Keep the vocabulary short; too many severity grades produce argument instead of action.

Exercises

Synthesis

A finding is a structured claim with a fixed vocabulary and an evidence pointer; validate before you report.

Continue studying — chapter 04 of 30

← Chapter 03 (draft) · Course chapter index · Chapter 05 (draft) →