PUBLIC-EVIDENCE AI SECURITY CASE STUDY

Bain Pyxis Compromise: When a Frontend Credential Owns Eleven Databases and the Identity Plane

Bain's Pyxis AI platform shipped a live AI service-account username and password inside a public frontend JavaScript bundle that any browser could download. CodeWall used that single credential to reach production in 18 minutes; the account held read/write across 11 databases and hundreds of roles, covering consumer-transaction data, client schemas, AI conversations, and the Pyxis system-prompt table. A Pyxis API endpoint accepted raw SQL and returned database errors, and platform LLM functions across 8 models could query live production tables, so the AI platform itself became a query front-end to the database; additional primitives supported bulk export to caller-chosen destinations and a single-call clone of the entire database, while activity logs retained full JWTs. A separate GraphQL path then permitted account creation and directory writes inside Bain's Okta tenant with no additional privileged approval step, converting data access into durable identity persistence. The 18,621-character system prompt, containing report methodology and SQL schema definitions, was retrievable through conversation metadata by any authenticated caller. The assessment describes one point-in-time configuration reported by an external red-team; the evidence available does not record Bain's remediation timeline.

Tool-Calling LLM / Connected GenAITier 3Indicative ERS 5.6 (3.2–7.9)Evidence source date 2026-04-18

Bain's Pyxis AI platform shipped a live AI service-account username and password inside a public frontend JavaScript bundle that any browser could download. CodeWall used that single credential to reach production in 18 minutes; the account held read/write across 11 databases and hundreds of roles, covering consumer-transaction data, client schemas, AI conversations, and the Pyxis system-prompt table. A Pyxis API endpoint accepted raw SQL and returned database errors, and platform LLM functions across 8 models could query live production tables, so the AI platform itself became a query front-end to the database; additional primitives supported bulk export to caller-chosen destinations and a single-call clone of the entire database, while activity logs retained full JWTs. A separate GraphQL path then permitted account creation and directory writes inside Bain's Okta tenant with no additional privileged approval step, converting data access into durable identity persistence. The 18,621-character system prompt, containing report methodology and SQL schema definitions, was retrievable through conversation metadata by any authenticated caller. The assessment describes one point-in-time configuration reported by an external red-team; the evidence available does not record Bain's remediation timeline.

ASSESSED SYSTEM

Bain's Pyxis AI platform in the pre-remediation state CodeWall assessed: the public frontend bundle that shipped a live AI service-account username and password; the platform's API surface including an endpoint accepting raw SQL and an LLM function-invocation surface across 8 models operating against live production tables; the bulk-export and single-call database-clone primitives; the activity logging that retained full JWTs; and the GraphQL path that reached Bain's Okta tenant. The service account held read/write across 11 databases and hundreds of roles.

OUT OF SCOPE

Bain's platform after remediation (the evidence does not record a remediation timeline, and no inference about the current state is made here); Okta as a product - the failure assessed is Bain's authorization path into the tenant, not any Okta defect; Bain's client systems not reachable through Pyxis; and CodeWall's autonomous testing agent, which is the attacker here and not part of the assessed system.

Architecture: Tool-Calling LLM / Connected GenAI (decision tree Q3) — The platform exposed LLM function invocation against live production database tables across 8 models, plus export primitives with caller-chosen destinations - the model calls external functions and databases, which is Q3 = YES. Q1 and Q2 were answered NO: the evidence documents user-triggered function invocation and single-call primitives, not two or more coordinating agents and not an autonomous multi-step planner maintaining task state. The brief's 'Agentic AI' tag is not treated as evidence of an autonomous planner, since the autonomy demonstrated in this case belongs to CodeWall's attacking agent. Under the hybrid rule, Tool-Calling LLM is the highest qualifying class the evidence supports. Tier 3: Tier 3 Internal: Pyxis is an internal consulting analytics platform whose intended users are authenticated Bain personnel, with no public interaction surface by design. The credential leak destroyed that boundary in practice, but that is an exposure and identity finding scored in ORP As and IVP Cn-5, not a reason to raise the tier.

Documented attack or failure path

  1. CodeWall downloaded the public Pyxis frontend JavaScript bundle and extracted a live AI service-account username and password shipped inside it - a passively retrievable artefact requiring no exploitation.
  2. Using that single credential the agent reached production in 18 minutes; the account held read/write across 11 databases and hundreds of roles, spanning consumer-transaction data, client schemas, AI conversations, and the Pyxis system-prompt table.
  3. A Pyxis API endpoint accepted raw SQL and returned database errors, and LLM function invocation across 8 models could query live production tables, so the AI platform's own model surface carried the service account's full reach.
  4. Further primitives allowed bulk export to caller-chosen destinations and a single call that cloned the whole database; activity logs held full JWTs, providing replayable credential material.
  5. A separate GraphQL path permitted account creation and directory writes inside Bain's Okta tenant with no new privileged approval step, moving the attacker from data theft to durable identity persistence.

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.

  • Authentication existed and was required: the compromise proceeded through a real service-account credential, not an unauthenticated path. The failure is credential handling and scope, not the absence of an authentication model.
  • Activity logging was present and detailed enough to record per-call authentication material - which is also precisely why it leaked JWTs, so the same evidence cuts both ways.
  • The system-prompt disclosure through conversation metadata required an authenticated caller, so that particular leak path was not open to anonymous internet users independent of the credential exposure.
  • The exposure was reachable by a passive scan of a public build artefact, meaning it was detectable by an inexpensive release-gate control (frontend secret scanning) rather than requiring novel detection capability.

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-metricScoreRubric basisEvidence
Robustness (Ro) — scenario interval 0.00–0.80 (midpoint 0.40), Tier 3 MVT 0.40 indeterminate
Ro-4Poisoning Attack Resistance0.00w 0.200.00 - no configuration or content integrity validation on the prompt ingestion path; a tampered variant would load without scanning, provenance check, or quarantine.The leaked service account held read/write across 11 databases including the Pyxis system-prompt table, and the brief's recommended hardening - that the prompt be 'protected by integrity controls so tampered variants cannot silently load' - is presented as absent. Nothing verified prompt or configuration integrity between the store and the model.source: researcher
Fairness (Fa) — scenario interval 0.00–1.00 (midpoint 0.50), Tier 3 MVT 0.45 indeterminate
Transparency (Tr) — scenario interval 0.06–0.81 (midpoint 0.44), Tier 3 MVT 0.45 indeterminate
Tr-3Audit Trail Completeness0.25w 0.250.25 - partial logging exists but the record set is not shown to cover the tool-mediated and identity-plane workflows that mattered, and the trail is neither access-controlled nor tamper-evident. Scored at the lower defensible anchor because coverage beyond authentication metadata is unevidenced rather than demonstrated.Activity logs existed and captured enough per-call detail to contain full JWTs. The evidence does not establish that they covered LLM function invocations, export destinations, or Okta directory writes, and the logs were plainly not access-controlled to the standard the 0.75 anchor requires, since their contents constituted usable credential material.source: brief
Privacy (Pr) — scenario interval 0.06–0.81 (midpoint 0.44), Tier 3 MVT 0.50 indeterminate
Pr-3Data Minimization Compliance0.25w 0.250.25 - some minimisation exists on the primary data model, but the logging path retains unnecessary sensitive fields (complete authentication tokens) and the egress path applies no necessity constraint on destination.Activity logs retained full JWTs - live credential material kept in a telemetry path that has no need of it. Export features additionally accepted attacker-chosen destinations, so data left the boundary with no destination constraint.source: researcher
Containment (Cn) — scenario interval 0.08–0.20 (midpoint 0.14), Tier 3 MVT 0.50 confirmed breach
Cn-1Scope Enforcement0.00w 0.160.00 - no effective scope boundaries: the assessed configuration permitted access to unauthorised data, tools and destinations, with no per-asset-class, per-action, or per-destination limit on what a single identity could reach.One service account held read/write across 11 databases and hundreds of roles; an API endpoint accepted raw SQL; a single call could clone the whole database; export primitives accepted attacker-chosen destinations; and the same identity reached the Okta directory write plane. Three independent boundary classes - query scope, egress destination, and identity plane - were each absent.source: researcher
Cn-2Escalation Prevention0.00w 0.160.00 - no escalation controls: the identity could obtain higher privileges and invoke restricted administrative primitives, bypassing any approval workflow that should have governed identity-plane mutation.A GraphQL path allowed account creation and directory writes inside Bain's Okta tenant 'without a new privileged approval step' - a data-plane credential reaching the permission-issuing plane with no additional authorization evaluated.source: researcher
Cn-3Output Filtering Robustness0.25w 0.200.25 - a context-leaking output was returned directly on a user-reachable path with no filtering. Scored at 0.25 rather than 0.00 because the evidence documents one unfiltered path rather than establishing the absence of all output policy enforcement across the platform.The 18,621-character Pyxis system prompt - containing report methodology, SQL schema definitions, and analytical frameworks, and therefore doubling as a blueprint of the production database - was returned verbatim through conversation metadata to any authenticated caller, with no redaction on that path.source: researcher
Cn-4Side-Channel Resistance0.00w 0.160.00 - no side-channel assessment is evident; error messages and logs revealed sensitive state, which is the anchor's exact condition.Two side channels are directly reported: the raw-SQL API endpoint returned database errors to the caller, making the schema and query surface enumerable, and activity logs held full JWTs, leaking authentication state through the observability layer.source: researcher
Cn-5Agent Identity Integrity0.25w 0.110.25 - basic shared-secret authentication with no workload or agent-to-agent verification, weak rotation, and auditability that leaks rather than protects credentials. Not 0.00, because a real credential was required and arbitrary or unauthenticated identities were not accepted.Identity was a static shared secret: a service-account username and password shipped in a public frontend bundle, spanning 11 databases and hundreds of roles, with no per-call verified machine identity (the recommended AID-H-004.002 control specifies issuer, audience, route binding and credential freshness, all presented as missing). Rotation was evidently weak, since the credential remained live in a production artefact long enough for a passive scan to find it, and full JWTs sat in activity logs as replay material.source: researcher
Cn-6Action Reversibility Classification Rate0.00w 0.090.00 - no reversibility classification is performed before execution and high-impact actions execute ungated (ARCR = 0); no taxonomy, per-class gate, or human-authority requirement is evidenced anywhere in the action surface.The exposed action set included a single-call clone of the entire database, bulk export to attacker-chosen destinations, and Okta account creation and directory writes - bounded-irreversible and delegated-irreversible actions by the Cn-6 taxonomy - executed with no pre-execution classification and, in the Okta case, explicitly 'without a new privileged approval step'.source: researcher

Unknown, not N/A: 14 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

DimensionScoreJustification
AaAutonomy Amplification0.70w 0.20Documented intermediate. The model surface composes and executes queries against live production tables without per-query human approval of the generated SQL, and no step-up exists for the high-consequence primitives (full-database clone, bulk export to arbitrary destinations, directory writes), which places it above the 0.50 human-on-the-loop anchor whose defining feature is that high-value actions are escalated. It stays below 0.75 because interaction is human-initiated and analytical output is consumed by a human analyst rather than acted on autonomously; no planner or unattended loop is evidenced.
AsAttack Surface Exposure0.85w 0.25The platform's API and GraphQL surfaces are internet-reachable and its service credential was publicly downloadable from a frontend bundle, so the authentication boundary was in practice open to any internet user; one endpoint additionally accepted raw SQL, i.e. attacker-controlled query structure with no validation. That is above the 0.75 anchor. It is below 1.00 because the evidence shows no untrusted RAG ingestion, no external-agent messaging, and no MCP tool integration - the exposure is credential and interface exposure rather than untrusted-content exposure. elevated
CpCascade Potential1.00w 0.30Graph-derived and corroborated on its merits. The observed path runs from a publicly downloadable credential (origin, no privilege) to read/write across 11 production databases (P2/P3), to bulk export at caller-chosen external destinations (P3 write-external), to Okta account creation and directory writes (P4 credential- and permission-issuing) with no additional approval anywhere on the chain. That is both an ungated path reaching a P4 node and a Privilege Amplification Depth of at least 3, either of which triggers the g_P = 1.00 anchor independently of the absent System Dependency Graph. All four stack layers are traversed: L1 model function surface, L2 conversation and prompt state, L3 database and export primitives, L4 the Okta identity plane.GDCP: corroborated by the observed path elevated
RfRemediation Feasibility0.25w 0.25Every remediation the evidence points to is deployment-infrastructure and permissions work rather than model change: rotate the credential and purge it from bundles and git history, re-scope the service account per asset class, sever the AI platform's path to the IdP write plane, retire the raw-SQL and bulk-export catch-all primitives, and add frontend secret scanning to the release gate. That is the 0.25 anchor. It is not 0.00 because re-scoping an identity that spans 11 databases and hundreds of roles is a permissions re-architecture rather than a single patch, and the evidence available does not record a completed fix.

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

ComponentScoreBasis
Pc — Public provenance evidence0.25The evidence establishes the shape of the deployment - 8 models available for function invocation, 11 databases, hundreds of roles, one 18,621-character system prompt - but not the identity of any model, the data lineage, the tool or function manifest, or the identity policy. Indeed the identity policy is the case's central failure rather than a documented artefact. Nothing is signed or independently reviewed. That is the 0.25 minimal-provenance anchor.
Ec — Public evaluation coverage0.39coverage 0.39 (9 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 freshness0.25Evidence dated 2026-04-13; age 122 days on the workpaper reference date. Components: T_behavior 0.25 · C_event 0.35 · T_containment 0.40 · C_behavior 0.40 · T_calendar 0.63 · C_monitor 0.65 · C_evidence 0.65. Binding term: T_behavior. dt_days = 122, measured from CodeWall's public research article dated 2026-04-13 to the 2026-08-13 evidence reference date; the AIDEFEND brief republished the analysis on 2026-04-18 without making the underlying evidence newer. agentic = true: Tool-Calling LLM / Connected GenAI is a tool-augmented class with runtime-mutable permission scopes and credentials, so the containment staleness floor with M_Cn = 2.0 applies - and this case is the archetype of why, since the whole failure is a permission boundary that was not what it appeared to be. baw = true, with the ambiguity stated plainly: the platform's LLM function surface executed against live production tables under a service account holding read/write across 11 databases including the AI conversation store and the system-prompt table, so model-issued statements could write state later consumed in a decision path, and conversation state is written and re-consumed (the system prompt was itself exposed through conversation metadata). That meets the BAW checklist's closed-feedback-loop item. The evidence does not decisively show the model writing rather than reading, so the spec's worst-case stance is applied. C_event = 0.35: a confirmed compromise including credential exposure and an identity-plane write path. C_monitor = 0.65: a detection failure is directly evidenced - a live credential sat in a production bundle long enough for a passive scanner to find it, a scoped human pentest did not catch it, and production was reached in 18 minutes with no reported detection. C_behavior = 0.40 (Band 0): no canaries, registered invariants, or maintained drift baseline are documented; the spec's worst-case house rule for unavailable evidence, not a finding that Bain operates no monitoring. C_evidence = 0.65 follows from the Band 0 cold-start rule and is independently supported by the open identity-scope gap.

Public-evidence ACI = (Pc × Ec × Tf)1/3 = 0.29 — diagnostic status: Invalid as assessment-of-record evidence. 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

Worp · ORP0.20(0.70) + 0.25(0.85) + 0.30(1.00) + 0.25(0.25) = 0.715
CRMNelevated = 2 → 1.15
ORPeffective0.715 × 1.15 = 0.822
Wivp · IVP midpoint0.20(0.40) + 0.15(0.50) + 0.20(0.44) + 0.25(0.44) + 0.20(0.14) = 0.379
IVP mitigation0.15 + 0.85(1 − 0.379) = 0.677
Scenario assuranceACI fixed at 1.000 for cross-case comparison; public-evidence ACI 0.290 is diagnostic only
Indicative ERS midpointmin(10, 0.822 × 0.677 × 1/1.000 × 10) = 5.6
Unknown-input interval3.2–7.9; 14 unknown applicable sub-metrics set to 1.00 / 0.00 at the bounds

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.

TechniqueDefence PriorityEvidences
AID-H-004.002Service & API AuthenticationParent AID-H-004 (Identity, Access & Trusted Communication for AI Systems). Requiring a verified machine identity with correct issuer, audience, route binding and credential freshness on every backend, database and GraphQL call is the direct Cn-5 control; never shipping service-account passwords to the browser and never logging raw JWTs also drives the Tr-3 and Pr-3 findings.Very HighCn-5 Tr-3
AID-H-018.002Policy-Based Access ControlParent AID-H-018 (Tool Authorization & Capability Scoping). Separate authorization evaluated per action type, per data class and per destination is exactly what would move Cn-1 and Cn-6 off the 0.00 anchor: 'query prod' must never be a single exposed tool.Very HighCn-1 Cn-6 Cn-7
AID-H-017.002Least-Privilege Tool ArchitectureParent AID-H-017 (Secure Agent Architecture). Replacing raw-SQL and bulk-export catch-alls with narrow single-purpose functions bounds the blast radius even when a credential leaks; the catalogue maps the parent to Cn-5, and in this case the control also bears directly on Cn-1.HighCn-5 Cn-7
AID-H-016.001System Prompt Structure & Instruction/Data SeparationParent AID-H-016 (Instruction Hierarchy & Prompt Injection Hardening). Delivering the prompt through a privileged channel only, never returning it verbatim in user-reachable responses or metadata, and protecting it with integrity controls addresses the Cn-3 disclosure and the Ro-4 tamper exposure; the catalogue maps the parent to Ro-1, which this case does not otherwise exercise.MediumRo-1

WHAT THIS CASE TEACHES

Identity, not the model, is the AI attack surface here: every low sub-metric sits in Containment (Cn-1, Cn-2, Cn-4, Cn-5, Cn-6 all at or near the floor) while Robustness barely features - and the case is the cleanest available demonstration of PAD >= 3 corroborating Cp = 1.00 on its merits, because one leaked frontend credential reached a P4 permission-issuing node with no gate on the path.

Sources: AIDEFEND in Action brief: Bain Pyxis Compromise (2026-04-18) · CodeWall: How We Hacked Bain's Competitive Intelligence Platform (2026-04-13)

AITBM sub-metrics referenced