Skip to content

feat(agents): built-in presets + preset linter#34

Merged
anfibiacreativa merged 6 commits into
mainfrom
feat/builtin-agent-presets
May 27, 2026
Merged

feat(agents): built-in presets + preset linter#34
anfibiacreativa merged 6 commits into
mainfrom
feat/builtin-agent-presets

Conversation

@anfibiacreativa
Copy link
Copy Markdown
Member

Summary

  • Ship system-level agent personas as code (no per-site content-bus setup needed)
  • Add skills-engineer as the first built-in persona for the Skills Lab chat
  • Validate all agent presets at write time and load time against injection patterns and structural rules
  • Guard agentId path parameter against traversal attacks

Why

  • Agent presets previously required manual upload to each site's content bus — fragile for system-level personas
  • Content-bus presets are user-editable and could contain prompt injection payloads
  • The agentId field comes from the client and was used directly in file path construction

What Changed

  • src/agents/builtin-presets.ts (NEW): built-in presets map with skills-engineer; getBuiltinPreset() export
  • src/agents/preset-linter.ts (NEW): structural rules (max lengths, URL allowlist, MCP server validation) + injection pattern detection (role override, instruction override, exfiltration, prompt leaking, encoding evasion)
  • src/agents/loader.ts: SAFE_AGENT_ID regex guards path construction; parsePreset() runs linter on load (rejects errors); saveAgentPreset() runs linter before write; fallback to built-in after site → org lookups
  • src/skill-resolver.ts: resolves built-in presets even without authenticated admin client
  • test/agents/preset-linter.test.ts (NEW): 29 tests covering clean presets, each injection pattern, structural limits, warning/error distinction, false-positive resilience
  • test/agents/loader.test.ts: updated fixture to use valid MCP server URLs

Security Analysis

  • Path traversal: agentId validated with /^[a-z0-9][a-z0-9-]{0,62}$/ before file access
  • Preset poisoning: linter blocks known injection patterns (role override, exfiltration, prompt leaking) at both save and load time
  • Structural limits: systemPrompt max 4000 chars, disallowed external URLs, MCP servers restricted to known domains
  • Encoding evasion: base64 blobs and hex sequences detected

Resolution Order (presets)

  1. Site-level .da/agents/{id}.json (per-site override)
  2. Org-level .da/agents/{id}.json (org-wide override)
  3. Built-in (hardcoded, ships with code)

Test Plan

  • Send agentId: "skills-engineer" without content-bus file — verify persona applied
  • Upload site-level override — verify it takes precedence
  • Send agentId: "../../etc/passwd" — verify rejected (regex guard)
  • Save preset with "ignore all previous instructions" in systemPrompt — verify rejected by linter
  • Save preset with disallowed URL — verify rejected
  • Save clean preset — verify success
  • Full test suite passes (237 tests)

anfibiacreativa and others added 4 commits May 20, 2026 13:29
The Invalid JSON (400) and Invalid request body (400) early-return paths
in handleChat were missing CORS_HEADERS. A Zod validation failure (e.g.
missing path in pageContext) would return a 400 without
Access-Control-Allow-Origin, causing the browser to block the response
and surface a misleading CORS error.

Also relax PageContextSchema.path to optional (defaults to '') so a
missing path never triggers a validation failure.

Supersedes #24 which became unmergeable after the modularization in #28.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Introduce a builtin-presets module so system-level agent personas
ship with da-agent code. Fallback order: site → org → built-in.
No per-site content-bus upload required for built-in agents.

Co-authored-by: Cursor <cursoragent@cursor.com>
…ral violations

Introduces preset-linter.ts that validates agent presets at both
write time (saveAgentPreset) and load time (parsePreset). Checks for
injection patterns (role override, instruction override, exfiltration,
prompt leaking, encoding evasion) and structural limits (max lengths,
disallowed URLs, unsafe MCP server endpoints). Errors block; warnings
are logged but allowed.

Co-authored-by: Cursor <cursoragent@cursor.com>
@anfibiacreativa anfibiacreativa requested a review from mhaack May 22, 2026 13:08
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this, should we have the "Content Author" as a preset as well to keep the same pattern for both identies? And look up the right one in server.ts using the agentId?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea, but it touches prompt-builder.ts and server.ts pretty deeply. we should do that as a follow-up so this PR stays focused on the new infra. I'll open an issue for it.

Comment thread src/agents/preset-linter.ts Outdated
Remove hlx.live and hlx.page from ALLOWED_URL_DOMAINS and SAFE_MCP_URL
regex. These Helix-era domains are deprecated in favor of aem.live/aem.page.

Co-authored-by: Cursor <cursoragent@cursor.com>
@anfibiacreativa anfibiacreativa requested a review from mhaack May 26, 2026 14:03
Comment thread src/agents/preset-linter.ts Outdated
const URL_PATTERN = /https?:\/\/[^\s"'<>]+/gi;

const ALLOWED_URL_DOMAINS = [
'aem.live',
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mhaack do you think this is enough? too much?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should remove adobeaem.workers.dev as well. Not sure when this would be used at all.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, Claude came up with these and I wasn't sure if some were legit

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea, but it touches prompt-builder.ts and server.ts pretty deeply. we should do that as a follow-up so this PR stays focused on the new infra. I'll open an issue for it.

Co-authored-by: Cursor <cursoragent@cursor.com>
@anfibiacreativa anfibiacreativa merged commit 1dd2f01 into main May 27, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants