Guide · Risk Management · SharePoint

How to Build a Risk Register in SharePoint — ISO 27001, ISO 27701 & ISO 42001

One SharePoint List, three frameworks. A practical build guide — with the full column schema, conditional formatting JSON you can paste in directly, Power Automate flows for review reminders and risk alerts, and the views auditors expect to see.

No GRC platform required. No annual licence. Built on what you already own — and owned by you, not locked into a vendor's export format.

Why a SharePoint List beats a spreadsheet for a risk register

Most organisations start their risk register in Excel. It works for the first audit cycle. By the second, the problems compound: no real-time collaboration, no version control that tracks who changed what and when, no automated reminders when reviews are overdue, no way to give different risk owners visibility of their items without sending them the whole workbook.

SharePoint Lists solve all of this without adding a new platform. If you're already on Microsoft 365, the List is included in your licence. You get version history, item-level permissions, calculated columns, conditional formatting, Power Automate integration, and views that different stakeholders can filter to their scope — all within the same tool your team uses every day.

The tradeoff is a little more setup effort upfront. This guide covers that setup in full so you don't have to figure it out trial and error.

One register, three frameworks

ISO 27001, ISO 27701, and ISO 42001 each have their own risk assessment requirements. ISO 27001 Clause 6.1.2 requires you to identify information security risks. ISO 27701 extends that to privacy risks. ISO 42001 adds AI-specific risk assessment including model risk, shadow AI, and transparency obligations.

The temptation is to run three separate registers. Don't. A single integrated register with a Framework column (ISMS / PIMS / AIMS) is the correct answer for three reasons:

  • Many risks genuinely span frameworks — a shadow AI risk has security, privacy, and governance dimensions simultaneously. A single register captures this naturally; three registers create duplication and inconsistency.
  • Integrated management system auditors (conducting combined ISO 27001 + 27701 + 42001 audits) expect to see one register. Three separate ones look like the frameworks aren't genuinely integrated.
  • Maintenance is dramatically lower. Risk reviews happen once, not three times. The change log is one document. The risk committee sees the full picture in one view.

The Framework column lets any auditor filter to their scope. The same scoring methodology applies across all three. This is the structure the guide builds.

The full column schema

Build each column exactly as specified. The column type matters — calculated columns won't work if the source columns are the wrong type, and Power Automate flows reference internal column names.

Column name SharePoint type Notes
Risk ID Single line of text Format: RISK-001. Set as the Title column or add alongside it.
Framework Choice Options: ISMS, PIMS, AIMS. Allow multiple — some risks span frameworks.
Category Choice Use the taxonomy from the scoring guide (Access & Identity, Shadow AI, etc.)
Risk Title Single line of text Short name, 5–10 words. Auditors scan this column first.
Risk Description Multiple lines of text Describe the threat, the mechanism, and the affected asset. 2–4 sentences.
Threat Source Single line of text E.g. External threat actor, Departing employee, Vendor change.
Affected Asset / Process Single line of text Be specific — "Microsoft 365 tenant" not "IT systems".
Inherent Likelihood Number Scale 1–5. Score before any controls are applied.
Inherent Impact Number Scale 1–5. Financial + operational + regulatory + reputational.
Inherent Score Calculated Formula: =[Inherent Likelihood]*[Inherent Impact]
Inherent Level Calculated Formula: =IF([Inherent Score]>=20,"Critical",IF([Inherent Score]>=15,"High",IF([Inherent Score]>=7,"Medium","Low")))
Treatment Choice Options: Mitigate, Transfer, Avoid, Accept
Treatment Rationale Multiple lines of text Why this treatment? What controls specifically? Auditors read this.
Linked SoA Controls Multiple lines of text Reference SoA control IDs, e.g. A.5.15, A.5.16, A.8.2. One per line.
Residual Likelihood Number Scale 1–5. Score after controls are operating.
Residual Impact Number Scale 1–5.
Residual Score Calculated Formula: =[Residual Likelihood]*[Residual Impact]
Residual Level Calculated Formula: =IF([Residual Score]>=20,"Critical",IF([Residual Score]>=15,"High",IF([Residual Score]>=7,"Medium","Low")))
Risk Owner Person or Group Single person. This drives Power Automate reminders.
Next Review Date Date and Time Drive this from Residual Level: Critical/High = +30 days, Medium = +90 days, Low = +365 days.
Last Reviewed Date and Time Updated manually or via a flow when status changes.
Status Choice Options: Identified, In Progress, Mitigated, Accepted, Transferred, Closed
Change Notes Multiple lines of text Append notes when scoring or treatment changes. Manual audit trail.

Calculated column note: SharePoint calculated columns use a formula syntax similar to Excel but with some differences — wrap column names in square brackets, not quotes. Test each calculated column with a sample entry immediately after creating it.

Conditional formatting JSON

Apply these directly in SharePoint via Column settings → Format this column → Advanced mode. Paste the JSON, save, and the column renders colour-coded badges automatically.

Risk Level badge — Residual Level & Inherent Level columns

Renders Critical (red), High (orange), Medium (amber), Low (green) as pill badges. Apply to both the Residual Level and Inherent Level columns.

{
  "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/column-formatting.schema.json",
  "elmType": "div",
  "style": {
    "display": "inline-block",
    "padding": "4px 12px",
    "border-radius": "20px",
    "font-weight": "700",
    "font-size": "0.78rem",
    "text-transform": "uppercase",
    "letter-spacing": "0.5px",
    "color": "white",
    "background-color": "=if([$ResidualLevel] == 'Critical', '#b91c1c', if([$ResidualLevel] == 'High', '#c2410c', if([$ResidualLevel] == 'Medium', '#b45309', '#15803d')))"
  },
  "txtContent": "[$ResidualLevel]"
}

For the Inherent Level column, replace [$ResidualLevel] with [$InherentLevel] in both the background-color formula and txtContent.

Status badge — Status column

Colour-codes each status value so the register's overall health is visible at a glance.

{
  "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/column-formatting.schema.json",
  "elmType": "div",
  "style": {
    "display": "inline-block",
    "padding": "4px 12px",
    "border-radius": "20px",
    "font-weight": "600",
    "font-size": "0.78rem",
    "color": "white",
    "background-color": "=if([$Status] == 'Identified', '#6366f1', if([$Status] == 'In Progress', '#0284c7', if([$Status] == 'Mitigated', '#15803d', if([$Status] == 'Accepted', '#b45309', if([$Status] == 'Transferred', '#7c3aed', '#64748b')))))"
  },
  "txtContent": "[$Status]"
}
Treatment type badge — Treatment column

Distinguishes treatment types visually — useful when reviewing the register distribution (too many Accepted risks in a single category is an audit flag).

{
  "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/column-formatting.schema.json",
  "elmType": "div",
  "style": {
    "display": "inline-block",
    "padding": "4px 12px",
    "border-radius": "20px",
    "font-weight": "600",
    "font-size": "0.78rem",
    "color": "white",
    "background-color": "=if([$Treatment] == 'Mitigate', '#1d4ed8', if([$Treatment] == 'Transfer', '#7c3aed', if([$Treatment] == 'Avoid', '#0f766e', '#92400e')))"
  },
  "txtContent": "[$Treatment]"
}
Overdue review highlight — Next Review Date column

Turns the Next Review Date red when it's in the past and the risk isn't Closed or Mitigated. Makes overdue reviews impossible to miss.

{
  "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/column-formatting.schema.json",
  "elmType": "div",
  "style": {
    "display": "inline-block",
    "padding": "4px 10px",
    "border-radius": "6px",
    "font-weight": "=if(toDateString([$NextReviewDate]) < toDateString(now()) && [$Status] != 'Mitigated' && [$Status] != 'Closed', '700', '400')",
    "color": "=if(toDateString([$NextReviewDate]) < toDateString(now()) && [$Status] != 'Mitigated' && [$Status] != 'Closed', 'white', '#0f172a')",
    "background-color": "=if(toDateString([$NextReviewDate]) < toDateString(now()) && [$Status] != 'Mitigated' && [$Status] != 'Closed', '#b91c1c', 'transparent')"
  },
  "txtContent": "=toDateString([$NextReviewDate])"
}

Views to build

Each view serves a different purpose. Build all five and pin the most-used ones to the page. Go to View options → Create new view for each.

All Risks — Standard list

The default view. All columns visible. Sort by Residual Score descending so Critical risks always appear at the top. This is the view you use during risk committee meetings.

Sort: Residual Score (desc) → Framework (asc)

Board by Residual Level — Kanban

Set view type to Board. Group by Residual Level. Four lanes: Critical, High, Medium, Low. Drag items between lanes to update status during a risk workshop. Visually compelling for management presentations.

Group column: Residual Level

By Framework — grouped list

Group by Framework. ISMS / PIMS / AIMS collapse groups. Use this view when preparing audit evidence packs for a single-framework audit — collapse the other two groups and screenshot only the relevant one.

Group by: Framework → Sort by Residual Score (desc)

My Risks — personal view

Filter: Risk Owner is equal to [Me]. Shows each person only their own risks. Share this view URL directly with risk owners. Combine with the Power Automate reminder flow so owners receive a link that lands them here.

Filter: Risk Owner = [Me]

Overdue Reviews

Filter: Next Review Date is less than [Today] AND Status is not equal to Mitigated AND Status is not equal to Closed. Run this view at the start of every risk committee meeting as the standing agenda item for stale risks.

Filter: Next Review Date < [Today] AND Status ≠ Mitigated/Closed

Board by Status — treatment pipeline

Set view type to Board. Group by Status. Four active lanes: Identified → In Progress → Mitigated → Accepted. Shows your treatment pipeline at a glance. Risks sitting in Identified for more than 30 days need a conversation.

Group column: Status

Power Automate flows

Three flows that convert a static list into a managed risk programme. Build each in Power Automate → Create → Automated cloud flow (for the first two) or Scheduled cloud flow (for the third). All use the SharePoint connector.

1

Review reminder — notify Risk Owner 7 days before due

Trigger: Scheduled · Runs daily at 8 AM

  1. Trigger: Recurrence — interval 1, frequency Day, at 08:00
  2. Action — Get items: SharePoint › Get items from your Risk Register list. Filter query: NextReviewDate le '[utcNow(addDays(7))]' and NextReviewDate ge '[utcNow()]' and Status ne 'Mitigated' and Status ne 'Closed'
  3. Action — Apply to each: Loop over the returned items
  4. Inside loop — Send an email (V2): To: Risk Owner email (use the RiskOwner.Email dynamic value). Subject: Risk review due in 7 days — [Risk ID] [Risk Title]. Body: include Risk ID, Framework, Residual Level, Next Review Date, and a direct link to the list item.

Tip: Add a condition before the email step: only send if Residual Level is not equal to "Low" — this suppresses noise for annual low-risk reviews that don't need 7-day advance notice.

2

New High / Critical risk alert — notify risk committee

Trigger: Automated · When a new item is created or modified in the list

  1. Trigger: SharePoint › When an item is created or modified (select your Risk Register site and list)
  2. Action — Condition: Check if ResidualLevel is equal to "Critical" OR ResidualLevel is equal to "High"
  3. If Yes — Post a message in a Teams channel: Target your risk committee channel. Message: ⚠️ [Residual Level] risk logged — [Risk ID]: [Risk Title] · Framework: [Framework] · Owner: [Risk Owner] · Next Review: [Next Review Date] with a link to the item.
  4. If Yes — Send an email (optional): To your risk committee distribution list, same content as the Teams message.
  5. If No: Do nothing (terminate branch).

Tip: Add a second condition inside the Yes branch to check if the Status is "Identified" — this prevents the flow from firing every time someone edits a description on an existing High risk.

3

Weekly overdue escalation — surface stale risks

Trigger: Scheduled · Runs every Monday at 7 AM

  1. Trigger: Recurrence — interval 1, frequency Week, on Monday at 07:00
  2. Action — Get items: Filter query: NextReviewDate lt '[utcNow()]' and Status ne 'Mitigated' and Status ne 'Closed' and Status ne 'Accepted'
  3. Action — Condition: Check if the count of returned items is greater than 0
  4. If Yes — Create HTML table: Use the Select action to build a table with columns Risk ID, Risk Title, Risk Owner, Next Review Date, and Residual Level. Then use Send an email with the table in the body.
  5. Send to: risk committee lead. Subject: [count] overdue risk reviews — action required. Include a link to the Overdue Reviews view.

Tip: Run this flow manually for the first time before scheduling it. "Get items" filter queries in SharePoint use OData syntax — test against your actual column internal names (visible in List Settings → Columns → click the column name and read the URL).

What auditors actually look for

Having a risk register is necessary but not sufficient. These are the specific things ISO 27001 auditors check during sampling — and the most common gaps we see.

Inherent risk must be scored separately

The single most common gap in risk registers we review. If your register only shows residual scores, auditors cannot verify that you understand the actual risk landscape. ISO/IEC 27005 is explicit that risk assessment includes identifying the risk before controls — the inherent score. A register that jumps straight to residual looks like the scores were chosen to justify existing controls rather than assess actual risk.

Every risk must link to a SoA control

The audit trail that connects the risk register to the Statement of Applicability is what auditors follow during sampling. A risk with no Linked SoA Controls reference, or a SoA control with no risk driving its inclusion, both raise findings. The linkage proves the ISMS is genuinely integrated rather than two separate documents.

Version history must demonstrate active management

SharePoint's built-in version history covers this automatically — every edit is timestamped and attributed. What auditors check for is that the register has actually changed over time. A register with a single version entry from twelve months ago, or one where all items have "Mitigated" status and no review dates, signals that it was created for audit and then abandoned.

Risk acceptance must be documented

If a risk is above your stated risk acceptance threshold and the Treatment is "Accept", auditors expect to see documented management sign-off. Add a Risk Acceptance Sign-off column (multi-line text) or a SharePoint approval workflow for accepted risks. A risk above threshold with no documented acceptance rationale is a major nonconformity.

Connecting the risk register to your SoA List

If you've also built your Statement of Applicability as a SharePoint List (the recommended approach for the same reasons this guide covers), link the two explicitly.

The cleanest implementation uses a Lookup column in each direction:

  • In the Risk Register List: add a Linked SoA Controls Lookup column pointing to the SoA List's Control ID column. Multi-select allowed.
  • In the SoA List: add a Driving Risks column — either a Lookup back to the Risk Register, or a multi-line text field listing risk IDs manually.

This bidirectional reference is what lets auditors follow the trail in either direction — from a risk to the controls treating it, or from a control back to the risks that justify its inclusion. It's the evidence that your management system is genuinely integrated, not a collection of independent documents.

Common questions

Can one SharePoint List cover all three frameworks?

Yes — and it's the correct answer. A Framework column (ISMS / PIMS / AIMS) lets each auditor filter to their scope. Many risks span frameworks legitimately. A single register with appropriate categorisation is what integrated management system auditors expect to see.

Do I need to score inherent and residual separately?

Yes, and this is one of the most common gaps we see in registers we review. Auditors want inherent risk (before controls) scored explicitly. Without it, they cannot verify you understand the actual risk landscape rather than working backwards from the controls you already have.

How often does the register need to be reviewed?

ISO 27001 Clause 8.2 requires reviews at planned intervals and when significant changes occur. In practice: Critical and High residual risks monthly, Medium quarterly, Low annually. The Next Review Date column and Power Automate reminder flow operationalise this without manual tracking.

What if a risk is above threshold and we're accepting it?

Documented management sign-off is required. A risk above your stated acceptance threshold with Treatment set to "Accept" but no documented rationale or approver is a major nonconformity. Add a Risk Acceptance Sign-off column, or build a SharePoint approval workflow that captures the approver and date automatically.

Related services

ISO 27001 Security Management ISO 27701 Privacy Management ISO 42001 AI Governance Automating Compliance M365 · Azure · AWS

Want this built in your environment?

We can deploy the full risk register — SharePoint List, column schema, conditional formatting, Power Automate flows, and pre-populated with example risks across your target frameworks — as part of a scoping engagement or standalone. A 30-minute call will tell you what your register currently covers and what auditors would flag.

📞 Microsoft Teams