Skip to content

Identity Risk Scoring

v5 status

In v5, risk scoring is driven from the UI (Admin > Risk Scoring). The PowerShell risk scoring functions (Invoke-FGRiskScoring, New-FGRiskProfile, New-FGRiskClassifiers) in tools/riskscoring/ are stubbed and return "not yet implemented in v5". The in-browser wizard and the Node.js scoring engine (app/api/src/riskscoring/engine.js) are the active implementation path.

Overview

Identity Atlas includes a universal risk scoring engine that assigns risk scores (0–100) to all entity types — Principals, Resources (including BusinessRoles), Contexts, and Identities. All scoring runs on your own infrastructure — no sensitive identity data is ever sent to external services.

Three-Phase Architecture

flowchart LR
    subgraph Phase1["Phase 1: Context (one-time)"]
        A["New-FGRiskProfile\nPublic domain info only"] --> B["New-FGRiskClassifiers\nIndustry-specific patterns"]
    end
    subgraph Phase2["Phase 2: Scoring (daily)"]
        B --> C["Invoke-FGRiskScoring\n4-layer batch engine"]
    end
    subgraph Phase3["Phase 3: Analysis"]
        C --> D[Risk Scoring UI Page]
        C --> E["Org Chart with\nrisk propagation"]
        C --> F[SQL: RiskScores table]
    end

Phase 1 (one-time setup):

New-FGRiskProfile -Domain "yourcompany.com" -LLMProvider Anthropic -LLMApiKey $key -ConfigFile '.\Config\mycompany.json'
New-FGRiskClassifiers -ConfigFile '.\Config\mycompany.json'

Phase 2 (run after each sync):

Invoke-FGRiskScoring -ConfigFile '.\Config\mycompany.json'

Phase 3 (analysis):

  • UI: Risk Scoring page, Org Chart
  • SQL: SELECT entityId, entityType, riskScore, riskTier FROM RiskScores ORDER BY riskScore DESC
  • Fast filter: riskScore and riskTier columns are denormalized onto Principals and Resources

4-Layer Scoring Engine

flowchart TD
    E[Entity] --> L1["Layer 1: Direct Match\nClassifier patterns on name/description\nResource type multiplier"]
    L1 --> L2["Layer 2: Membership Analysis\nHigh-risk member/group density\nPIM eligibility, no-owner signals"]
    L2 --> L3["Layer 3: Structural Hygiene\nStale sign-in, never used\nGuest accounts, missing description\nDynamic membership, directory role signals"]
    L3 --> L4["Layer 4: Propagation\nInherit risk from riskiest\nmember / group / parent"]
    L4 --> S["Final Score 0–100\nClamped + tiered"]

Each layer adds points; the final score is clamped to 0–100.

Scoring by Entity Type

Entity Type Layer 1 Layer 2 Layer 3 Layer 4
Principal (User) Classifier matches on name/title/UPN Group count, PIM eligibility, high-risk group density Stale sign-in (90/180d), never signed in, guest account, active high-privilege usage Riskiest group membership
Principal (AI Agent/SP) Agent classifier matches on name Group count, high-risk resource density No-human-in-loop penalty, type-specific bonus, active production workload detection Riskiest resource membership
Resource Classifier + resourceType multiplier High-risk member density, PIM-eligible members, no owner No description, dynamic membership, directory role signals, ghost app roles Riskiest member
BusinessRole (Resource) Classifier matches High-risk assignee density No review configured, missed reviews, no auto-removal Aggregate contained resource risk
OrgUnit Name/dept classifiers, hierarchy position Aggregate principal risk Size extremes (tiny/huge), no manager, high external ratio Parent OrgUnit risk
Identity Account count, multi-system Highest-risk linked principal Orphaned accounts, low confidence, not verified Critical/High principal propagation

Risk Tiers

Tier Score Action
Critical 90–100 Requires immediate attention
High 70–89 Should be reviewed soon
Medium 40–69 Monitor regularly
Low 20–39 Low concern
Minimal 1–19 Negligible
None 0 No signals detected

Analyst Overrides

Analysts can adjust any entity's score with a required justification. The adjustment must be a whole number between −50 and +50, and the justification must be 3–500 characters:

  • Via UI: Risk Scoring page → click Override button
  • Overrides are stored in RiskScores and preserved across re-scoring runs
  • Override history is preserved across re-scoring runs

Configuring the AI provider

The AI provider is configured in Admin → LLM Settings. Three providers are supported:

Provider provider value Default model Notes
Anthropic anthropic claude-sonnet-4-6 API key required
OpenAI openai gpt-4o API key required
Azure OpenAI azure-openai (deployment name required) Also requires endpoint URL and deployment name

Once you enter the API key and click Test, IdentityAtlas verifies the connection and populates the model dropdown from the provider's API. The key is stored encrypted in the built-in secrets vault — it is never stored as plain text.

For Azure OpenAI the endpoint must be a valid Azure OpenAI hostname (*.openai.azure.com, .us, or .cn). The deployment name is the name you gave the deployment in Azure, not the underlying model name.

Data Privacy

No identity data ever leaves your infrastructure

  • Phase 1 only contacts an LLM — the prompt contains only public organisational context: the domain name, optional organisation name, optional free-text hints you type, and any text you paste from internal documents.
  • No identity data — no user names, email addresses, group names, or access assignments — is ever sent to the AI provider.
  • All scoring (matching classifiers against your data) runs locally against your database with no network calls.

What is sent to the AI, exactly:

What Example
Domain name contoso.com
Organisation name (optional) Contoso Ltd
Free-text hints (optional) We operate in the Netherlands under NIS2
Text from URLs you add (optional) Scraped text from public or internal pages

Nothing else. The AI generates regex patterns from this context; those patterns are then stored locally and applied against your data entirely on-premises.

Provider security comparison:

Provider Data stays in your region? Used for AI training?
Anthropic API No — routed to api.anthropic.com Depends on your plan. Paid API plans include a no-training clause; verify your agreement.
OpenAI API No — routed to api.openai.com Consumer tier: opt-out required in account settings. Enterprise agreement: excluded by contract.
Azure OpenAI Yes — stays within your Azure subscription No — Microsoft Azure terms contractually exclude customer prompts from model training.

For regulated environments or when in doubt, use Azure OpenAI: the data stays within your Azure tenant and training exclusion is contractual by default.

RiskScores Table

-- Top risky principals
SELECT p.displayName, p.principalType, rs.riskScore, rs.riskTier,
       rs.directScore, rs.membershipScore, rs.structuralScore, rs.propagatedScore
FROM Principals p
JOIN RiskScores rs ON rs.entityId = p.id AND rs.entityType = 'Principal'
ORDER BY rs.riskScore DESC;

-- All entity types together
SELECT entityId, entityType, riskScore, riskTier
FROM RiskScores
ORDER BY riskScore DESC;