azurenoops / azurenoops/spin_agent

Executive Strategic Audit - SPIN AGENT

Open
#636 0 comments 0 reactions 0 assignees View on GitHub
documentation
Dominant language
C#
Stars
3
Forks
1
Avg merge
11h 20m
Merged PRs (30d)
70

Description

# Executive Strategic Audit — SPIN AGENT (ATO Copilot)

**Prepared by:** Friday (F.R.I.D.A.Y.) — Senior SaaS & Platform Engineering Lead
**Date:** August 6, 2026
**Source:** Live gh api reconnaissance of azurenoops/spin_agent (public repo, main branch)
**Audience:** Cyborg / Security & Architecture Review

---

## Executive Summary

SPIN AGENT (ATO Copilot) is a production-grade, AI-powered DoD compliance platform that automates all seven phases of the NIST Risk Management Framework. It is technically ambitious and well-structured for its mission domain. The codebase demonstrates strong security awareness (CAC/PIV auth, PIM JIT, multi-tenant isolation, Serilog redaction, audit logging) and solid test coverage with 3,164 tests.

**Three areas require immediate attention before any DoD production authorization:**

1. A documented P1 cross-tenant data leak (fixed, but the root pattern can recur)
2. Total authentication bypass in non-production environments — a staging misconfiguration risk
3. Absence of a formal threat model and SBOM

Strategic positioning is strong: no direct competitor covers all 7 RMF phases in a single conversational interface. The main platform risks are operational rather than architectural.

---

## 1. Product & Mission

- **Repo:** azurenoops/spin_agent (public)
- **Mission:** AI-powered DoD RMF automation — Prepare → Categorize → Select → Implement → Assess → Authorize → Monitor
- **Unique claim:** First tool covering all 7 RMF steps in one conversational interface
- **AI engine:** Azure OpenAI GPT-4o, function calling, 130 MCP tools (max 72/request)
- **Target cloud:** Azure Government (default)
- **Channels:** VS Code (Copilot Chat), Web Chat (React + SignalR), Stdio MCP, HTTP REST/SSE, M365 Teams bot

---

## 2. Architecture Overview

### Stack
- Backend: C# 13 / .NET 9.0, ASP.NET Core, EF Core 9.0
- AI: Azure OpenAI (GPT-4o), Microsoft.Extensions.AI 9.4-preview, Azure.AI.Agents.Persistent
- Databases: SQLite (dev), SQL Server 2022 (prod), Redis (throttle counters)
- Frontend: React 18/19 + TypeScript 5
- Extensions: VS Code (TypeScript), M365 Teams bot (TypeScript, Adaptive Cards)
- Infra: Docker, Azure Container Apps, Azure Government

### Key Files
- BaseAgent: src/Ato.Copilot.Agents/Common/BaseAgent.cs
- ComplianceAgent: src/Ato.Copilot.Agents/Compliance/Agents/ComplianceAgent.cs
- EF Context: src/Ato.Copilot.Core/Data/Context/AtoCopilotContext.cs

### AI Architecture
- Uses IChatClient (provider-agnostic) — not raw Azure OpenAI SDK
- AzureAiOptions.Provider switches between Foundry, Azure OpenAI, and deterministic paths
- CanHandle(message) returns confidence 0.0-1.0; orchestrator routes to highest scorer (threshold 0.3)
- Entire NIST SP 800-53 Rev 5 OSCAL catalog compiled as embedded resources into the agent binary

---

## 3. Security Architecture

### Authentication
- CacAuthenticationMiddleware.cs: CAC/PIV — writes ClaimsPrincipal to HttpContext.User
- CacPassthroughAuthHandler.cs: Scheme "CacPassthrough" — 401/403 on failure
- AuthOptions: Default CAC, AzureUSGovernment, idle timeout 30min, HMAC-SHA256 cookies

### Authorization / RBAC (ComplianceAuthorizationMiddleware.cs)
Roles: Compliance.Administrator, SecurityLead, Analyst, Auditor (read-only), PlatformEngineer, Viewer (default)
Tool RBAC: WriteTools HashSet + ApprovalTools HashSet in middleware

**CRITICAL BYPASS — auth skipped for:**
- /health (by design)
- /api/auth/* (role-agnostic by design)
- ASPNETCORE_ENVIRONMENT == "Development" — skips ALL auth
- Stdio mode — skips ALL auth

### Multi-Tenant Isolation
- ITenantContextAccessor (AsyncLocal-backed singleton) drives HasQueryFilter on all [TenantScoped] entities
- TenantStampingSaveChangesInterceptor: stamps TenantId at SaveChanges
- TenantScopedQueryGuardInterceptor: throws on HTTP-context EF queries with null accessor.Current
- TenantResolutionMiddleware: resolves and bridges tenant context to AsyncLocal

### Audit Logging (AuditLoggingMiddleware.cs)
- Every MCP request logged with correlation ID, tool name, PIM role, action context
- UserId redacted: first 8 chars + "***" (per FR-048)
- Persisted to AtoCopilotContext.AuditLogs
- **Retention discrepancy:** README = 7-year; code XML doc = 730-day (2-year) — unresolved

### Sensitive Data Protection (SensitiveDataDestructuringPolicy.cs)
Redacts (exact + partial match): ClientSecret, ConnectionString, AccessToken, RefreshToken, Password, ApiKey, Authorization, BearerToken, Token, Secret, Credential

---

## 4. Documented Security Incidents

### P1 — Cross-Tenant Data Leak (2026-05-29)
**Source:** SECURITY.md
**Root cause:** TenantResolutionMiddleware resolved ITenantContext but never called tenantAccessor.Push(ctx). AsyncLocal was empty, TenantFilterDisabled=true on every EF query — all tenant rows returned to any authenticated user.
**Why invisible:** Audit logs showed correct EffectiveTenantId; top endpoint computed its own filter masking the bug; existing tests bypassed middleware bridge.
**Fix:** using var _ = tenantAccessor.Push(ctx); await _next(httpContext); — push must wrap _next().
**Fixed:** PR #97 (0ff3242). Hardened: PR #100-followup.
**Defense added:** TenantScopedQueryGuardInterceptor + TenantScopedEndpointHttpPipelineTests.

---

## 5. NIST 800-53 / OSCAL Integration

Embedded at build time (no runtime remote fetch):
- NIST_SP-800-53_rev5_catalog.json — full Rev 5 OSCAL catalog
- nist-800-53-baselines.json — Low/Mod/High baselines
- fedramp-baselines.json, cnssi-1253-overlays.json, sp800-60-information-types.json
- cci-nist-mapping.json, plugin-family-mappings.json, oscal-schemas/
All at: src/Ato.Copilot.Agents/Compliance/Resources/

DB entity: AtoCopilotContext.NistControls (DbSet)

---

## 6. Persistence Models

Key TenantScoped entities:
- RegisteredSystem: root anchor for all 7 RMF phases (SystemType, MissionCriticality, AzureEnvironmentProfile)
- CacSession: TokenHash=SHA-256 only (raw JWT never stored), SessionStatus, ClientType
- JitRequestEntity: PIM JIT role activation lifecycle
- NarrativeVersion: immutable SSP narrative snapshots with versioning and review workflow
- ComplianceAssessment/Finding/Evidence/Document: full RMF evidence chain
- AuditLogEntry: compliance action trail
- RemediationBoard/Task/Comment: Kanban-style remediation tracking

---

## 7. Test Coverage

Reported total: 3,164 tests

Security-relevant test files confirmed:
- TenantResolutionMiddlewareAccessorBridgeTests.cs — P1 cross-tenant bug bridge
- CrossTenantFkRejectionTests.cs — FK-level tenant isolation
- TenantScopedQueryGuardGlobalReferenceTests.cs — query guard interceptor
- SimulationGateTests.cs — auth simulation mode gate
- LoginThrottleServiceTests.cs + LoginThrottleMiddlewareSignalTests.cs — rate limiting
- 34 tool test files covering entire MCP tool surface
- 15 auth test files, 15 tenancy security test files

---

## 8. Risk Assessment

### Critical
- C1 (HIGH): Auth completely bypassed in Development/Stdio — silent P1 risk if staging misconfigured
- C2 (CRITICAL — FIXED): P1 cross-tenant data leak pattern; fixed PR #97, hardened, test-covered
- C3 (HIGH): No SBOM anywhere in repo
- C4 (MEDIUM): No formal threat model (SECURITY.md covers one incident; no STRIDE/DREAD)

### Operational
- O1 (MEDIUM): Audit retention discrepancy (7-year vs 730-day) — must resolve before ATO submission
- O2 (MEDIUM): NIST catalog integrity — embedded at build, no runtime integrity check
- O3 (LOW): Tool RBAC HashSet-enforced in middleware, not attribute-based — manual sync required for new tools
- O4 (LOW): UserId partially exposed in logs (first 8 chars) — accepted per FR-048

---

## 9. Recommendations

### Immediate (Before Production Authorization)
1. Add startup guard: fail fast if ASPNETCORE_ENVIRONMENT=="Development" in cloud deployment
2. Resolve audit retention discrepancy — 7-year vs 730-day — pick one, test it
3. Generate SBOM via dotnet sbom-tool or syft in CI; publish SPDX/CycloneDX as release artifact
4. Produce STRIDE threat model covering MCP tool surface, EF query filters, audit write path, CAC session lifecycle

### Near-Term (90 Days)
5. Replace WriteTools/ApprovalTools HashSets with [RequiresRole] attribute for compile-time enforcement
6. Add CI build step: verify SHA-256 of embedded OSCAL catalog against pinned known-good hash
7. Expand SensitiveDataDestructuringPolicy with DoD-specific fields (ClearanceLevel, etc.)

---

## 10. Strategic Position

- No direct competitor covers all 7 RMF phases in a single AI-driven interface
- eMASS export integration is the correct DoD workflow strategy
- Multi-channel delivery (VS Code, Teams, Web, Stdio) maximizes reach across DoD tooling
- Azure Government default = correct positioning for IL4/IL5 workloads
- Embedded OSCAL catalog enables air-gapped operation — significant classified environment advantage

**Primary strategic risk:** Platform credibility depends entirely on catalog correctness. A stale or tampered NIST catalog produces authoritative-looking but wrong compliance guidance — a mission and reputational risk that outweighs the convenience of embedded resources.

---

*Audit prepared from live gh api reconnaissance. All file paths cited are exact and verified. No invented content.*

Contributor guide

Open the contributing guide

Research direction

The audit names BaseAgent.cs, ComplianceAgent.cs, AtoCopilotContext.cs, TenantResolutionMiddlewareAccessorBridgeTests.cs, and SimulationGateTests.cs; start by reading the relevant recommendation against those entry points and tests. Because no single change is specified, define one accepted recommendation and its validation before starting; done requires the chosen risk to be addressed with matching tests or documentation.

Written by the indexing model from the issue text.

Assessment

Tech stack
azure, csharp, docker, react, redis, sql, typescript
Domain
backend, cloud, databases, documentation, frontend, security
Issue type
Documentation
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.