{"record":{"id":"a6d48b211df05347","repo":"NousResearch/hermes-agent","slug":"refusing-to-extract-unsafe-archive-member-member","errorCode":null,"errorMessage":"Refusing to extract unsafe archive member {member!r}: it escapes the extraction directory","messagePattern":"Refusing to extract unsafe archive member (.+?): it escapes the extraction directory","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"agent/secret_sources/bitwarden.py","lineNumber":350,"sourceCode":"    zf: zipfile.ZipFile, member: str, dest_dir: Path\n) -> Path:\n    \"\"\"Extract a single archive member, refusing path traversal.\n\n    ``ZipFile.extract`` will happily honour member names containing\n    ``../`` or absolute paths, letting a malicious archive write outside\n    ``dest_dir`` (a \"zip-slip\").  We resolve the would-be target and\n    confirm it stays within ``dest_dir`` before extracting.\n    \"\"\"\n    dest_root = os.path.realpath(dest_dir)\n    target = os.path.realpath(os.path.join(dest_root, member))\n    # ``commonpath`` raises ValueError for e.g. different drives on\n    # Windows; treat that as an escape too.\n    try:\n        contained = os.path.commonpath([dest_root, target]) == dest_root\n    except ValueError:\n        contained = False\n    if not contained or target == dest_root:\n        raise RuntimeError(\n            f\"Refusing to extract unsafe archive member {member!r}: \"\n            f\"it escapes the extraction directory\"\n        )\n    zf.extract(member, dest_root)\n    return Path(target)\n\n\n# ---------------------------------------------------------------------------\n# Secret fetch + apply\n# ---------------------------------------------------------------------------\n\n\ndef _token_fingerprint(token: str) -> str:\n    \"\"\"SHA-256 prefix used as a cache key — never logged, never displayed.\"\"\"\n    return hashlib.sha256(token.encode(\"utf-8\")).hexdigest()[:16]\n\n\ndef _b64e(raw: bytes) -> str:","sourceCodeStart":332,"sourceCodeEnd":368,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/agent/secret_sources/bitwarden.py#L332-L368","documentation":"Error \"Refusing to extract unsafe archive member {member!r}: it escapes the extraction directory\" thrown in NousResearch/hermes-agent.","triggerScenarios":"Thrown at agent/secret_sources/bitwarden.py:350 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Do not extract the archive member that escapes the target directory; re-download from the official release.","Treat the archive as untrusted and verify its origin before extracting."],"exampleFix":null,"handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}