azurenoops / azurenoops/spin_agent
Executive Strategic Audit - SPIN AGENT
- 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
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