Repository navigation
[Bug]: the presentation public-boundary scan certifies unlabeled OpenAI and Anthropic API keys as public-safe #7799
Description
Impact
The presentation public-boundary scan certifies unlabeled OpenAI and Anthropic API keys as public-safe. scan_public_boundary_text is the canonical gate for dash HTML/JSON serving, loopx dash generate --out, static-site publication, chat detail publication, and manager-channel result return. A key that passes this scan is served, written, or accepted under a positive public-safe certification; credential disclosure is irreversible until the key is rotated.
LoopX explicitly supports OPENAI_API_KEY and ANTHROPIC_API_KEY as first-class provider routes (loopx/chat_endpoint_catalog.py, loopx/chat_providers.py, and docs/guides/personal-workspace-trial-guide.md). These are the most likely API credentials in a LoopX operator environment and in provider error output, CI logs, or environment dumps. The shared provider-token owner recognizes GitHub, AWS, Slack, Google, Stripe, npm, PyPI, and JWT shapes, but no current OpenAI (sk-proj-, sk-svcacct-, sk-admin-) or Anthropic (sk-ant-...) shape. The neighboring SECRET_LIKE_SURFACE_PATTERN recognizes these values, which shows the drift is in the narrower provider-shape set consumed by the presentation boundary.
This continues the residual explicitly disclosed by merged #7732 (follow-up to #7727): its boundary matrix left sk-proj- as an unclaimed shape. It affects five shipped presentation paths and the default API-provider credentials for both major supported model providers.
Minimal reproduction
On upstream/main ec91c4dbbb9aecf0abd0395455fc52466506f2b2, with synthetic token shapes only:
from loopx.presentation.public_safety import scan_public_boundary_text
for token in (
"sk-proj-" + "A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0",
"sk-svcacct-" + "A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0",
"sk-admin-" + "A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0",
"sk-ant-api03-" + "A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0",
):
print(scan_public_boundary_text(f"CI log fragment: exported {token} to the runner"))Observed:
{'ok': True, 'warnings': []}
{'ok': True, 'warnings': []}
{'ok': True, 'warnings': []}
{'ok': True, 'warnings': []}
The same values are rejected by SECRET_LIKE_SURFACE_PATTERN, but that pattern is not the one consumed by PRESENTATION_PUBLIC_BOUNDARY_PATTERNS.
Expected behavior
Each unlabeled OpenAI and Anthropic API-key shape above should return {"ok": False, "warnings": ["provider token"]} at the presentation boundary, and each existing consumer should continue using its current fail-closed behavior (withhold the endpoint, refuse the output file, reject the static-site file, omit chat detail text, or reject the manager result).
Short prose such as sk-proj-abcdefghijklmnop should remain readable through the existing length floor; this report does not ask for a generic sk- substring match.
Actual behavior
All four synthetic values are certified public-safe and reach the five presentation consumers unchanged.
Why this is high importance
- Affected surface: five shipped publication/readback paths share this gate, including the dash server and static-site publisher.
- Who pays: any LoopX operator or agent whose tool output contains an
OPENAI_API_KEYorANTHROPIC_API_KEYvalue. Provider errors and CI environment dumps are ordinary carriers. - Severity: the control returns a positive safety receipt for a credential; downstream publication is irreversible without rotation.
- Scale: both primary API model providers supported by LoopX; every agent run whose text reaches the dash, export, chat detail, or manager-channel return is exposed to the same drift.
- Not an edge case: the missing prefixes are issuer-specific, standard key shapes, and the merged fix(presentation): reject unlabeled provider tokens at the public boundary #7732 test itself names
sk-proj-while currently asserting it is safe.
Root cause
PROVIDER_TOKEN_SHAPE_PATTERN_SOURCE in loopx/public_safe_text.py omits the OpenAI and Anthropic issuer prefixes. PRESENTATION_PUBLIC_BOUNDARY_PATTERNS composes that owner without a generic sk- arm, so the presentation gate cannot see these keys even though the broader credential classifier can.
Proposed fix
Extend the canonical provider-token alternation with the issuer-specific OpenAI and Anthropic families, and pin them at the presentation boundary. This reuses the existing shape owner rather than adding a second scanner or a broad generic sk- match.
Preflight
- I searched existing issues and pull requests for this behavior.
- The report and reproduction contain only synthetic token shapes, no credentials, private state, raw logs, or local paths.
- This is a public-safe boundary correctness report in the same class as [Bug]: the presentation public-boundary scan certifies unlabeled GitHub, AWS, Slack, Google, Stripe, npm, PyPI and JWT credentials as public-safe #7727 and its merged follow-up fix(presentation): reject unlabeled provider tokens at the public boundary #7732; no live credential or exploitable production state is included.
Activity