fix(admin): adagents.json builder v3 validation + UX polish#4423
Merged
bokelley merged 2 commits intoMay 12, 2026
Conversation
Six validation and UX fixes from expert review of #4415. Closes silent data loss on enc key rows and signing key JSON errors, adds import-time validation pass, escapes innerHTML in renderAgents, and adds v3 field test coverage in adagents-manager.test.ts. https://claude.ai/code/session_01RunY4jCVuW6pABsJZsBiXk
Post-expert-review findings on PR #4423: - renderProperties/renderSignals/renderTags/renderSignalTags interpolated state into innerHTML template strings unescaped. Same class as the bug PR #4415 fixed in renderAgents — security reviewer pointed out the four siblings also need escapeHtml, and the new importFile validation pass routes attacker-controlled state straight into them. Wrapped every state interpolation in escapeHtml; rewrote bulk-tag-select dropdown via createElement + textContent + .value (option value attribute is the most dangerous sink for tag names). - renderSigningKeysList: added textarea.maxLength = 16384 to back the "signing-key size cap" claim from the PR description (the in-PR JSON parse feedback shipped, but the size cap was missing). E2E (Playwright + Docker, all 5 pass): golden path, country-code reject, X25519 reject, encryption/signing key XSS regression, and new property/signal/tag/signal-tag XSS regression seeding malicious state and asserting no dialog fires + no injected <img> nodes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
Author
|
Post-expert-review fix-up landed in b069363:
E2E (Playwright + Docker, 5/5 pass): golden path + country-code reject + X25519 CI fully green this round including |
This was referenced May 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #4421
Six validation and UX fixes from expert review of PR #4415 (v2→v3 builder upgrade). All items were non-blocking at merge time; this PR cleans them up.
Changes
Item 1 —
importFilevalidation bypass +renderAgentsself-XSSimportFile()now callsnormalizeImportedData()before loading state: uppercases and deduplicates country codes, warns about malformedencryption_keys.xvalues, lowercasescontact.domain. Returns a summary alert listing any coerced entries (warn-and-import, not hard-reject).authoritative_locationwith noauthorized_agents) now refuse to load with a helpful message pointing to the actual file URL.authorized_agentsorauthoritative_locationmust be present).renderAgents()template literal: wrappedagent.url,agent.authorized_for,agent.delegation_type,tagNames,propNamesin the existingescapeHtml()helper to close a self-XSS vector in imported file rendering.Item 2 — Countries: dedupe + empty-token tolerance (
saveAgent()).filter(Boolean)to remove empty tokens from trailing/double commas — previously aborted save with confusing "invalid code" error.[...new Set(...)]deduplication — schemauniqueItems: truewould reject duplicates on strict validators.Item 3 — Half-filled encryption key rows silently dropped (
saveAgent())filter(k => k.kid && k.x), now checks for rows with one field filled but not the other and alerts with 1-based row index.Item 4 — Signing keys: silent JSON parse failure (
saveAgent())[data-sig-index]textareas directly; alerts with 1-based row indices for any rows containing invalid JSON beforegetSigningKeysFromForm()silently drops them.Item 5 —
contact.domainlowercase normalization (getContactFromForm()).toLowerCase()applied on save. Schema pattern requires lowercase host syntax.Item 6 — Test coverage for v3 fields (
adagents-manager.test.ts)createAdAgentsJson: new round-trip test forexclusive,countries,effective_from/until,signing_keys.validateProposed: 4 new tests — valid v3 fields accepted, invalid country codes rejected,effective_until < effective_fromrejected, malformedsigning_keys(missingkid) rejected.Non-breaking justification
All changes are in a client-side admin HTML tool (
server/public/) and a server unit test file. No protocol schemas, no API contracts, no published spec surfaces touched. The worst failure mode is an additional alert box.Pre-PR review
renderAgentsescaping correct; countries dedup logic correct; signing-key parse-check logic correct; testas anycasts appropriate.normalizeImportedDatamutation on fresh parse result is safe.Session: https://claude.ai/code/session_01RunY4jCVuW6pABsJZsBiXk
Generated by Claude Code