The Spreadsheet Problem

Every security team I have worked with tracks risks in a spreadsheet. The format varies. The column count ranges from twelve to forty. Some have color-coded risk heat maps. Some have dropdown validations. Some have both. The constant is that a human sits between every input and the spreadsheet. Someone identifies a risk, tells the security team about it (maybe over Slack, maybe in a meeting, maybe not at all), and someone on the GRC team manually enters it into the register, creates a tracking issue, and links them together.

The register I work with has 33 columns across four sections: identification, assessment, treatment, and monitoring. Each risk needs a row in the spreadsheet and a corresponding issue in the project tracker. Column A of each row is hyperlinked to the tracking issue, and that hyperlink is the single source of truth for whether a risk is being tracked. Before this project, populating a single risk meant clicking through dozens of cells, creating an issue with a specific description template, then manually hyperlinking the cell. Fifteen to twenty minutes per risk if everything went smoothly.

The spreadsheet itself was fine. The process around it created three problems. First, the mechanical work of populating cells was tedious enough that risks accumulated in backlogs before they made it into the register. Second, reporting a risk required knowing who to tell and hoping they would log it. Third, the institutional knowledge for how to populate the register correctly lived in one person's head. If that person was unavailable, risks waited.

The Backfill

Before automating intake, the existing register needed to be complete. Multiple risks needed tracking issues created and hyperlinked. Doing this manually would have taken a full day of clicking into cells, copying issue URLs, and using Cmd+K to insert links one at a time.

The first attempt at automation went through the spreadsheet UI: clicking into each cell, typing values, pressing Tab to advance. This was fragile. The Name Box did not navigate to cells reliably. Cells sometimes did not activate on click. Dropdown validations required exact string matches that were easy to mistype. The approach worked in theory and failed in practice because spreadsheet UIs are designed for human interaction patterns that do not translate to programmatic control.

The solution was Google Apps Script. Instead of navigating the UI, a single function writes all non-formula columns in one execution. A second function sets rich-text hyperlinks programmatically, replacing the manual Cmd+K workflow entirely. What would have taken hours of clicking took seconds.

function setHyperlinks() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet()
    .getSheetByName('Risk Register');
  var data = [
    [5, 'R-002', 'https://tracker.example.com/issue/RIS-29'],
    [6, 'R-003', 'https://tracker.example.com/issue/RIS-30'],
    // ... all risks in one batch
  ];
  for (var i = 0; i < data.length; i++) {
    var cell = sheet.getRange('A' + data[i][0]);
    cell.setRichTextValue(
      SpreadsheetApp.newRichTextValue()
        .setText(data[i][1])
        .setLinkUrl(data[i][2])
        .build()
    );
  }
}

The lesson was immediate: if your automation workflow involves Google Sheets and you are interacting through the UI, stop and write an Apps Script. The reliability difference is not incremental. It is categorical.

The Skill

With the manual process understood and the Apps Script patterns proven, the next step was codifying everything into a reusable skill. A skill in this context is a structured instruction file that an AI assistant reads and follows. It encodes process knowledge the same way a runbook encodes operational procedures, except the consumer is an AI system that can execute the steps programmatically.

The risk assessment skill captures the full workflow: the 33-column register structure with its spacer columns and formula columns to avoid, the risk statement pattern ([Threat] increases the risk of [Event], leading to [Impact]), the tracking issue description template with its risk analysis sections and security metadata table, the five-dimension impact rating scale, the Apps Script templates for both population and hyperlinking, and the writing rules that keep the register consistent.

The skill supports two modes. Structured mode walks through a guided assessment covering all eighteen required fields: product, functional area, assets, CIA triad category, likelihood, five impact dimensions, current controls, control coverage, control gaps, risk response, planned activities, owner, target date, and treatment status. Intake mode is the fast path: drop in raw notes, a Slack thread, or pentest findings, and the skill drafts the complete risk statement, description, and proposed ratings in a single response. The operator confirms or corrects, and the system populates everything.

One field gets special treatment. The Treatment Status is the one value the skill never proposes on its own. Whether a risk is "Not Started," "Accepted," or "In Progress" is a judgment call that belongs to the operator. The skill asks every time. This distinction between fields the AI can reasonably propose (likelihood based on context, impact based on the threat scenario) and fields that encode a decision (treatment strategy, ownership) is what makes the workflow trustworthy. The AI handles pattern matching and data formatting. Humans handle the calls that carry organizational authority.

The Pipeline

The skill automated the work of a single operator sitting at the register. The pipeline automated the work of getting risks to the operator in the first place.

Before the pipeline, reporting a risk required knowing who on the security team to tell, how to describe it in terms that would translate to the register format, and hoping the handoff would not get lost in a Slack thread. The barrier was high enough that risks went unreported. Not because people did not notice them, but because the path from "I see something concerning" to "it is tracked in the register" required too much knowledge of the internal process.

The pipeline has four components. A Slack workflow form in a public channel lets anyone in the company submit a security risk. Six fields: what is the concern, where did it come from, which product, what systems are affected, any existing controls, and a link for context. No security expertise required. Describe what you see.

Submissions automatically post to a private review channel visible only to the security team. Each submission arrives as a structured message with all form fields populated. The reviewer reads the submission, replies in the thread with the ratings that require security judgment (likelihood, impact dimensions, risk response, owner, treatment status), and reacts with a checkmark to approve.

A scheduled task runs every weekday morning. It scans the review channel for approved submissions that have not been processed yet. For each one, it reads the reviewer's ratings from the thread replies, creates the tracking issue with a structured description, populates the register via Apps Script, hyperlinks column A, and replies in the thread with the result: risk ID, issue URL, confirmation. A clipboard reaction marks the submission as processed.

The entire flow from submission to tracked risk requires zero manual spreadsheet work. The judgment calls (ratings, ownership, response strategy) stay with a human who has the authority and context to make them. The mechanical work (data entry, issue creation, hyperlinking, confirmation) runs automatically.

What This Changed

Lower friction means more visibility

The most significant change was not speed. It was coverage. When reporting a risk requires knowing the security team's process, only people close to the security team report risks. When reporting a risk requires filling out a six-field form in Slack, engineers, IT staff, and product managers report things they previously would have mentioned in passing or not at all. The register sees more because the barrier to entry dropped.

Skills are institutional memory

The risk assessment skill went through several iterations in a single session. The first version had instructions for Cmd+K hyperlinking. When Apps Script proved more reliable, the skill updated. When the intake pipeline added Slack message parsing, the skill gained a new section. Each iteration made future runs more accurate. A skill is not documentation. It is institutional memory that actively improves the execution of the process it describes. When the operator is unavailable, anyone with access to the skill can process risks the same way because the process knowledge is encoded in the file, not in someone's head.

Apps Script is the right layer

Three layers of automation were available for the spreadsheet: UI interaction (clicking cells), API export (reading the sheet as data), and Apps Script (running code inside the spreadsheet environment). UI interaction was fragile. API export worked for reads but required careful handling of cell formatting, data validation, and rich-text hyperlinks for writes. Apps Script operated at the right level of abstraction: it has full access to the spreadsheet's internal features (rich text, data validation, formulas) without the fragility of UI automation or the limitations of external API access.

Separate judgment from mechanics

The pipeline design makes a clear split. The parts of risk management that require expertise, context, and authority (Is this a real risk? How severe? Who owns it? What is the response strategy?) stay with humans. The parts that are purely mechanical (format the data, validate the dropdown values, create the issue, populate the cells, set the hyperlink, send the confirmation) run without human involvement. This separation is worth being explicit about because the instinct with automation is to automate everything or nothing. The useful middle ground is automating the mechanics while preserving the judgment layer.

What This Did Not Change

The spreadsheet is still the source of truth. The register format did not change. The column structure, the rating scales, the formula columns, the data validation rules: all unchanged. The pipeline writes to the spreadsheet; it does not replace it. This matters because the spreadsheet has survived three years of organizational change, two audit cycles, and a team restructuring. It works. Building a custom application to replace it would have taken months and introduced migration risk for marginal benefit. The automation wraps around the spreadsheet rather than replacing it, which means adoption required zero change to how anyone reads or references the register.

The assessment methodology did not change either. The five-dimension impact framework, the likelihood scale, the treatment status categories: these are the same ones the team has used since the register was created. The pipeline encodes the existing methodology; it does not invent a new one. When the methodology evolves (and it will), the skill updates to reflect the change. The pipeline adapts because the process knowledge lives in a file that can be edited, not in application logic that requires a deployment.

The Sequence

The order matters. We did not design the pipeline first. We manually processed risks, learned the pain points (cell-by-cell entry is slow, Cmd+K is unreliable, hyperlinks are the only source of truth for tracking), and then automated the parts that were mechanical. The skill and pipeline are directly shaped by the manual experience. They solve problems we actually encountered, not problems we imagined.

Start manual. Identify what is judgment and what is mechanics. Automate the mechanics. Codify the judgment criteria so they are reviewable and repeatable. Then open the front door so anyone can contribute to the process without needing to understand its internals. The spreadsheet stays. The process around it gets faster, more reliable, and accessible to the whole organization.