---
title: 'Asset and Inventory Management'
source: 'https://academia.sh/en/courses/governance-risk-and-compliance/asset-and-inventory-management'
course: 'Governance, Risk and Compliance'
language: en
updated: '2026-09-26T03:02:52+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Counts the risk items produced by off-inventory assets and calculates their share of the true total'
    - 'Ranks two lists side by side: how many items in the incomplete list end up in the wrong position, and by how many places'
    - 'Measures the unit cost of discovery sources and the risk carried by the asset no source ever sees'
---

# Asset and Inventory Management

When six off-inventory assets are added to the list, the 47-item list grows to 69 items and the 5,768.61-unit total rises to 8,045.45 fictional units: off-inventory items carry 28.3 percent of the true risk, 41 recorded items change rank, the largest shift is 22 positions, six shadow items enter the top twenty, 8 of the 30 shadow items can never enter any ranking because their value was never written, and the shadow item that rises to the highest rank comes from an asset no discovery source has ever seen.

Across three lessons the same list was ranked, measured and budgeted: 47 items, ten assets, seven
threats. Every calculation assumed this list was complete. Yet the list was derived from an
inventory, and an inventory is a set of records — an asset that was never recorded cannot enter the
list.

An unrecorded asset's risk is not zero; it is unwritten. It is invisible in the ranking, takes no
place in the budget, is not even counted as accepted — because acceptance requires at least a
record. This lesson counts that gap: how many assets sit outside the inventory, how many items they
produce, how many ranking positions would change if they entered the list, and what the unit cost
of finding them is.

## Left Outside the Inventory

An off-inventory asset is not usually a rule violation; more often it is the residue of ordinary
operations: a server spun up for a test and never torn down, a cloud account a team opened on its
own budget, a transfer service the field team set up itself, a branch endpoint that was
decommissioned but never unplugged, a second supplier connection, a backup data copy. Each one
exists because it served some purpose, and none of them was set up with updating the inventory in
mind.

The way to find them is discovery sources, and each source looks from a different angle. Network
scanning sees what is addressable, identity records see what has an account, billing records see
what generates a cost, the configuration repository sees what is defined, the endpoint agent sees
what has software running on it. An asset is as findable as the number of sources it appears in; if
it appears in none, it cannot be found.

- **RM17.** The seven threats and their coefficients are the same as in the previous lessons; the
  unit is the **fictional unit**.
- **RM18.** The five discovery sources, their costs and source masks are a model; no real scan is
  performed.
- **RM19.** The six off-inventory assets are a model. The `?` mark shows that the asset has been
  found but its value has not been written.
- **RM20.** An item's risk can only be calculated if the asset's value has been written; an asset
  whose value is unwritten cannot enter any ranking even if it is discovered.
- **RM21.** Discovery is one-time and puts the asset it finds into the inventory; entering the
  inventory does not mean the value has been written.
- **RM22.** Off-inventory assets are written with higher exposure multipliers than recorded assets;
  the model's rationale is that maintenance and hardening work is applied only to recorded assets.

```js
// risk/inventory.mjs — assets in the inventory and off-inventory assets. THIS IS A MODEL; no real
// scan is performed, no real account is opened, every value is in "fictional units".

// RM17: 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 }; });

// RM18: discovery source: name | annual cost. Every asset carries a source mask.
export const SOURCE = `
  network-scan         35
  identity-record      15
  billing-record       10
  config-repository    25
  endpoint-agent       45`
  .trim().split("\n").map((r) => { const [name, b] = r.trim().split(/\s+/);
    return { name, cost: +b }; });

// RM19: asset row: name | value ('?' value not written) | exposure | threat mask |
// source mask | in inventory. The ten assets in the inventory are already recorded.
const ROW = `
  field-laptop            900  1.6  1111011  11001  E
  branch-endpoint         600  1.2  1111110  10011  E
  measurement-collector   750  1.4  0111110  10010  E
  processing-server      1800  0.6  1111101  11011  E
  perimeter-network      1200  1.8  0011100  10010  E
  identity-directory     2400  1.0  1011100  01010  E
  cloud-account          2000  1.5  1011100  01100  E
  subscriber-database    3000  0.4  1011100  00011  E
  field-application      1400  1.1  1111001  00110  E
  supplier-connection    1000  1.3  1001101  01100  E
  temporary-test-server   800  1.7  1111101  11010  H
  team-cloud-account        ?  1.6  1011100  01100  H
  field-transfer-service  700  1.9  1111011  10001  H
  retired-branch-endpoint 500  1.5  1111110  10010  H
  third-supplier-endpoint   ?  1.4  1001101  01100  H
  backup-data-copy       2200  0.8  1011100  00000  H`;

export const ASSET = ROW.trim().split("\n").map((r) => {
  const [name, v, m, mask, km, inv] = r.trim().split(/\s+/);
  return { name, value: v === "?" ? null : +v, exposureMult: +m, mask, sourceMask: km,
    inInventory: inv === "E", visible: km.includes("1") };
});
export const RECORDED = ASSET.filter((v) => v.inInventory);
export const SHADOW = ASSET.filter((v) => !v.inInventory);

// RM20: an item's risk can only be calculated if the asset's value has been written; an asset
// whose value is unwritten cannot enter any ranking even if it is discovered.
export const ALL = ASSET.flatMap((v) => THREAT
  .filter((_, j) => v.mask[j] === "1")
  .map((t) => ({ v, t, risk: v.value === null ? null : +(t.baseFreq * v.exposureMult * v.value * t.exposureRatio).toFixed(2) })));
export const REC = ALL.filter((k) => k.v.inInventory);
export const SHA = ALL.filter((k) => !k.v.inInventory);
export const rank = (L) => L.filter((k) => k.risk !== null)
  .map((k, i) => ({ k, i })).sort((a, b) => b.k.risk - a.k.risk || a.i - b.i).map((x) => x.k);
export const sum = (L) => +L.reduce((a, k) => a + (k.risk || 0), 0).toFixed(2);
```

## Counting the Two Lists

```js
// risk/missing.mjs — how the ranking would change if off-inventory items entered the list
import { RECORDED, SHADOW, SOURCE, ALL, REC, SHA, rank, sum } from "./inventory.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 S1 = rank(REC), S2 = rank(ALL);
const position = (L, k) => L.indexOf(k) + 1;

console.log(`${RECORDED.length} assets / ${REC.length} items / ${sum(REC)} fictional units are in the inventory; ` +
  `${SHADOW.length} off-inventory assets / ${SHA.length} items / ${sum(SHA)} units ` +
  `(${((sum(SHA) / sum(ALL)) * 100).toFixed(1)} percent of the true total)`);

const A = [-23, 7, 7, 10, 10, 10];
console.log("\n1. off-inventory assets");
y(A, "asset", "value", "items", "risk", "sources", "status");
for (const v of SHADOW) {
  const ks = SHA.filter((k) => k.v === v);
  y(A, v.name, v.value ?? "?", ks.length, v.value === null ? "-" : sum(ks).toFixed(2),
    v.sourceMask.split("").filter((c) => c === "1").length,
    v.value === null ? "valueless" : v.visible ? "visible" : "unseen");
}
const scorable = SHA.filter((k) => k.risk !== null);
console.log(`${scorable.length} of the ${SHA.length} off-inventory items are scorable ` +
  `(${sum(scorable).toFixed(2)} units), ${SHA.length - scorable.length} cannot enter any ranking ` +
  `because their value was never written`);

const B = [-38, 9];
console.log("\n2. what changes when the full list is ranked");
const shift = REC.map((k) => Math.abs(position(S1, k) - position(S2, k)));
y(B, "inventory list / full list items", `${S1.length} / ${S2.length}`);
y(B, "total risk", `${sum(REC).toFixed(2)} / ${sum(ALL).toFixed(2)}`);
y(B, "recorded items with a changed rank", shift.filter((x) => x > 0).length);
y(B, "largest rank shift", Math.max(...shift));
y(B, "off-inventory items in top ten",
  S2.slice(0, 10).filter((k) => !k.v.inInventory).length);
y(B, "highest off-inventory item's rank",
  Math.min(...scorable.map((k) => position(S2, k))));
y(B, "off-inventory items in top twenty",
  S2.slice(0, 20).filter((k) => !k.v.inInventory).length);

const C = [-22, -21, 10, 9, 6];
console.log("\n3. the full list's top ten");
y(C, "asset", "threat", "risk", "source", "rank");
for (const k of S2.slice(0, 10))
  y(C, k.v.name, k.t.name, k.risk.toFixed(2), k.v.inInventory ? "recorded" : "shadow", position(S1, k) || "-");

const D = [-21, 7, 8, 13, 8, 9];
console.log("\n4. per discovery source (off-inventory assets only)");
y(D, "source", "cost", "assets", "risk opened", "items", "ratio");
const opened = (f) => { const vs = SHADOW.filter(f);
  const ks = SHA.filter((k) => vs.includes(k.v) && k.risk !== null);
  return { vs, ks, r: sum(ks) }; };
for (const [i, s] of SOURCE.entries()) {
  const a = opened((v) => v.sourceMask[i] === "1");
  y(D, s.name, s.cost, a.vs.length, a.r.toFixed(2), a.ks.length, (a.r / s.cost).toFixed(3));
}
const all5 = opened((v) => v.visible);
const cost = SOURCE.reduce((a, s) => a + s.cost, 0);
y(D, "all five combined", cost, all5.vs.length, all5.r.toFixed(2), all5.ks.length,
  (all5.r / cost).toFixed(3));
const blind = SHADOW.filter((v) => !v.visible);
console.log(`assets no source ever sees: ${blind.length}, items ` +
  `${SHA.filter((k) => blind.includes(k.v)).length}, risk ` +
  `${sum(SHA.filter((k) => blind.includes(k.v))).toFixed(2)} units`);
```

```
10 assets / 47 items / 5768.61 fictional units are in the inventory; 6 off-inventory assets / 30 items / 2276.84 units (28.3 percent of the true total)

1. off-inventory assets
asset                    value  items      risk   sources    status
temporary-test-server      800      6    688.16         3   visible
team-cloud-account           ?      4         -         2 valueless
field-transfer-service     700      6    606.48         2   visible
retired-branch-endpoint    500      6    375.00         2   visible
third-supplier-endpoint      ?      4         -         2 valueless
backup-data-copy          2200      4    607.20         0    unseen
22 of the 30 off-inventory items are scorable (2276.84 units), 8 cannot enter any ranking because their value was never written

2. what changes when the full list is ranked
inventory list / full list items        47 / 69
total risk                            5768.61 / 8045.45
recorded items with a changed rank           41
largest rank shift                           22
off-inventory items in top ten                1
highest off-inventory item's rank             7
off-inventory items in top twenty             6

3. the full list's top ten
asset                 threat                     risk   source  rank
cloud-account         misconfiguration         360.00 recorded     1
cloud-account         credential-theft         315.00 recorded     2
identity-directory    misconfiguration         288.00 recorded     3
perimeter-network     misconfiguration         259.20 recorded     4
identity-directory    credential-theft         252.00 recorded     5
cloud-account         service-disruption       240.00 recorded     6
backup-data-copy      misconfiguration         211.20   shadow     -
field-application     malicious-code           192.50 recorded     7
identity-directory    service-disruption       192.00 recorded     8
field-application     misconfiguration         184.80 recorded     9

4. per discovery source (off-inventory assets only)
source                  cost  assets  risk opened   items    ratio
network-scan              35       3      1669.64      18   47.704
identity-record           15       3       688.16       6   45.877
billing-record            10       2         0.00       0    0.000
config-repository         25       2      1063.16      12   42.526
endpoint-agent            45       1       606.48       6   13.477
all five combined        130       5      1669.64      18   12.843
assets no source ever sees: 1, items 4, risk 607.20 units
```

The numbers are in the **measurement** class; its inputs are RM17–RM21.

## The Missing List's Share

Six off-inventory assets produce 30 risk items, and the risk they carry is 2,276.84 fictional
units. The true total is not 5,768.61 but **8,045.45 units**; the off-inventory share is **28.3
percent**. Every ranking, every budget calculation and every acceptance decision made across three
lessons was given under the assumption that this share did not exist.

The number matters not only because it is large but because of its **distribution**. The backup
data copy alone carries 607.20 units and outweighs six of the ten assets in the inventory. The
temporary test server, at 688.16 units, outweighs eight of those ten. What they have in common is a
low value — but a low value multiplied by a high exposure does not produce a small number.

The exposure multiplier column explains this height, and it is a deliberate choice in the model
(RM22): off-inventory assets take values between 0.8 and 1.9, recorded assets between 0.4 and 1.8.
The rationale is simple and self-reinforcing — hardening, patching and monitoring work is applied
to the list in the inventory, and an asset that is not on the list receives none of it. Being
unrecorded means not only invisibility but also **neglect**; the two effects multiply in the same
direction.

## Where the Ranking Shifts

The second table answers the real question. The incomplete list ranks 47 items, the full list
ranks 69; **41 recorded items change rank** and the largest shift is **22 positions**. Six shadow
items enter the top twenty, and one of them rises to **seventh place**.

The third table names this item: misconfiguration on the backup data copy, seventh on the list at
211.20 units, and it does not exist in the inventory list **at all**. When it enters, the
malicious-code item on the field application drops from seventh to eighth, and every item below it
moves down one place. If the budget handles the first ten items, a program working from the
incomplete list never opens this item at all — and it does not even know this is a gap, because the
item is not on the list and so does not appear in the "not handled" column either.

The size of the shift is tied to how flat the list's distribution is. When the risk distribution is
flat, 22 new items scatter throughout it and change nearly every item's position. If there had been
a sharp peak, the new items would pile up at the bottom and the top ten would not change. Here the
top ten does change, which means the gap reaches the region where **decisions are made**.

## Being Found and Being Counted Are Not the Same

The first table's last column writes a second distinction. Two of the six assets — the cloud
account the team opened and the third supplier endpoint — appear in two separate sources, but their
values were never written. These two assets produce 8 risk items, and none of those items can be
scored: no value means no impact, and no impact means no risk can be calculated. **22 of the 30
shadow items are scorable, 8 are not.**

This is the half of inventory work that gets missed most often. Discovery records that an asset
**exists**; the inventory records **what it is** — who owns it, what work it carries, what happens
if it goes down. The first can be automated, the second requires a person to make a judgment. An
asset that has been found but whose value was never written ends up in the same place as an asset
that was never found at all: **neither enters any ranking.** The only difference between them is
that the first one's name is on a list somewhere.

## Discovery's Unit Cost

The fourth table tests discovery against the course's unit of measure. Network scanning opens
three assets and 1,669.64 units of risk for 35 units; its ratio of **47.704** is the highest on the
list. Identity records open 688.16 units for 15 units (45.877). Billing records find two assets for
10 units and open **0.00 units** — the two assets they find have no value written, so the scorable
risk they open is zero.

The last row tests the sum. All five sources together find five assets for 130 units, but the risk
they open is still **1,669.64 units** — the number network scanning opens on its own. The remaining
four sources spend 95 more units and add nothing to the scorable risk; the two assets they add stay
valueless. The return per unit falls from 47.704 to **12.843**. Adding a discovery source always
finds more items, but if the item it finds cannot be scored, it does not enter the ranking and takes
no place in the budget.

The final line writes the lesson's harshest number: there is an asset **no source ever sees**,
carrying 4 items and 607.20 units. Even if all five sources were bought, it would not be found. And
the item in seventh place on the full list comes from exactly this asset. Discovery coverage is not
a lid, it is a **threshold**: everything that falls below it goes unmeasured, and everything
unmeasured is counted as accepted by default.

## Summary

- Six off-inventory assets carry 30 items and 2,276.84 fictional units; the true total is 8,045.45
  units and the off-inventory share is 28.3 percent.
- When the full list is ranked, 41 recorded items change position, the largest shift is 22 places;
  six shadow items enter the top twenty and one rises to seventh.
- A program working from the incomplete list cannot even see that it has not handled this item:
  because the item is not on the list, it is not in the "not handled" column either.
- Being found and being counted are not the same thing. Two shadow assets appear in two sources but
  their value was never written; 22 of the 30 shadow items are scorable, 8 can never enter any
  ranking.
- Network scanning gives a ratio of 47.704 for 35 units; all five sources together open the same
  risk for 130 units and the ratio falls to 12.843. Adding sources finds more assets, not more
  scorable risk.
- An asset no source ever sees carries 4 items and 607.20 units; the item in seventh place on the
  full list comes from this asset.

## Next Step

Every discovery source assumes one thing in common: the asset being sought leaves a trace in the
organization's own network, its own identity system, or its own billing. A server sitting in a
supplier's own systems leaves none of these traces. Network scanning never reaches it, the endpoint
agent never runs on it, the configuration repository does not recognize it. All that stands in the
organization's place for those assets is a contract clause and an assessment questionnaire. The
next lesson measures this across a set of three suppliers: how many controls the contract states,
how many the questionnaire actually proves, and how many items remain that look delegated but
cannot be verified.
