Skip to content

fix: consistent resource-ID validation for runtime, gateway, memory, and harness commands - #2604

Closed
jariy17 wants to merge 3 commits into
refactorfrom
bugbash/1hr-sweep
Closed

jariy17 wants to merge 3 commits into
refactorfrom
bugbash/1hr-sweep

Conversation

@jariy17

@jariy17 jariy17 commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

Draft — time-boxed bug-bash sweep. Fixes are small and tested, but this came out of a one-hour exploratory pass, not a planned change. Findings I didn't fix are listed at the bottom.

1. Reject ARNs passed as --id on runtime and gateway read commands

What: runtime get, runtime version get|list, runtime endpoint get|list, gateway get, and gateway target|rule|connector get|list now reject an ARN passed where an ID is expected, with must be a Runtime ID, not an ARN / must be a Gateway ID, not an ARN (exit 2).

Why: These commands took any non-empty string, so an ARN reached the service and came back as AccessDeniedException ... not authorized to perform: bedrock-agentcore:GetAgentRuntime — even for a fully privileged caller. That reads like an IAM problem, not a typo. runtime invoke|exec|logs|shell|traces and gateway invoke already rejected ARNs client-side; the read commands just didn't use the same schema.

How: Reuse the existing runtimeIdSchema / gatewayIdSchema. gateway policy generate is untouched — its flag explicitly accepts an ID or ARN.

2. Same fix for memory read commands

What/Why: memory get, memory session|actor list, memory event get|list, memory record get|list had the same misleading-AccessDenied behavior with an ARN. Added memoryIdSchema and used it across all seven.

3. Harness --id rejected valid full-length IDs

What: Every harness command capped --id at 48 characters. That's the harness name limit; the service's harnessId pattern is [a-zA-Z][a-zA-Z0-9_]{0,39}-[a-zA-Z0-9]{10}, so IDs can be up to 51 characters. IDs of 49–51 characters were rejected client-side, and passing an ARN failed with an opaque Too big: expected string to have <=48 characters.

How: One shared harnessIdSchema (max 51, explicit ARN rejection) across the 16 harness commands. Kept it loose rather than matching the exact service regex, so the CLI doesn't break if the suffix format changes.

Testing

  • bun test (4585 pass, 0 fail) — new cases in runtime.test.tsx, gateway.test.tsx, memory.test.tsx, harness/idSchema.test.ts
  • bun run typecheck, lint:check, format:check
  • Checked live against real resources: an ARN now fails client-side with the new message, and a real ID still returns the resource.

Findings not fixed here

  1. agentcore <group> <typo> --help exits 0 and shows the group's help rather than the "unknown subcommand" error the no---help path gives. Commander resolves --help during option parsing, before the router's typo check runs. Repro: agentcore runtime gett --help; echo $?.
  2. An invalid --region surfaces as a raw DNS error. agentcore --region not-a-region runtime list → getaddrinfo ENOTFOUND bedrock-agentcore-control.not-a-region.amazonaws.com. The supported-region check exists only in the deploy path (src/core/project/manager.tsx). Making it global needs a decision on per-service region availability.
  3. eval online-eval get / eval dataset get with an ARN give the same misleading AccessDenied. Left alone: this was previously triaged as expected service behavior; worth revisiting for consistency with the fixes above.
  4. --json is not honored on error paths for add/remove/status: stdout is empty and the error is plain text on stderr. deploy already uses renderJsonError. Repro: agentcore add memory --name Dup --json twice.
  5. Exit codes differ for the same class of user error: adding a duplicate resource exits 2, removing a missing resource exits 1.
  6. status --json on a project that hasn't been deployed errors (exit 1, "No deployment targets are configured") instead of listing local resources as not deployed.

jariy17 added 3 commits October 15, 2026 21:26
runtime get/version/endpoint and gateway get/target/rule/connector took any
string as the ID, so an ARN reached the service and came back as a misleading
AccessDeniedException. invoke/exec/logs already used runtimeIdSchema /
gatewayIdSchema to reject ARNs client-side; use them here too.
Same gap as runtime/gateway: a Memory ARN reached the service and surfaced as
a misleading AccessDeniedException. Reject it client-side.
…lear error

Every harness --id flag capped input at 48 characters, but 48 is the harness
name limit; the service's ID is a <=40-char name plus a 10-char suffix (51 max),
so valid IDs of 49-51 characters were rejected client-side. Passing an ARN also
failed with an opaque length error. Share one schema across harness commands.
@github-actions github-actions Bot added the size/m PR size: M label Oct 15, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added agentcore-harness-reviewing AgentCore Harness review in progress claude-security-reviewing Claude Code /security-review in progress labels Oct 15, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot removed claude-security-reviewing Claude Code /security-review in progress agentcore-harness-reviewing AgentCore Harness review in progress labels Oct 15, 2026

@agentcore-devx-automation agentcore-devx-automation Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

AgentCore Harness Review

Verdict: Looks good

Nicely scoped refactor. Consolidating the per-resource idSchema constants and giving ARN inputs a clear, resource-specific error message is a real UX win over the generic Invalid value for option '--id'.

A couple of small observations (none blocking):

  • src/handlers/harness/idSchema.ts chains .max(51) after .refine(...). This works in zod v4 (the test for the 51-char boundary confirms it), but there's no negative test for a 52-char input — worth adding alongside the existing cases if you want to lock the upper bound down.
  • runtimeIdSchema and gatewayIdSchema don't bake in .min(1), so some call sites still need to tack on .min(1) while others (e.g., runtime/invoke, gateway/invoke) rely on the schema's lack of a min. Not introduced by this PR, but folding .min(1) into the base schemas (matching harnessIdSchema / memoryIdSchema) would make the four schemas symmetric and remove the per-call-site .min(1) noise.
  • The new memory ARN-rejection test exercises memory session list / memory record list without their other required flags (--actor-id, etc.). It passes today because id is validated first, but that ordering is a bit implicit — passing the other required flags would make the test less fragile.

Nothing here needs to block merge.

@jariy17 jariy17 closed this Oct 15, 2026
@jariy17
jariy17 deleted the bugbash/1hr-sweep branch October 15, 2026 21:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/m PR size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant