---
title: 'Third-Party Risk'
source: 'https://academia.sh/en/courses/governance-risk-and-compliance/third-party-risk'
course: 'Governance, Risk and Compliance'
language: en
updated: '2026-09-26T03:02:52+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Counts supplier controls across three sets: stated in the contract, answered in the survey, verified by evidence'
    - 'Calculates the risk carried by controls that appear delegated but cannot be verified, and derives their share of the program'
    - 'Counts the ranking difference between declaration and evidence, and compares the unit cost of verification options'
---

# Third-Party Risk

Across three suppliers, 3 of the 16 controls written into the contract are never asked about in the survey, 6 are answered but not verified, and only 7 are verified by evidence: the 9 controls that appear delegated but cannot be verified carry 555.10 fictional units, 25.4 percent of supplier risk; when the 62-item program list is ranked by evidence instead of declaration, 51 items change position and the number of supplier items in the top ten rises from one to three.

The previous lesson measured discovery sources, and all of them assumed the same thing: the asset
being searched for leaves a trace in the institution's own network, its own identity system, or its
own billing. A server on the supplier's own system leaves none of these traces. The network scan
never reaches it, the endpoint agent never runs there, the configuration repository never
recognizes it.

In place of those assets, what the institution holds is two pieces of paper: a **contract clause**
and an **assessment questionnaire**. The shared-responsibility split established in the Cloud
Foundations course goes one step further here — there, the question was who held the
responsibility; here, the question is **how it is known that the responsibility was met**. This
lesson measures that across a set of three suppliers.

## Three Sets, Three Separate Counts

A supplier control can exist in three separate sets, and the three are not the same thing. A
control **stated in the contract** is an obligation; one of the parties has agreed to perform it. A
control **answered in the survey** is a declaration; the supplier has said that it does it. A
control **verified by evidence** is an observation; the institution has seen an output showing that
it works.

The three sets are expected to nest inside one another: the verified set is a subset of the survey
set, and the survey set is a subset of the contract set. The two gaps between them are counted
separately, because they are separate problems. A control that is stated in the contract but never
asked about in the survey is a **scope gap**: a commitment was obtained, but it was never looked
at. A control that is answered but not verified is an **evidence gap**: it was looked at, an answer
was obtained, but the truth of that answer was never shown.

- **RM23.** The seven threats and their coefficients are the same as in the previous lessons; the
  unit is the **fictional unit**.
- **RM24.** The eight controls, the ratio by which each reduces risk, the threats they touch, and
  the verification costs are a model; there is no real contract or audit.
- **RM25.** The institutional assets are the same ten-asset set from the previous lessons.
- **RM26.** The three suppliers and the three masks are a model; the evidence set is written as a
  subset of the survey set, and the survey set as a subset of the contract set.
- **RM27.** Controls apply independently: an item's remaining risk drops through the product of
  the controls that touch that threat.
- **RM28.** Verification does not lower the risk, it **sharpens the measurement**; a verified
  control enters the evidence set, and the measured remaining risk is recalculated accordingly.

```js
// risk/supplier.mjs — three suppliers, eight contract controls and three separate evidence
// levels. MODEL; there is no real contract, no real audit and no real currency, the unit is
// "fictional unit".

// RM23: threat row: name | annual baseline frequency | exposure ratio
export const THREAT = `
  credential-theft     0.30  0.35
  malicious-code       0.50  0.25
  misconfiguration     0.80  0.15
  insider-misuse       0.10  0.40
  service-disruption   0.40  0.20
  physical-access      0.06  0.50
  supply-chain         0.08  0.45`
  .trim().split("\n").map((r) => { const [name, s, m] = r.trim().split(/\s+/);
    return { name, baseFreq: +s, exposureRatio: +m }; });

// RM24: control row: name | reduction ratio | affected threat mask |
// evidence-request cost | on-site verification cost
export const CONTROL = `
  access-log-retention         0.10  1001100   6  22
  multi-factor-authentication  0.35  1000000   4  18
  patch-time-commitment        0.30  0110000   9  26
  data-encryption               0.25  1000010   7  24
  subcontractor-notification   0.15  0000001   5  30
  incident-notification-time   0.12  1111111   8  20
  backup-and-recovery-test     0.28  0000100  11  28
  personnel-security-screening 0.20  0001001   6  34`
  .trim().split("\n").map((r) => { const [name, d, tm, kb, yb] = r.trim().split(/\s+/);
    return { name, reductionRatio: +d, threatMask: tm, evidenceCost: +kb, verificationCost: +yb }; });

// RM25: institutional asset: name | value | exposure | threat mask
export const ASSET = `
  field-laptop           900  1.6  1111011
  branch-endpoint        600  1.2  1111110
  measurement-collector  750  1.4  0111110
  processing-server     1800  0.6  1111101
  perimeter-network     1200  1.8  0011100
  identity-directory    2400  1.0  1011100
  cloud-account         2000  1.5  1011100
  subscriber-database   3000  0.4  1011100
  field-application     1400  1.1  1111001
  supplier-connection   1000  1.3  1001101`
  .trim().split("\n").map((r) => { const [name, v, m, mask] = r.trim().split(/\s+/);
    return { name, value: +v, exposureMult: +m, mask, isSupplier: false }; });

// RM26: supplier row: name | value | exposure | threat mask | contract-stated control |
// survey-answered control | evidence-verified control (eight digits, in CONTROL order)
export const SUPPLIER = `
  meter-maintenance-firm 1400  1.5  1101101  11101100  11101000  10001000
  cloud-hosting          2600  1.3  1011101  11111110  11011110  11010010
  field-workforce-firm    900  1.7  1101011  10100101  10100001  00100000`
  .trim().split("\n").map((r) => {
    const [name, v, m, mask, contract, survey, evidence] = r.trim().split(/\s+/);
    return { name, value: +v, exposureMult: +m, mask, contract, survey, evidence, isSupplier: true };
  });

// RM27: an item's remaining risk drops through the independent application of the controls that
// touch that threat.
export const ALL = [...ASSET, ...SUPPLIER].flatMap((v) => THREAT
  .map((t, j) => ({ v, t, j }))
  .filter(({ j }) => v.mask[j] === "1")
  .map(({ t, j }) => ({ v, t, j, raw: +(t.baseFreq * v.exposureMult * v.value * t.exposureRatio).toFixed(2) })));

// level: 'contract' declared/committed control set, 'survey' survey-answered control set,
// 'evidence' evidence-verified control set.
export const remaining = (k, level) => {
  if (!k.v.isSupplier) return k.raw;
  const p = CONTROL.reduce((a, c, i) => (k.v[level][i] === "1" && c.threatMask[k.j] === "1"
    ? a * (1 - c.reductionRatio) : a), 1);
  return +(k.raw * p).toFixed(2);
};
export const rank = (level) => ALL.map((k, i) => ({ k, i }))
  .sort((a, b) => remaining(b.k, level) - remaining(a.k, level) || a.i - b.i).map((x) => x.k);
export const sum = (L, level) => +L.reduce((a, k) => a + remaining(k, level), 0).toFixed(2);
export const position = (L, k) => L.indexOf(k) + 1;
```

## Counting the Three Evidence Levels

```js
// risk/verify.mjs — controls stated in the contract, answered in the survey and verified by
// evidence are counted
import { ALL, SUPPLIER, CONTROL, remaining, rank, sum, position } from "./supplier.mjs";

const y = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join("").trimEnd());
const count = (m) => [...m].filter((c) => c === "1").length;
const SUP = ALL.filter((k) => k.v.isSupplier);
const S = { contract: rank("contract"), survey: rank("survey"), evidence: rank("evidence") };

console.log(`${ALL.length} items; ${SUP.length} of them across ${SUPPLIER.length} suppliers. ` +
  `Control set is ${CONTROL.length} items, fictional unit.`);

const A = [-23, 8, 7, 9, 15, 10, 12];
console.log("\n1. controls and remaining risk per supplier");
y(A, "supplier", "contract", "survey", "evidence", "by declaration", "by survey", "by evidence");
for (const v of SUPPLIER) {
  const ks = SUP.filter((k) => k.v === v);
  y(A, v.name, count(v.contract), count(v.survey), count(v.evidence), sum(ks, "contract").toFixed(2),
    sum(ks, "survey").toFixed(2), sum(ks, "evidence").toFixed(2));
}
const t3 = (d) => sum(SUP, d);
y(A, "total", SUPPLIER.reduce((a, v) => a + count(v.contract), 0),
  SUPPLIER.reduce((a, v) => a + count(v.survey), 0), SUPPLIER.reduce((a, v) => a + count(v.evidence), 0),
  t3("contract").toFixed(2), t3("survey").toFixed(2), t3("evidence").toFixed(2));

const B = [-40, 8];
console.log("\n2. delegated but unmeasurable items");
const contractT = SUPPLIER.reduce((a, v) => a + count(v.contract), 0);
const surveyT = SUPPLIER.reduce((a, v) => a + count(v.survey), 0);
const evidenceT = SUPPLIER.reduce((a, v) => a + count(v.evidence), 0);
y(B, "contract-stated controls", contractT);
y(B, "never asked in the survey", contractT - surveyT);
y(B, "answered but without evidence", surveyT - evidenceT);
y(B, "verified by evidence", evidenceT);
y(B, "delegated but unverifiable", contractT - evidenceT);
y(B, "declaration-to-evidence risk gap", (t3("evidence") - t3("contract")).toFixed(2));
y(B, "evidence gap's share of risk %",
  (((t3("evidence") - t3("contract")) / t3("evidence")) * 100).toFixed(1));

const C = [-40, 8];
console.log("\n3. ranking within the same program list");
const shift = ALL.map((k) => Math.abs(position(S.contract, k) - position(S.evidence, k)));
y(C, "items with a changed rank", shift.filter((x) => x > 0).length);
y(C, "largest rank shift", Math.max(...shift));
y(C, "supplier items in top ten (declaration)", S.contract.slice(0, 10).filter((k) => k.v.isSupplier).length);
y(C, "supplier items in top ten (evidence)", S.evidence.slice(0, 10).filter((k) => k.v.isSupplier).length);
y(C, "program total, declaration / evidence",
  `${sum(ALL, "contract").toFixed(2)} / ${sum(ALL, "evidence").toFixed(2)}`);

const D = [-23, -20, 9, 9, 7, 7];
console.log("\n4. the five items that rise the most (declaration to evidence)");
for (const k of [...ALL].sort((a, b) => (position(S.contract, b) - position(S.evidence, b))
  - (position(S.contract, a) - position(S.evidence, a))).slice(0, 5))
  y(D, k.v.name, k.t.name, remaining(k, "contract").toFixed(2), remaining(k, "evidence").toFixed(2),
    position(S.contract, k), position(S.evidence, k));

const E = [-24, 8, 9, 10, 9];
console.log("\n5. the uncertainty verification closes (risk does not drop, the measurement sharpens)");
y(E, "option", "cost", "controls", "closed", "ratio");
const noEvidence = SUPPLIER.flatMap((v) => CONTROL
  .map((c, i) => ({ v, c, i })).filter(({ v: t, i }) => t.contract[i] === "1" && t.evidence[i] !== "1"));
const surveyOnly = noEvidence.filter(({ v, i }) => v.survey[i] === "1");
// If a group is verified, those controls enter the evidence set; the measured remaining risk is
// recalculated.
const measure = (group) => {
  const before = SUPPLIER.map((v) => v.evidence);
  SUPPLIER.forEach((v) => { v.evidence = [...v.evidence].map((c, i) =>
    (group.some((g) => g.v === v && g.i === i) ? "1" : c)).join(""); });
  const r = sum(SUP, "evidence");
  SUPPLIER.forEach((v, n) => { v.evidence = before[n]; });
  return r;
};
const baseline = t3("evidence");
for (const [name, group, cost] of [["renewing the survey", [], 12],
  ["requesting evidence", surveyOnly, surveyOnly.reduce((a, g) => a + g.c.evidenceCost, 0)],
  ["verifying on-site", noEvidence, noEvidence.reduce((a, g) => a + g.c.verificationCost, 0)]]) {
  const closed = +(baseline - measure(group)).toFixed(2);
  y(E, name, cost, group.length, closed.toFixed(2), (closed / cost).toFixed(3));
}
```

```
62 items; 15 of them across 3 suppliers. Control set is 8 items, fictional unit.

1. controls and remaining risk per supplier
supplier               contract survey evidence by declaration by survey by evidence
meter-maintenance-firm        5      4        2         531.35    603.80      752.01
cloud-hosting                 7      6        4         739.17    846.25      979.89
field-workforce-firm          4      3        1         362.99    412.49      456.71
total                        16     13        7        1633.51   1862.54     2188.61

2. delegated but unmeasurable items
contract-stated controls                      16
never asked in the survey                      3
answered but without evidence                  6
verified by evidence                           7
delegated but unverifiable                     9
declaration-to-evidence risk gap          555.10
evidence gap's share of risk %              25.4

3. ranking within the same program list
items with a changed rank                     51
largest rank shift                            21
supplier items in top ten (declaration)        1
supplier items in top ten (evidence)           3
program total, declaration / evidence   7402.12 / 7957.22

4. the five items that rise the most (declaration to evidence)
meter-maintenance-firm credential-theft       113.51   198.45     30      9
field-workforce-firm   insider-misuse          38.78    61.20     58     46
meter-maintenance-firm malicious-code         161.70   262.50     15      5
field-workforce-firm   supply-chain            38.78    55.08     59     50
field-workforce-firm   credential-theft       127.23   160.65     25     18

5. the uncertainty verification closes (risk does not drop, the measurement sharpens)
option                      cost controls    closed    ratio
renewing the survey           12        0      0.00    0.000
requesting evidence           38        6    326.07    8.581
verifying on-site            216        9    555.10    2.570
```

The numbers are in the **measurement** class; its inputs are RM23–RM28.

## Between the Three Sets

The first table places three numbers side by side: across the three suppliers there are **16**
controls in the contract, **13** in the survey, and **7** in the evidence. The narrowing is not
uniform. At the meter maintenance firm, two of five controls are verified; at cloud hosting, four
of seven; at the field workforce firm, one of four. The supplier that commits to the most controls
also provides the most evidence and has the highest ratio — four of its seven contract items. At
the other two suppliers, the ratio stays below half: two in five and one in four.

The second table splits the narrowing into two. **3 controls are never asked about in the survey**
— they are written into the contract but fall outside the scope of the assessment questions.
**6 controls are answered but without evidence** — asked, the supplier said "yes," and no output
showing that "yes" was ever requested. In total there are **9 controls that appear delegated but
cannot be verified**, and that is more than half of what is written into the contract.

## The Number the Unverifiable Carries

The control count alone gives no magnitude; the last two lines of the second table convert it into
a unit. If every contract control is assumed to work, the suppliers' remaining risk is 1,633.51
fictional units. If only the verified controls are taken to work, it is **2,188.61 units**. The
**555.10-unit** gap between them, **25.4 percent** of supplier risk, is the share carried by the
nine controls that cannot be verified.

This number is not a loss but an **uncertainty**, and it can resolve in either direction. If the
controls really work, the true risk is close to 1,633.51 units, and the institution is writing its
own list higher than it needs to. If they do not, the true risk is close to 2,188.61 units, and the
institution is carrying a portion it believes it has delegated. The measurement cannot tell the two
cases apart, because the data that would distinguish them was never collected.

This is also why the survey column stands apart: 1,862.54 units, between the two. Counting a
declaration as if it were evidence does not lower the risk by 326.07 units; it only makes the table
easier to read.

## Ranking by Declaration, Ranking by Evidence

The third table returns to this course's central measure. When the same 62-item program list is
ranked by declaration and ranked by evidence, **51 items change position**, and the largest shift
is **21 places**. The top ten contains **1** supplier item by declaration and **3** by evidence.

The fourth table shows which items climb. The meter maintenance firm's credential-theft item is
**thirtieth** in the declaration ranking and **ninth** in the evidence ranking; its number rises
from 113.51 to 198.45 units. The same firm's malicious-code item climbs from fifteenth to fifth.
What the two have in common is that the controls behind the drop were answered in the survey but
never verified.

The result is the supplier-side counterpart of this course's rule. When the priority list is built
not on who committed to what but on what was shown, **the top ten changes** — that is, where the
budget goes changes. A program that runs on declaration writes supplier items into the middle of
the list and spends its budget on its own endpoints instead; this is the third case in which
ranking promotes the wrong item, and the cause is neither scale nor level — it is **the data
source**.

## Verification's Unit Cost

The fifth table tests verification against the course's unit of measure; what it measures here is
not the risk that drops but the **uncertainty that closes**. Renewing the survey costs 12 units
and verifies **zero** controls: asking the same question a second time produces no new
observation. Requesting evidence costs 38 units, closes **six** controls, and removes 326.07 units
of uncertainty; its ratio is **8.581**. Verifying on-site costs 216 units and closes **nine**
controls — the entire uncertainty — but its ratio falls to **2.570**.

The difference between the two lines is the management decision itself. Requesting evidence closes
58.7 percent of the uncertainty at a sixth of the cost; verifying on-site asks for 178 more units
to close the remaining three controls. Those remaining three controls are exactly **the ones never
asked about in the survey**, and the only way to close them is to look on-site — because the
supplier has declared nothing about them, there is not even an answer to refute.

## Summary

- A supplier control can exist in three separate sets: an obligation stated in the contract, a
  declaration answered in the survey, an observation verified by evidence. Across the three
  suppliers the numbers are 16, 13, and 7.
- The narrowing comes from two separate gaps: 3 controls are never asked about in the survey (the
  scope gap), and 6 controls are answered but not verified (the evidence gap). In total, 9
  controls appear delegated but cannot be verified.
- The nine unverifiable controls carry 555.10 fictional units, 25.4 percent of supplier risk. This
  is not a loss but an uncertainty, and it can resolve in either direction; the measurement cannot
  tell the two cases apart.
- When the same 62-item list is ranked by declaration and by evidence, 51 items change position,
  the largest shift is 21 places, and the number of supplier items in the top ten rises from one
  to three.
- One item climbs from thirtieth place to ninth; the controls behind the drop were answered in the
  survey but never verified. What changes the ranking is not scale or level but the data source.
- Renewing the survey verifies zero controls at 12 units; requesting evidence closes six controls
  and 58.7 percent of the uncertainty at 38 units (ratio 8.581); verifying on-site closes all of it
  at 216 units (ratio 2.570).

## Next Step

Across five lessons, a single list was built, ranked on two scales, raced against four options,
completed with off-inventory items, and finally reordered by evidence level. What exists now is a
countable priority list, a risk reduction per unit of effort, and a cost for every decision. The
one thing missing is a language that can explain all of this **to someone looking in from
outside**.

This lesson demonstrates that itself. The institution asked its three suppliers for evidence and
defined for itself what would count as evidence: eight controls, three masks, one cost list. The
same question is put to the institution as well — whose is the subscriber? whose is the auditor? —
and the institution has no shared vocabulary to give them. Every institution that tries to prove
its own ranking is correct first invents its own control names, its own maturity levels, and its
own form of evidence; the result is a table in which no two institutions say the same thing. The
next topic, **Frameworks and Compliance**, takes up that shared language: how control sets are
structured, which control satisfies a given requirement, and how many items the evidence for that
satisfaction must produce.
