{"record":{"id":"ca2ef73b8491abec","repo":"alibaba/nacos","slug":"server-error-ca2ef7","errorCode":"SERVER_ERROR","errorMessage":"Downloaded ZIP contains unsafe entry paths: %s","messagePattern":"Downloaded ZIP contains unsafe entry paths: (.+?)","errorType":"exception","errorClass":"NacosException","httpStatus":null,"severity":"error","filePath":"client/src/main/java/com/alibaba/nacos/client/ai/remote/AiHttpClientProxy.java","lineNumber":314,"sourceCode":"        params.put(\"namespaceId\", namespaceId);\n        params.put(\"name\", skillName);\n        if (StringUtils.isNotBlank(version)) {\n            params.put(\"version\", version);\n        }\n        if (StringUtils.isNotBlank(label)) {\n            params.put(\"label\", label);\n        }\n        \n        RequestResource resource = RequestResource.aiBuilder().setNamespace(namespaceId)\n            .setGroup(com.alibaba.nacos.api.common.Constants.DEFAULT_GROUP)\n            .setResource(null == skillName ? StringUtils.EMPTY : skillName).build();\n        \n        byte[] zipBytes = reqApiBytes(SKILL_DOWNLOAD_PATH, params, resource);\n        SkillUtils.validateZipBytes(zipBytes);\n        try {\n            SkillUtils.validateZipEntryPaths(zipBytes);\n        } catch (Exception e) {\n            throw new NacosException(NacosException.SERVER_ERROR,\n                \"Downloaded ZIP contains unsafe entry paths: \" + e.getMessage(), e);\n        }\n        return zipBytes;\n    }\n    \n    @Override\n    public SkillQueryResponse querySkill(String skillName, String version, String label, String md5)\n        throws NacosException {\n        Map<String, String> params = new HashMap<>(8);\n        params.put(\"namespaceId\", namespaceId);\n        params.put(\"name\", skillName);\n        if (StringUtils.isNotBlank(version)) {\n            params.put(\"version\", version);\n        }\n        if (StringUtils.isNotBlank(label)) {\n            params.put(\"label\", label);\n        }\n        if (StringUtils.isNotBlank(md5)) {","sourceCodeStart":296,"sourceCodeEnd":332,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/client/src/main/java/com/alibaba/nacos/client/ai/remote/AiHttpClientProxy.java#L296-L332","documentation":"Thrown by AiHttpClientProxy.downloadSkillZip after SkillUtils.validateZipEntryPaths detects an unsafe (zip-slip or otherwise malicious) entry path in the downloaded skill ZIP. validateZipBytes already confirmed non-empty content; this second guard blocks path-traversal entries that could escape the extraction target. SERVER_ERROR reflects a corrupt or malicious server payload.","triggerScenarios":"The server returns a skill ZIP containing an entry whose path traverses outside the intended directory (e.g. ../../etc/passwd) or otherwise violates the safe-path contract; SkillUtils.validateZipEntryPaths raises and the client wraps it.","commonSituations":"A tampered or maliciously crafted skill package on the server; a packaging bug in the skill build that emitted absolute or traversal paths; server-side zip assembly regression producing invalid entry names.","solutions":["Inspect the downloaded ZIP entries to confirm which path triggered the guard (the exception message lists them).","Re-publish the skill from a clean, correctly-packaged build that uses relative, in-bounds entry paths.","If untrusted, do not extract; quarantine the package and audit the skill source.","Ensure the skill build tooling normalizes entry paths before zipping."],"exampleFix":"// before: skill built with absolute/traversal entry names\n// after: build with normalized relative paths, e.g.\n//   zip entries like \"skills/my-skill/manifest.json\" (no leading / or ../)","handlingStrategy":"validation","validationCode":"// Before publishing a skill, validate its entries locally:\nSkillUtils.validateZipEntryPaths(Files.readAllBytes(Path.of(\"skill.zip\")));","typeGuard":null,"tryCatchPattern":"try {\n    client.downloadSkillZip(name, version, label);\n} catch (NacosException e) {\n    if (e.getErrCode() == NacosException.SERVER_ERROR\n        && e.getMessage().contains(\"unsafe entry paths\")) {\n        // do not extract; quarantine and republish with normalized entry paths\n    }\n    throw e;\n}","preventionTips":["Build skill ZIPs with normalized, relative, in-bounds entry paths.","Validate ZIP entries before publishing to the server.","Never extract untrusted skill packages; audit their contents."],"tags":["ai","skill","security","zip-slip","validation","http"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}