fix(skills): prevent path traversal in LocalSkillSource via normalize + boundary check#1311
Conversation
f0a8a8c to
30ba017
Compare
|
Hi @herdiyana256, thank you for your contribution! We appreciate you taking the time to submit this pull request. Could you please include the corresponding unit tests to verify your changes and i noticed some inconsistencies in the code formatting. Could you please take a look and address those issues? |
|
Thanks for the review! I've added unit tests to
Could you point out which formatting inconsistencies you noticed? Happy to address them. |
|
Thank you for the quick response @herdiyana256. Could you please review the PR contribution Policy and ensure the code formatting and ensure your PR having single commit? |
… + boundary check
LoadSkillResourceTool validates resourcePath with a string prefix check
(startsWith("references/"), startsWith("assets/"), etc.), but this check
is trivially bypassed: "references/../../../../etc/passwd" passes it while
the OS resolves the .. components at Files.exists() time.
Fix in LocalSkillSource.findResourcePath() and listResources():
- Call .normalize() on the resolved path
- Assert file.startsWith(base) — reject if the resolved path escapes the
skill directory
Added unit tests covering both findResourcePath() and listResources():
- testLoadResource_pathTraversalBlocked
- testLoadResource_pathTraversalWithDoubleDotOnly
- testLoadResource_legitimatePathNotBlocked
- testListResources_pathTraversalInResourceDirectoryBlocked
- testListResources_dotDotResourceDirectoryBlocked
Fixes: CWE-22 (Improper Limitation of a Pathname to a Restricted Directory)
ae8146b to
52bbada
Compare
|
hii @hemasekhar-p Done! Squashed into a single commit (52bbada) and verified formatting with fmt-maven-plugin 0 files reformatted. Ready for re-review. |
Summary
LoadSkillResourceToolvalidatesresourcePathwith a string prefix check(
startsWith("references/"),startsWith("assets/"),startsWith("scripts/")),but this check is trivially bypassed:
"references/../../../../etc/passwd".startsWith("references/") == true // bypassed!
LocalSkillSource.findResourcePath()then resolves the raw path againstskillsBasePathwithout callingPath.normalize()or asserting a boundary,so the OS resolves
..components atFiles.exists()time — resulting inarbitrary file reads outside
skillsBasePath.The same issue exists in
listResources()for theresourceDirectoryparameter.Fix
In
LocalSkillSource.findResourcePath()andlistResources():.normalize()on the resolved pathfile.startsWith(base)— reject if the resolved path escapes the skill directoryThe correct enforcement point is the filesystem layer after resolution,
not a string prefix check on raw user input.
Files Changed
core/src/main/java/com/google/adk/skills/LocalSkillSource.javafindResourcePath(): normalize + boundary checklistResources(): normalize + boundary check onresourceDirectoryTesting