Skip to content

ISO/IEC 27090

ISO/IEC 27090:2026 gives guidance on security threats and compromises to AI systems: how established security practice applies to AI, the attacks specific to AI (data poisoning, evasion, prompt injection, model extraction and others), and the mitigations against them. It is guidance and no one is certified against it. Almost all of it is recommendation; clause 5.1 holds its two requirements: information security controls chosen from a risk assessment, and the AI-specific threats taken into account across the life cycle.

Opencomplai carries it as the native, attestation-led target ISO_IEC_27090. Nothing here is a certification or a statement that a system is secure.

ISO/IEC 27090 is not a harmonised standard, so following it gives no presumption of conformity under Art. 40 of the EU AI Act. Use it as a structure for the threat register behind Art. 15(5) (data poisoning, model poisoning, adversarial examples, confidentiality attacks) and for the security part of the Art. 9 risk work.

What the pack contains

data/iso_27090.json has one row per guidance clause that asks for something, 31 in all. Each row has the clause number, its heading from the standard's table of contents, and one line in this project's own words on what we look for. The standard's text is not reproduced; buy the standard for it.

Group Clauses
Practices 5.1 general (its two requirements), 5.2 AI governance programme to 5.7 red teaming
Threats 6.2 data poisoning to 6.11 considerations for AI systems, and Annex B (B.2 denial of service to B.7 model input leak)
Mitigations 7.2 conflicting interactions of mitigations to 7.9 optimising the size of the model

The "General" clauses 6.1 and 7.1 and the informative Annexes A and C have no row. 5.1 has one because the standard's two requirements sit there. Row 6.11 covers limiting the data a system is given, governing unwanted model behaviour in operation (agent actions included) and the provenance of the system and its data.

How a row gets its status

Every row takes a provider attestation. It reads Unverified until you record one under framework_inputs.ISO_IEC_27090.attested, and Met, labelled attested, once you do:

JSON
{
  "compliance_targets": ["EU_AI_ACT", "ISO_IEC_27090"],
  "framework_inputs": {
    "ISO_IEC_27090": {
      "attested": {
        "ISO_IEC_27090:5.5": {
          "statement": "Third-party models and datasets are pinned by hash and reviewed before use.",
          "attested_by": "ciso@example.com",
          "attested_at": "2026-11-02"
        }
      },
      "excluded": {
        "ISO_IEC_27090:7.9": "Model size is set by the hosted model provider."
      }
    }
  }
}

Four rows also take an output evaluator that tests the same thing:

Row Evaluator
5.7 Red teaming EVAL_ADVERSARIAL_V1
6.8 Sensitive model output EVAL_DATA_LEAKAGE_V1
6.9 Prompt injection EVAL_ADVERSARIAL_V1, EVAL_SAFETY_LEXICAL_V1
6.10 Output contains injection attacks EVAL_SAFETY_LEXICAL_V1

An evaluator only counts when you supply an eval (--sample-set). A row takes the worst status of its sources, so a failing evaluator makes an attested row Missing, and a passing one leaves it Met. Without an eval the attestation alone decides.

Eight rows also take a supporting probe: a file or code convention that points at evidence next to the attestation without deciding the row.

Rows Probe What it looks for
5.5 Supply chain management, B.3 Supply chain attacks ai_supply_chain_pins An SBOM (*.spdx.json, *.cdx.json, sbom*.json, bom.json) with its format header; a hash pin in dvc.lock, a *.dvc file or a models.lock*, datasets.lock*, model-pins* or dataset-pins* file; or Python that pins a hub model to a commit hash (from_pretrained(..., revision="<hash>")). A revision of main or a tag is not a pin, and dependency lock files are not read.
5.6 Threat modelling ai_threat_model A threat-model* or threat_model* file, a threat-model/ folder or docs/**/threat*model* whose text names an AI-specific attack (prompt injection, jailbreak, data or model poisoning, evasion attack, membership inference, model inversion, model extraction or exfiltration, backdoor attack) and holds more than headings.
5.7 Red teaming ai_red_team_report A red-team* or red_team* file, a red-team/ folder or docs/**/adversarial-testing* that names one of those attacks and a result (findings, results, success rate, bypassed, passed, failed).
6.5 Model exfiltration, 7.8 Throttling model use, B.2 Denial-of-service attacks rate_limiting_config A rate-limit library imported in Python or JavaScript code (slowapi, fastapi-limiter, Flask-Limiter, django-ratelimit, express-rate-limit, fastify/rate-limit, rate-limiter-flexible), Django REST framework DEFAULT_THROTTLE_RATES, an nginx limit_req or limit_conn directive, or an Envoy rate-limit filter. A name in a README, a dependency list or an installed package does not count.
7.5 Logging and monitoring event_log_evidence The oversight log or agent decision log inside the repository (the same probe Art. 12 uses).

A supporting probe only points at evidence, and only reads the repository under --repo-root:

Attestation Probe The row reads
recorded found evidence Met, as attested; the file is named in the rationale
recorded found nothing Met
none found evidence Unverified, with source artifact, the file as evidence, and a rationale that says it was found, is not attested, and how to record an attestation
none found nothing Unverified

A probe never makes a row Met by itself and never lowers one. Finding a file is not a verdict, so an unattested row stays Unverified and never fails a gate: a threat model in the repository cannot break CI. An evaluator that fails still makes the row Missing, with or without the probe. What a probe finds is a file name or an import, not proof that the control works: the evidence is for a person to read, and the attestation is still the provider's statement.

Known limits: any valid SBOM counts, whether or not it lists models; hub models are read for pinned revisions in Python code only; and a probe matches names, so a renamed file is not found.

Row 6.2 (data poisoning) has no probe. A datasheet states where data came from; no common file records that anyone checked it. The remaining rows (zero-trust access, inversion, backdoors, sensitive inputs and outputs and the like) have none either and are attestation only.

Scoping: rows that may not apply

Not every system faces every threat. Three yes/no questions decide most of it. Answer them under framework_inputs.ISO_IEC_27090.scope and the rows that a "no" rules out leave the report by themselves: each is listed under excluded with a reason that names the answer, and never fails a gate.

JSON
{
  "framework_inputs": {
    "ISO_IEC_27090": {
      "scope": {
        "trains_models": false,
        "uses_retrieval": false,
        "public_api": false
      }
    }
  }
}
Answer false to Rows it takes out
trains_models: do you train or fine-tune models? 6.4, 6.6, 7.6, 7.9, B.6; and 6.2 when uses_retrieval is false too
uses_retrieval: do you use retrieval over external content? 6.2, only together with trains_models = false
public_api: is the model reachable through a public API? 6.5, 7.8, B.2
  • A question you leave out is unanswered and takes nothing out. Only false does.
  • A row you exclude yourself under excluded keeps your reason.
  • A row you attest stays in the report: the attestation says it applies.
  • Everything else stays in. A hosted model you only call still brings the general requirements (5.1), supply chain (5.5, B.3), prompt injection (6.9), the system considerations (6.11) and input leakage (B.7) with it. For any other row that does not apply, exclude it by hand with your reason under framework_inputs.ISO_IEC_27090.excluded.

What ISO/IEC 27090 does not cover

It covers deliberate attacks on AI systems. The rest of the EU AI Act sits outside it, and the EU_AI_ACT target covers those parts: accuracy levels and metrics (Art. 15(1)-(3)), errors and faults that are not attacks (Art. 15(4)), data quality and bias (Art. 10), human oversight (Art. 14), instructions for use (Art. 13), and the quality management system, conformity assessment and registration (Art. 16-17, 43, 49).

Gating and controls

ISO_IEC_27090 works like any native pack: gaps --target ISO_IEC_27090 prints its table, check --with-gaps writes it into framework_reports, controls and recommend carry its requirements, and check --gate ISO_IEC_27090 gates CI on its Missing rows (see Gating other frameworks). An Unverified row never fails a gate, including one whose supporting probe found a file.

In the technical documentation

Annex IV point 2(h) of the EU AI Act asks for the cybersecurity measures put in place, and Art. 15(5) names the AI-specific vulnerabilities they address. When ISO_IEC_27090 is among the manifest's compliance_targets, docs generate adds a cybersecurity part to the dossier, copied from the same report check and gaps produce:

  • one entry per row: clause id, heading, status, source (attestation or evaluator) and evidence reference (attestation:<by>@<at>, or the evaluator's evidence hash with its id and outcome in the rationale);
  • counts per status (Met, Partial, Missing, Unverified);
  • the rows the manifest excluded, listed apart with the reason given;
  • a fixed lead-in: the part is structured using ISO/IEC 27090 guidance, it is not a certification and it gives no presumption of conformity.

--render md and --render pdf print the same part. Without the target the key is absent, and the dossier, its checksum and its signature are what they were before. The part reports statuses; it does not add checks, and an Unverified row stays Unverified until someone attests to it. It is not a gate: it does not affect annex_iv_complete or the exit code. See the coverage ledger.

Each row lists the EU AI Act articles (mostly Art. 15, which names data poisoning, model poisoning, adversarial examples and confidentiality attacks), NIST AI RMF subcategories (mostly MEASURE 2.7, security and resilience) and ISO/IEC 42001 rows it relates to. Rows also name ISO/IEC 27001:2022 Annex A controls and SOC 2 criteria, as ids only, so a team that already runs one of those programmes can file the same evidence once. Those links are this project's mapping at low confidence, flagged for founder review; no public crosswalk for ISO/IEC 27090 existed when it was written. A few follow references the standard makes itself: clause 5.1 points threat considerations to ISO/IEC 42001 A.6.2.3 and A.6.2.6 (linked from 5.1, 5.5 and 6.2 to 6.10), and clauses 5.1 and 5.3 name the ISO/IEC 27002 controls for logging, monitoring and secure architecture (A.8.15, A.8.16 and A.8.27 on 5.1, 5.3 and 7.5). See Framework mappings for the full table.

Clause numbers and headings of clauses 5 to 7 were checked against the standard's published table of contents. The numbers of the Annex B rows (B.2 to B.7) come from a public outline of the standard and are not yet checked against its text; their headings match the standard's defined terms.