-
Notifications
You must be signed in to change notification settings - Fork 1
Manage Third Party Risk
Concentration risk, fourth-party exposure, and due-diligence (DD) cadence are
the auditor-facing core of a third-party risk management (TPRM) program.
Evidentia keeps a local vendor inventory, computes concentration-risk reports
across configurable dimensions, and generates / ingests DD questionnaires
(CAIQ, SIG via a licensed template, or a packaged generic baseline). This guide
walks the full operator loop with the evidentia tprm command group.
- Nothing beyond a working Evidentia install — the vendor inventory is local file-backed persistence (no third-party credentials, no network calls).
- The store location resolves via, in order: an explicit path, the
EVIDENTIA_VENDOR_STORE_DIRenvironment variable, then a platform default (platformdirs.user_data_dir). For a self-contained demo or a CI run, point it at a scratch directory so you do not touch your real inventory:
export EVIDENTIA_VENDOR_STORE_DIR="$(mktemp -d)/vendor_store"The
xlsxquestionnaire output format requires the optional[xlsx]extra (pip install 'evidentia-core[xlsx]'). Thesig/sig-liteframeworks additionally require a Shared Assessments licensed XLSX template you supply with--from-template. Thejson/csvpaths below run with no extras.
| Field | What it drives |
|---|---|
--type |
Vendor type — one of saas, subservice_org, contractor, data_processor, cloud_provider, open_source. |
--criticality-tier |
FFIEC tier — one of critical, high, medium, low. Drives the auto-computed DD review cadence. |
--regulatory-classification |
Comma-separated flags — custody, clearing, model, data_processor, critical_third_party. |
--residual-risk-score |
Integer 1–25 (0 = unscored). |
next_review_due |
Auto-computed from criticality_tier + last_due_diligence_review unless you override it with --next-review-due. |
The concentration-report dimensions (--by) are 4th-party, cloud-provider,
criticality-tier, region, regulatory-classification, and
service-category, aligned to FFIEC + OCC Bulletin 2013-29 + FRB SR 13-19
expectations.
evidentia tprm vendor add \
--name "Acme Cloud Inc." \
--type saas \
--criticality-tier critical \
--owner "alice@example.com" \
--contract-start-date 2026-01-01 \
--region "us-east-1" \
--regulatory-classification "data_processor,critical_third_party" \
--residual-risk-score 16 \
--last-due-diligence-review 2026-02-15✓ Added vendor Acme Cloud Inc. (id: e5dd135b-e489-4a4a-9fa4-f3da59589f71)
The command prints the new vendor's UUID — capture it; later commands
(show, edit, dd-questionnaire generate) take that ID. Key flags:
-
--contract-start-dateis required (YYYY-MM-DD). It is easy to miss because it sits among the optional date flags, butvendor addwill not create a record without it. -
--name,--type,--criticality-tier, and--ownerround out the minimum atomic add. See the table above for the--typeand--criticality-tierenum values. - Because we passed
--last-due-diligence-review, Evidentia auto-computesnext_review_duefrom the criticality-tier cadence (acriticalvendor reviewed2026-02-15is next due2027-02-15). - For complex records with fourth-parties and evidence pointers, skip the
atomic flags and load a YAML file with
--from-yaml <path>instead.
Add a couple more so later steps have something to aggregate:
evidentia tprm vendor add --name "Globex Hosting LLC" --type cloud_provider \
--criticality-tier high --owner "bob@example.com" \
--contract-start-date 2025-06-01 --region "us-east-1" --residual-risk-score 12
evidentia tprm vendor add --name "Initech Analytics" --type data_processor \
--criticality-tier medium --owner "carol@example.com" \
--contract-start-date 2025-09-15 --region "eu-west-1" \
--regulatory-classification "model" --residual-risk-score 6✓ Added vendor Globex Hosting LLC (id: c03d3d9e-c2d0-451c-8a6a-fc3fbf541716)
✓ Added vendor Initech Analytics (id: 6e4d2c8d-7c63-4701-83fd-38aeab4b4e6a)
evidentia tprm vendor list Vendor inventory (3 total)
┌─────────┬─────────┬─────────┬─────────┬──────────┬─────────┬──────┬────┬────┐
│ ID │ Name │ Type │ Critic… │ Owner │ Next │ Risk │ 4P │ Ev │
│ │ │ │ │ │ review │ │ │ │
├─────────┼─────────┼─────────┼─────────┼──────────┼─────────┼──────┼────┼────┤
│ e5dd13… │ Acme │ saas │ critic… │ alice@e… │ 2027-0… │ 16 │ 0 │ 0 │
│ │ Cloud │ │ │ │ │ │ │ │
│ c03d3d… │ Globex │ cloud_… │ high │ bob@exa… │ — │ 12 │ 0 │ 0 │
│ │ Hosting │ │ │ │ │ │ │ │
│ 6e4d2c… │ Initech │ data_p… │ medium │ carol@e… │ — │ 6 │ 0 │ 0 │
│ │ Analyt… │ │ │ │ │ │ │ │
└─────────┴─────────┴─────────┴─────────┴──────────┴─────────┴──────┴────┴────┘
The table is sorted by criticality then name. The 4P column counts
fourth-parties and Ev counts attached evidence refs. Filter with
--criticality-tier / --type to narrow a large inventory.
For machine consumption, add --json — a bare array of vendor records,
ready for jq:
evidentia tprm vendor list --json | jq '.[].name'"Acme Cloud Inc."
"Globex Hosting LLC"
"Initech Analytics"Each record carries the full vendor shape (id, type, criticality_tier,
relationship_owner, region, the contract / review dates,
regulatory_classification, fourth_parties, residual_risk_score,
evidence_refs, created_at / updated_at, and an evidentia_version
stamp). This same JSON is what you feed to gap analysis as a tamper-evident
vendor inventory — see What's next.
The CLI
--jsonis unpaginated (optimized for shell pipes). The REST equivalentGET /api/tprm/vendorsreturns a{total, skip, limit, vendors}pagination envelope instead; the shape divergence is intentional and documented in the CLI reference.
Show one vendor in full, including the resolved review cadence:
evidentia tprm vendor show e5dd135b-e489-4a4a-9fa4-f3da59589f71Acme Cloud Inc. (e5dd135b-e489-4a4a-9fa4-f3da59589f71)
Type: saas
Criticality tier: critical
Relationship owner: alice@example.com
Contract start: 2026-01-01
Contract end: (indefinite)
Last DD review: 2026-02-15
Next review due: 2027-02-15
Residual risk: 16 / 25
Regulatory flags: data_processor, critical_third_party
Created: 2026-05-30 06:44:33+00:00 Updated: 2026-05-30 06:44:33+00:00
Add --json to show for the raw record instead of the human view.
Atomic --<field> flags update one or more fields in place. Record a completed
DD review and bump the residual-risk score for the cloud-provider:
evidentia tprm vendor edit c03d3d9e-c2d0-451c-8a6a-fc3fbf541716 \
--residual-risk-score 15 \
--last-due-diligence-review 2026-03-01✓ Updated vendor Globex Hosting LLC (id: c03d3d9e-c2d0-451c-8a6a-fc3fbf541716)
Updating --last-due-diligence-review re-runs the cadence calculation, so
next_review_due moves automatically (a high vendor reviewed 2026-03-01 is
next due 2027-03-01). Confirm with show:
evidentia tprm vendor show c03d3d9e-c2d0-451c-8a6a-fc3fbf541716Globex Hosting LLC (c03d3d9e-c2d0-451c-8a6a-fc3fbf541716)
Type: cloud_provider
Criticality tier: high
Relationship owner: bob@example.com
Contract start: 2025-06-01
Contract end: (indefinite)
Last DD review: 2026-03-01
Next review due: 2027-03-01
Residual risk: 15 / 25
Created: 2026-05-30 06:44:51+00:00 Updated: 2026-05-30 06:45:35+00:00
edit has two other mutually-exclusive modes: --from-yaml <path> for a
scripted full-replace (preserves the original id + created_at), and
--editor to open the current record as YAML in $EDITOR. To remove a record
entirely, evidentia tprm vendor delete <id> prompts for confirmation unless
you pass -y — auditors generally prefer keeping the record and letting the
contract dates lapse over deleting history.
Aggregate the inventory across one or more dimensions to surface where you are
over-concentrated. Pass --threshold to flag any value whose vendor share
meets-or-exceeds a percentage; omit it for an unflagged distribution view.
evidentia tprm concentration-report --by criticality-tier --threshold 30 --format json{
"generated_at": "2026-05-30T06:45:49.891330Z",
"total_vendors": 3,
"threshold": 30.0,
"dimensions": [
{
"dimension": "criticality-tier",
"total_unique_values": 3,
"distribution": [
{ "value": "critical", "count": 1, "percentage": 33.3, "exceeds_threshold": true },
{ "value": "high", "count": 1, "percentage": 33.3, "exceeds_threshold": true },
{ "value": "medium", "count": 1, "percentage": 33.3, "exceeds_threshold": true }
],
"vendors_with_value": 3
}
]
}The real JSON also ends with an
"evidentia_version"field (the build that produced the report); it is trimmed here so the doc does not pin a version.
The report dict carries generated_at, total_vendors, the threshold you
passed, and a dimensions array — each with a per-value distribution
(count, percentage, and exceeds_threshold against your threshold). With
three single-vendor tiers each holding 33.3%, all three exceed a 30% threshold.
--by accepts multiple comma-separated dimensions (the default is
region,cloud-provider), and --format offers html / json / csv. CSV is
the most pipe-friendly for a single dimension:
evidentia tprm concentration-report --by region --threshold 50 --format csvdimension,value,count,percentage,exceeds_threshold
region,us-east-1,2,66.7,true
region,eu-west-1,1,33.3,false
Here two of three vendors sit in us-east-1 (66.7%), which trips the 50%
threshold — exactly the regional-concentration signal an examiner looks for.
The default --format html writes a self-contained, sortable HTML report;
redirect it to a file (--output report.html) or let it dump to stdout.
dd-questionnaire generate pre-fills a questionnaire with the vendor's metadata
(name, type, criticality, contract dates, region, regulatory classification,
fourth-party disclosures) so the receiving vendor only fills in the control
answers. The default framework is evidentia-generic (a packaged FFIEC-aligned
baseline) and the default --output-format is json:
evidentia tprm dd-questionnaire generate \
--vendor-id e5dd135b-e489-4a4a-9fa4-f3da59589f71 \
--format evidentia-generic \
--output-format json \
--output acme-dd.json✓ Wrote JSON questionnaire to acme-dd.json (20 question(s);
format=evidentia-generic; vendor=Acme Cloud Inc.)
The written file carries a vendor metadata block (echoing the inventory
record) and a questions array. Each question has a stable id, a domain,
the question_text, optional response_options, and operator notes on
acceptable evidence:
{
"id": "EVG-GOV-03",
"domain": "Governance",
"question_text": "Has your organization undergone an independent third-party security audit (SOC 2 Type II, ISO 27001, FedRAMP, or equivalent) in the last 12 months?",
"response_options": ["Yes", "No", "Not Applicable"],
"notes": "If Yes, provide the report or attestation letter and indicate the audit period covered."
}Key flags:
-
--vendor-idis required — the questionnaire is always tied to a record. -
--formatchoices:caiq-full,caiq-lite,evidentia-generic(packaged).sig/sig-liteare also accepted only with--from-template(see below). -
--output-formatchoices:json,csv,xlsx.xlsxrequires the[xlsx]extra (pip install 'evidentia-core[xlsx]') and a--outputpath (binary output can't go to stdout). Thejson/csvpaths shown here need no extra.
Requires a licensed template. SIG / SIG-Lite generation needs a Shared Assessments licensed XLSX you supply with
--from-template; Evidentia pre-fills vendor metadata into the standard cells and leaves the question content untouched for license compliance. Not shown here (the template is not redistributable):evidentia tprm dd-questionnaire generate \ --vendor-id <id> --format sig \ --from-template path/to/SIG-2026.xlsx \ --output sig-prefilled.xlsx
Once a vendor returns the completed file, dd-questionnaire ingest parses it
and correlates it back to the inventory record. Format is auto-detected from the
extension (.json / .csv / .xlsx). Correlation is required — it
resolves via --vendor-id if you pass it, otherwise via the questionnaire's
embedded vendor_id from the prefill.
evidentia tprm dd-questionnaire ingest --questionnaire acme-completed.jsonThe command parses the file, correlates it back to the vendor inventory record, and prints a summary for operator review:
✓ Ingested questionnaire from completed-q.json
Vendor: Acme Cloud (id=e1ed43f9-…) Questionnaire ID: ed778a88-… Format: evidentia-generic
Responses: 20 (answered: 0)
Vendor responses (first 25)
┌─────────────┬──────────┐
│ Question ID │ Response │
├─────────────┼──────────┤
│ EVG-GOV-01 │ (blank) │
│ EVG-GOV-02 │ (blank) │
│ … │ … │
└─────────────┴──────────┘
Pass --output-format json for a machine-readable summary. The format field
carries the questionnaire framework (evidentia-generic, caiq-lite, …); the
responses map is keyed by question ID:
{
"vendor": { "id": "e1ed43f9-…", "name": "Acme Cloud" },
"questionnaire_id": "ed778a88-…",
"format": "evidentia-generic",
"responses": { "EVG-GOV-01": "", "EVG-GOV-02": "", "…": "…" }
}The flags themselves are straightforward: --questionnaire <path> is required;
--vendor-id overrides correlation when the embedded ID is missing or you want
to file the response against a different record; --output-format is table
(default) or json.
Note on persistence: this release's
ingestis parse + correlate + display only. Writing the response intovendor.evidence_refs[]is queued for a follow-up release (pending the evidence chain-of-custody Sigstore signing — see Sign and verify evidence).
-
Feed the inventory into gap analysis.
evidentia tprm vendor list --json > vendors.jsonproduces the inventory thatevidentia gap analyze --format oscal-ar --vendor-inventory vendors.jsonembeds into an OSCAL Assessment Results document (each vendor added tometadata.parties[]and as a SHA-256-hashed back-matter resource). See Run a gap analysis. - Track remediation of vendor findings. Roll material third-party gaps into a POA&M with milestone timelines.
- Run reviews on a cadence. Wire the DD-review schedule into a recurring assessment loop with CONMON deployment.
-
Full flag reference. Every
tprmflag, default, and enum is in the CLI reference →evidentia tprm. - The data model. The base-model conventions behind the vendor record live in Concepts → Data model.
-
vendor addexits without creating a record: confirm you passed--contract-start-date(YYYY-MM-DD). It is required and sits among the optional date flags, so it is the most commonly missed argument. -
Invalid vendor ID format (expected UUID string):show/edit/deletetake the full UUID, not the truncated ID shown in thelisttable. Runevidentia tprm vendor list --json | jq '.[].id'to copy a full ID. -
xlsx requires the [xlsx] extra(or an import error onopenpyxl): thexlsxoutput format needspip install 'evidentia-core[xlsx]'. Usejsonorcsvif you don't need a workbook. -
concentration-reportshows everything at 0%/100% or an empty distribution: the report is computed over whatever is in the store. ConfirmEVIDENTIA_VENDOR_STORE_DIRpoints at the inventory you populated (a freshmktemp -dstore starts empty), and that the vendors carry the dimension you asked for with--by(e.g.--by regionneeds--regionset on records).
-
- AI Governance
- Air Gapped Install
- Ci Integration
- CONMON Deployment
- Emit Cyclonedx VEX
- Emit OCSF Detection
- Emit SARIF
- Explain Controls
- Generate And Quantify Risk
- Governance Metrics And Workflows
- Ingest OCSF
- Manage Model Risk
- Manage POAM
- Manage Third Party Risk
- MCP Client Setup
- OSPS Self Assessment
- Run Gap Analysis
- Serve The Web Ui
- Sign And Verify Evidence