fix(skills): accept dotted registry ids in GCPSkillRegistry - #7138
chelsealong wants to merge 2 commits into
Conversation
Google-published skills have registry resource ids like cloud.google.com-<name>, which are not SKILL.md frontmatter names and were never meant to be held to the frontmatter naming rule. get_skill rejected every such id outright, and search_skills silently dropped every matching catalog entry, making Google-published skills unreachable from ADK. Give registry ids their own safe-path-segment check (still rejecting traversal, slashes, and other unsafe characters) instead of routing them through Frontmatter's kebab/snake-case name validator, which is scoped to SKILL.md content. Fixes google#7136
codebee-aoki
left a comment
There was a problem hiding this comment.
Verified this branch against a real Agent Registry catalog (117 skills, location global) with #6824 applied so downloads succeed: traversal-style names are all still rejected, search_skills("networking") now returns the Google-published ids, and get_skill("cloud.google.com-google-cloud-networking-observability") downloads and parses fine. One problem, inline below. Everything else looks right to me.
|
|
||
| def _is_safe_registry_id(name: str) -> bool: | ||
| """True if `name` is safe to use as a single skill-registry path segment.""" | ||
| return len(name) <= 64 and bool(_SAFE_REGISTRY_ID_PATTERN.match(name)) |
There was a problem hiding this comment.
The 64-character cap rejects 7 of the 117 real ids in the catalog, e.g. cloud.google.com-google-cloud-solution-agentic-analytics-spark-knowledge-catalog (80 chars) and cloud.google.com-gke-ai-troubleshooting-handle-disruption-gpu-tpu (65 chars). That limit comes from the SKILL.md frontmatter rule, not from anything about URL-segment safety, so I'd drop it (or raise it well above 80, e.g. 256) and replace the "a" * 65 "unsafe" case in the tests with a test that a long real id is accepted.
The 64-char cap on GCPSkillRegistry's registry-id check rejected real Agent Registry catalog ids (e.g. an 80-char and a 65-char Google-published id), since that limit came from the SKILL.md frontmatter naming rule, not from anything about URL-segment safety. Raise the cap to 256 and cover the two real catalog ids as regression tests.
|
Raised the registry-id length cap from 64 to 256 chars and added the two real catalog ids you flagged (80 and 65 chars) as regression tests in |
|
Re-verified 314172e with #6824 on top against the real catalog: 117/117 ids now pass the registry-id check (was 110/117 at the 64-char cap), traversal-style names are still rejected, |
Please ensure you have read the contribution guide before creating a pull request.
Link to Issue or Description of Change
1. Link to an existing issue:
Problem:
Skills published by Google into Agent Registry have resource ids of the
form
cloud.google.com-<display-name>(alsodiscoveryengine.googleapis.com-<name>).GCPSkillRegistryrejects all ofthem:
get_skill(name="cloud.google.com-...")raisesValueError: Invalid skill name ...because the check added for fix(skills): skip invalid catalog hits in GCP skill search #6839 requires the name tomatch
models._SNAKE_OR_KEBAB_NAME_PATTERN, which does not allow dots.search_skills()feeds each catalog id intomodels.Frontmatter(name=...),whose own field validator applies the same strict kebab/snake-case rule,
so every Google-published hit is silently dropped with a "Skipping search
result" warning.
In a real catalog this rejects the large majority of skills — only
self-created, plain-kebab-case skills pass. That name-pattern check was
never meant to apply here in the first place: it is the SKILL.md
frontmatter naming rule (a content-format rule for the file inside the
skill archive), and a registry resource id is a different kind of string
that happens to reuse the same
Frontmatter.namefield for convenience.Solution:
_is_safe_registry_idhelper ingcp_skill_registry.pywith itsown pattern (
^[a-z0-9]+(?:[._-][a-z0-9]+)*$, length <= 64) that keepsthe original security intent (reject
./.., slashes, and anything elsethat isn't safe to interpolate as a single URL path segment) while
allowing dots.
get_skillnow validates the incoming name against this registry-id ruleinstead of the SKILL.md frontmatter name pattern.
search_skillsnow validates each catalog id the same way, andconstructs the returned
Frontmatterviamodel_construct(bypassingthe frontmatter name validator, which does not apply to registry ids)
while still running the real
descriptionvalidation so malformeddescriptions are still skipped and logged as before.
Neither change touches
models.Frontmatter's own naming rule, which stillapplies, unmodified, to names parsed from SKILL.md content.
Testing Plan
Unit Tests:
Added:
test_search_skills_accepts_dotted_registry_id— a dotted registry id(
cloud.google.com-agent-platform-eval-flywheel) is now returned bysearch_skillsinstead of being dropped.test_get_skill_builds_expected_url_for_valid_namewith the samedotted id to confirm
get_skillaccepts it and builds the expected URL.test_get_skill_rejects_unsafe_name_before_any_requestwith".","..", and a 65-character name to confirm the safe-path-segmentcheck still rejects bare traversal segments and enforces the length cap.
test_search_skills_skips_entry_failing_validation's first case(previously the dotted id, used as an example of a name that fails
validation) to
"..", since a dotted id is now valid.Verified the added tests fail without the fix (
git checkout HEAD~1 -- src/google/adk/integrations/skill_registry/gcp_skill_registry.py, keepingthe new tests) with the exact errors the issue describes:
Summary of passed pytest results (with the fix restored):
(One unrelated test,
test_eval_injects_session_input_state_into_instruction,is flaky under
-n autoparallel execution and reproduces identically onunmodified
main; deselected from the full run above for a clean signal.)Also ran
ruff check,pyink --check, andpylinton the changed files —clean (pylint's only remaining note is a pre-existing line-length warning on
an unrelated line this PR doesn't touch).
Manual End-to-End (E2E) Tests:
Not run — no live Agent Registry project was available in this
environment; verified via the unit tests above, which exercise the same
name-validation and Frontmatter-construction code paths the issue reports
as broken.
Checklist
Additional context
This PR was generated by an AI coding agent (Claude Code). The implementation
and tests were verified against the automated test suite as described above.