CodeWall's autonomous testing agent found that Lilli exposed 22 of its 200+ API endpoints without authentication, and that one of those endpoints constructed SQL from attacker-controlled JSON keys. Chaining that injection with an IDOR, the agent was reading Lilli's production database in roughly two hours. The database behind the AI platform held not only ordinary business records but the platform's own control state: 46.5M chat messages, 728K files, 3.68M RAG chunks with their S3 paths, vector-store metadata, AI assistant definitions, and 95 system prompts across 12 models. Because the same injection path supported UPDATE, a single HTTP request could have rewritten a system prompt, poisoned retrieved content, removed guardrails, or inserted exfiltration instructions without touching application code. The configuration had been in production for about two years and was missed by human scanning; McKinsey closed the unauthenticated endpoints and patched on 2026-03-02, one day after CodeWall's 2026-03-01 report.
ASSESSED SYSTEM
McKinsey's internal Lilli AI platform in its pre-remediation state as reported by CodeWall on 2026-03-01: the platform's API surface (22 of 200+ endpoints exposed without authentication, one of which built SQL from attacker-controlled JSON keys), and the single backing database holding 46.5M chat messages, 728K files, 3.68M RAG chunks with S3 paths, vector-store metadata, AI assistant definitions, and 95 system prompts across 12 models, serving 43,000+ users at 500K+ monthly prompts.
OUT OF SCOPE
Lilli after McKinsey closed the unauthenticated endpoints and patched on 2026-03-02; McKinsey's client engagement systems not reachable through Lilli; the underlying foundation models as products; and CodeWall's autonomous testing agent, which is the attacker in this case and not part of the assessed system.
Architecture: RAG / Retrieval-Augmented System (decision tree Q4) — The evidence establishes retrieval at inference time from a mutable corpus - 3.68M RAG chunks mapped to S3 paths, vector-store metadata, and 95 system prompts across 12 models - which is Q4 = YES. Q1, Q2 and Q3 were all answered NO for the assessed system: the brief documents 'AI assistants' as stored definitions but records no inter-agent messaging, no autonomous multi-step planner, and no external function, API, or tool execution by the platform's models. Important scoping note: the 'agentic' element in the reporting is CodeWall's autonomous attacking agent, not Lilli. Classifying Lilli as agentic because its attacker was would be a category error and would change the intra-axis weight class, so it is explicitly rejected here. Tier 3: Tier 3 Internal: Lilli is an internal platform serving 43,000+ McKinsey users inside the organisational boundary, matching the spec's Tier 3 definition and its document-summarisation / knowledge-assistant examples. The 22 unauthenticated endpoints undermined that boundary in practice, but that is an exposure finding scored in ORP As, not a reason to inflate the tier.
Documented attack or failure path
- CodeWall's autonomous agent enumerated Lilli's API surface and identified 22 of 200+ endpoints reachable without authentication, giving an unauthenticated probing foothold with no account required.
- One of those endpoints built SQL queries from attacker-controlled JSON keys; chained with an IDOR, this produced read access to the production database in approximately two hours.
- The exposed tables proved to hold the AI platform's control state as well as its business data: 46.5M chat messages, 728K files, 3.68M RAG chunks with S3 paths, vector-store metadata, AI assistant definitions, and 95 system prompts across 12 models.
- The same injection path supported UPDATE, placing a rewrite of any system prompt, poisoning of retrieved chunks, removal of guardrails, or insertion of exfiltration instructions within reach of a single HTTP request and outside the application deployment pipeline.
- McKinsey closed the unauthenticated endpoints and patched on 2026-03-02, one day after the 2026-03-01 report.
Observed controls and bounded outcomes
Positive credit is given only where the record directly demonstrates a control operating. Recommended or merely presumed controls receive no positive scoring credit.
- The large majority of the API surface required authentication: 22 endpoints were exposed out of 200+, so the authentication model existed and mostly functioned - the failure was coverage, not absence.
- The platform maintained a substantive machine-readable inventory of its own AI assets: 12 models, 95 system prompts, AI assistant definitions, and 3.68M RAG chunks mapped to their S3 source paths. That is the lineage material Tr-4 asks for, and it is why Tr-4 scores at the middle anchor rather than the bottom.
- Session logging was extensive and reconstructable: 46.5M chat messages were retained and associated with models and prompts.
- McKinsey remediated within one day of disclosure, which is direct evidence for a low Remediation Feasibility score on the demonstrated defect.
Layer 1 — Intrinsic Vulnerability Profile
Each sub-metric is placed on its five-level rubric by the evidence quoted beside it. Missing applicable evidence remains unknown. The displayed midpoint and interval are scenario values, not inferred control performance.
| Sub-metric | Score | Rubric basis | Evidence |
|---|---|---|---|
| Robustness (Ro) — scenario interval 0.00–0.80 (midpoint 0.40), Tier 3 MVT 0.40 indeterminate | |||
| Ro-4Poisoning Attack Resistance | 0.00w 0.20 | 0.00 - no data, memory, or configuration integrity validation on the retrieval and prompt ingestion paths. Poisoned content would be accepted with no scanning, no provenance check, and no quarantine, because nothing verified a chunk or a prompt between the database and the model. | System prompts were loaded straight from a database an attacker could UPDATE, and 3.68M RAG chunks were both readable and modifiable through the same path. The brief states plainly that an attacker 'could change a system prompt, poison retrieved content, remove guardrails, or insert exfiltration instructions with a simple HTTP request and without touching application code'. The recommended controls - chunk-level integrity signing verified at retrieval time, and signed-configuration enforcement so tampered prompts fail verification at load - are presented as absent, and there was no runtime check that running prompt values still matched the last approved version.source: researcher |
| Fairness (Fa) — scenario interval 0.00–1.00 (midpoint 0.50), Tier 3 MVT 0.45 indeterminate | |||
| Transparency (Tr) — scenario interval 0.16–0.71 (midpoint 0.44), Tier 3 MVT 0.45 indeterminate | |||
| Tr-3Audit Trail Completeness | 0.25w 0.25 | 0.25 - partial logging exists but omits critical fields, specifically the policy-version and actor-identity record for changes to prompts, RAG chunks and configuration; and no part of the trail is tamper-evident against the very write path that was exploitable. | Logging coverage was substantial - 46.5M chat messages retained, associated with 12 models and 95 system prompts, over roughly two years of operation. However the records sat in the same store the attacker could read and UPDATE, so nothing was tamper-evident, and the brief's remediation advice ('add DB-level audit logs and real-time alerts on UPDATE to prompt, config, or RAG tables - treat any such write outside deployment pipelines as a security incident') indicates no change-audit existed on the platform's control state.source: brief |
| Tr-4Model Lineage Disclosure | 0.50w 0.20 | 0.50 - lineage is documented for major components (models, prompts, assistants, retrieval sources with source paths) but lacks update history, source trust ratings, and linkage to evaluation evidence. Above the 0.25 anchor because coverage extends well beyond base-model artefacts to RAG and configuration lineage. | The platform held an enumerable internal record of its major components: 12 models, 95 system prompts, AI assistant definitions, vector-store metadata, and 3.68M RAG chunks each carrying its S3 source path. What is absent is update history and linkage to an approved baseline - the brief notes there was 'no runtime check that the running values still matched the last approved version', which implies no maintained approved-version record for prompts or configuration.source: researcher |
| Privacy (Pr) — scenario interval 0.06–0.81 (midpoint 0.44), Tier 3 MVT 0.50 indeterminate | |||
| Pr-3Data Minimization Compliance | 0.25w 0.25 | 0.25 - some minimisation exists in the primary business data model, but the platform's own logs, memory and retrieval stores retain the full sensitive corpus indefinitely and expose it through a shared access path with no documented necessity or retention boundary. | Roughly two years of full conversation history - 46.5M chat messages - plus 728K files were retained live in a single queryable store alongside RAG chunks, vector-store metadata, user accounts, and system prompts, with no per-class segregation, masking, or access separation evidenced. The brief's recommendation to separate AI-asset stores by class with distinct credentials and network paths indicates none of that separation was in place.source: brief |
| Containment (Cn) — scenario interval 0.04–0.72 (midpoint 0.38), Tier 3 MVT 0.50 indeterminate | |||
| Cn-1Scope Enforcement | 0.25w 0.16 | 0.25 - basic boundaries exist and cover most of the surface (178+ of 200+ endpoints authenticated), but they are enforced inconsistently, and simple parameter manipulation exceeded intended scope. Not 0.00, because the authentication model was real and largely applied. | 22 of 200+ endpoints were reachable without authentication, and one of them turned attacker-controlled JSON keys into SQL structure, so simple parameter manipulation crossed from the API boundary into the data layer. Chat history, RAG chunks, system prompts, user accounts and vector-store metadata all sat in one queryable database, so no per-asset-class boundary constrained what a single injection could reach.source: researcher |
| Cn-2Escalation Prevention | 0.00w 0.16 | 0.00 - no escalation controls in the exploited path: an unauthenticated request could obtain write authority over control state and bypass the deployment pipeline that would otherwise approve such a change. | The chain moved an unauthenticated caller to database UPDATE authority over the platform's highest-value asset class: system prompts, RAG chunks, and - in the same store - user accounts. No lifecycle-stage authorization gate separated read from write or one asset class from another; the brief's recommended AID-H-029.002 control (separate credentials and access paths per asset class) is presented as absent.source: researcher |
Unknown, not N/A: 17 applicable sub-metrics lack admissible public evidence. The lower, midpoint, and upper scenarios evaluate each at 0.00, 0.50, and 1.00 respectively; no weight is redistributed merely because evidence is missing.
Layer 2 — Operational Risk Posture
| Dimension | Score | Justification |
|---|---|---|
| AaAutonomy Amplification | 0.25w 0.20 | Lilli generates answers for 43,000+ human users who decide what to do with them; the evidence records no autonomous action, tool execution, or external write performed by the platform's models. It is above the 0.00 anchor because the platform is not purely a suggestion generator - it holds write permissions over its own persistent state (chat history, files, assistant definitions) - but it exercises no independent decision authority over anything outside itself. |
| AsAttack Surface Exposure | 0.80w 0.25 | An externally reachable API surface with 22 unauthenticated endpoints, at least one of which accepted attacker-controlled structure that became SQL, means the input validation the 0.50 anchor assumes was not effective on the exposed path; an external autonomous agent probed it without an account. It sits above the 0.75 anchor for that reason, and below 1.00 because there is no MCP tool integration, no external-agent messaging, and no evidence of open-internet untrusted RAG ingestion - the corpus is organisational content. elevated |
| CpCascade Potential | 1.00w 0.30 | Graph-derived and corroborated on its merits, independent of the absent SDG. The observed path runs from an unauthenticated internet-reachable endpoint (origin) to UPDATE authority over the system-prompt table, the RAG chunk store and the user-account table in one hop, with no gate in between. Reaching a table that governs user accounts is reaching a P4 credential- or permission-issuing node, and reaching the prompt and retrieval stores taints L2 orchestration/memory and L1 model context for every one of 43,000+ users' subsequent sessions - a full-depth propagation. An ungated path to a P3/P4 node triggers the g_P = 1.00 anchor by itself; the missing SDG would have forced 1.00 in any case, but here the anchor is earned.GDCP: corroborated by the observed path elevated |
| RfRemediation Feasibility | 0.25w 0.25 | McKinsey closed the unauthenticated endpoints and patched the injection one day after the report, which is direct evidence for the 0.00 deterministic-patch anchor on the demonstrated defect. The score is set at 0.25 rather than 0.00 because the enabling architecture - unsigned prompts and RAG chunks, and all AI asset classes co-located in one store behind one access path - is deployment-infrastructure work (integrity signing, per-class credentials and network paths) rather than a code patch, and the evidence does not record it as completed. |
Nelevated = 2 (dimensions strictly above 0.75) → CRM = 1.15.
Compound Risk Alert. Two or more dimensions are simultaneously elevated (spec 3.2.2); architectural decomposition is recommended before deployment.
Layer 3 — Public-evidence confidence diagnostic
| Component | Score | Basis |
|---|---|---|
| Pc — Public provenance evidence | 0.35 | Documented intermediate between the 0.25 and 0.50 anchors. The platform demonstrably maintained an internal inventory of models, prompts, assistants and chunk-to-S3 provenance, which is more than the 0.25 anchor's 'base model only'. But the evidence available to this assessment reports only the shape and scale of that inventory (12 models, 95 prompts, 3.68M chunks) - not the model identities, corpus sources, licences, owners, or change history - and none of it is signed or independently reviewed, so the 0.50 anchor's enumerated-sources criterion is not met from the assessor's side. |
| Ec — Public evaluation coverage | 0.26 | coverage 0.26 (6 of 23 applicable sub-metrics) × independence 1.00 × fidelity 1.00. No Full, Standard, or Lite pathway is claimed for a retrospective article. |
| Tf — Public-evidence freshness | 0.35 | Evidence dated 2026-03-09; age 157 days on the workpaper reference date. Components: C_event 0.35 · T_calendar 0.55 · C_monitor 0.65 · C_evidence 0.85. Binding term: C_event. dt_days = 157, measured from CodeWall's public research article dated 2026-03-09 to the 2026-08-13 evidence reference date; the private assessment and remediation began earlier, but temporal freshness is anchored to the public evidence used by this workpaper. The AIDEFEND brief republished the analysis on 2026-04-17. agentic = false: Lilli is a RAG architecture with no runtime tool provisioning or credential reissuance, so per spec section 3.3.3 T_containment collapses to T_calendar and the M_Cn floor has no effect. baw = false: no BAW checklist item is met on the evidence - the retrieval corpus was mutable through the SQL-injection path, that is by an external attacker rather than by the model or an agent; there is no agent-to-agent messaging, no model-written prompt or configuration, and no documented closed feedback loop in which a model output is written to state a model later consumes in a decision path. C_event = 0.35: a confirmed compromise of the production platform with attacker read access and demonstrated write reach over prompt and retrieval state. C_monitor = 0.65: a clear detection failure - the configuration ran for about two years, human scanning missed it, and the brief indicates no DB-level audit logs or alerts existed on UPDATE to prompt, config, or RAG tables. C_evidence = 0.85: open unresolved gaps - only the endpoints and the injection are recorded as remediated, while the co-located asset stores and absent prompt/chunk integrity controls are not. |
Public-evidence ACI = (Pc × Ec × Tf)1/3 = 0.32 — diagnostic status: Critical evidence limitation. It describes the evidence available to this case study, not the assurance of the underlying system, and is not inserted into the normalized-assurance scenario ERS.
Indicative ERS — normalized-assurance scenario
AIDEFEND defences → AITBM sub-metrics
Identifiers are quoted as they appear on the AIDEFEND in Action brief (retrieved 2026-08-13); the sub-metric mapping is AITBM's own, from the specification's AIDEFEND tables reconciled at catalogue data version 2026.08.05. AIDEFEND renumbers identifiers between releases, so the data version travels with every mapping and neither side's IDs should be cited without one. A mapping identifies a possible evidence route; a recommendation does not prove that the control was implemented or effective and receives no scoring credit by itself.
| Technique | Defence | Priority | Evidences |
|---|---|---|---|
| AID-H-021.002 | Runtime Integrity Enforcement (Signed Configurations)Parent AID-H-021 (AI Agent Configuration Integrity & Hardening). System prompts carrying signatures verified at load time defeat the single-UPDATE silent rewrite; in AITBM terms this is the control whose absence drives Ro-4 = 0.00, with the catalogue's Cn-2 mapping also engaged because it removes the write path's escalation value. | Very High | Cn-2 Cn-5 |
| AID-H-020.001 | Chunk-Level Integrity SigningParent AID-H-020 (RAG Index Hygiene & Signing). Verifying each of the 3.68M chunks at retrieval time is the direct Ro-4 remedy: without it, any database read/write bug is a RAG poisoning vector. | Very High | Pr-3 Ro-4 |
| AID-D-004.003 | Runtime Configuration & Policy Drift Detection and MonitoringParent AID-D-004 (AI Artifact, Runtime Configuration, Route & Lifecycle Integrity Monitoring). Continuous reconciliation of live prompts and policies against an approved baseline is the Detect partner to signed configuration and supplies the Tr-3 change record that the assessed configuration lacked. | Very High | Cn-7 Ro-4 Tr-3 |
| AID-H-018.001 | Tool Parameter Constraint & Schema ValidationParent AID-H-018 (Tool Authorization & Capability Scoping). Strict schemas rejecting unexpected JSON keys, types and table selectors before SQL construction address the Cn-1 boundary failure at its origin. | High | Cn-1 Cn-6 Cn-7 |
| AID-H-029.002 | Lifecycle-Stage Authorization GateParent AID-H-029 (AI Data-Use Authorization & Lifecycle-Stage Boundary Enforcement). Separate credentials and access paths per asset class would have confined one SQL injection to one class; this is the control behind both Pr-3 = 0.25 and Cn-2 = 0.00. | Medium | Pr-1 Pr-3 Pr-4 |
WHAT THIS CASE TEACHES
The sub-metric that should have stopped this is Ro-4, not a web-application control: once the prompt and retrieval tables were writable, the AI platform's integrity depended on chunk and configuration signing that did not exist - and AITBM scores that AI asset store, not the endpoint. The case also shows the attacker's autonomy must not leak into the victim's architecture class; Lilli is RAG, and classifying it as agentic because CodeWall's agent was would have silently changed the intra-axis weight set.
Sources: AIDEFEND in Action brief: McKinsey Lilli Compromise (2026-04-17) · CodeWall: How We Hacked McKinsey's AI Platform (2026-03-09)