{"schema":"threatline.record/2","record":{"id":"GHSA-8hc4-6xx6-3rh3","aliases":["GHSA-8hc4-6xx6-3rh3"],"summary":"Path Traversal in FileArtifactService allows unauthenticated arbitrary file read/write via crafted userId/sessionId","details":"### Impact\n\n`FileArtifactService` built filesystem paths from the `userId` and `sessionId` values using `path.join()` without validation or a containment check. When an application uses `FileArtifactService` (for example through a `file://` artifact service URI) and exposes the ADK API server, a remote unauthenticated client can supply path traversal sequences (raw `../` or percent-encoded `..%2F`) in the `userId` or `sessionId` route parameters and make the service resolve artifact paths outside the intended storage root (`users/<userId>/sessions/<sessionId>/artifacts`).\n\nExample request:\n\n```\nGET /apps/{app}/users/alice/sessions/..%2F..%2F..%2F..%2Fsome%2Fdir/artifacts/{name}\n```\n\n- **Confidentiality:** artifacts stored under directories outside the storage root, including other users' or sessions' artifacts, can be read if they follow the artifact directory layout (`<name>/versions/<n>/...`) and are readable by the Node.js process.\n- **Integrity:** when an agent tool saves artifacts (`saveArtifact`), an attacker who controls the `userId` or `sessionId` of a run can cause artifact files to be written outside the storage root.\n\nApplications that use the default in-memory artifact service are not affected.\n\n### Patches\n\nFixed in `@google/adk` **0.6.0** (google/adk-js#210). The fix adds an allow-list check for `userId` and `sessionId` (alphanumerics, `_`, `-`, `.`, `@`; no path separators, percent-encoding, null bytes or leading `.`) and a post-resolution check that the resulting path stays inside the storage root. Versions `< 0.6.0` are affected. Upgrade to 0.6.0 or later.\n\n### Workarounds\n\nIf upgrading is not possible:\n\n- Do not use `FileArtifactService`; use another artifact service.\n- Do not expose the ADK API server to untrusted clients; put it behind authentication.\n- Validate `userId` and `sessionId` at a proxy or middleware layer, rejecting anything outside `^[A-Za-z0-9_@-][A-Za-z0-9_.@-]{0,255}$`.\n- Run the Node.js process with a least-privilege account and a filesystem limited to the artifact directory.\n\n### Reported by\n\nGouri Sankar A ([@g0w6y](https://github.com/g0w6y))\n","categories":["Unclassified"],"product":"@google/adk","vendor":"","ecosystem":null,"affected_ranges":[{"source":"GitHub Advisory Database","source_url":"https://github.com/google/adk-js/security/advisories/GHSA-8hc4-6xx6-3rh3","source_modified_at":"2026-09-30T01:54:47Z","fetched_at":"2026-10-26T23:45:56.352924Z","package":{"ecosystem":"npm","name":"@google/adk"},"range":"< 0.6.0"}],"fixed_versions":[{"source":"GitHub Advisory Database","source_url":"https://github.com/google/adk-js/security/advisories/GHSA-8hc4-6xx6-3rh3","source_modified_at":"2026-09-30T01:54:47Z","fetched_at":"2026-10-26T23:45:56.352924Z","package":{"ecosystem":"npm","name":"@google/adk"},"version":"0.6.0"}],"cvss":9.8,"severity":"Critical","kev":{"listed":false},"epss":{"probability":null,"percentile":null,"score_date":null},"published_at":"2026-09-29T17:18:59Z","modified_at":"2026-09-30T01:54:47Z","provenance":[{"source":"GitHub Advisory Database","url":"https://github.com/google/adk-js/security/advisories/GHSA-8hc4-6xx6-3rh3","fetched_at":"2026-10-26T23:45:56.352924Z","source_modified_at":"2026-09-30T01:54:47Z"}],"sources":["GitHub Advisory Database"],"references":[],"locations":[],"motoko_assessment":{"status":"requires_architecture_review","automatic_remediation":false},"classification":{"method":"product-first software-layer rules","rules_version":"2.1","matched_on":null,"confidence":"unknown","reviewed":false},"change_timestamp":"2026-09-30T01:54:47Z","content_hash":"178631337e020c64b4b1e916fcd4c43687f2e5a9f36f713283efcceb3fcbfd18"}}
