docx-validate
    Preparing search index...

    Function containRelationshipTarget

    • Containment check for relationship targets resolved from untrusted OOXML parts (CWE-22). Two layers, and the canonical one decides (#594):

      1. Lexical: the resolved path, as spelled, must stay under unpackedDir (path.relative must not escape via .. or go absolute). This judges the spellings as passed, so on a case-insensitive volume it reads an in-root target spelled unlike the root as an escape — it is a filter, never the verdict, while layer 2 can run.
      2. Symlinks and case: a purely lexical check is defeated by a symlink inside the unpacked tree pointing outward (link/secret where link → /etc), and blind to spelling: Node's JS realpathSync keeps the case a path is written in, so only realpathSync.native reports the on-disk case (#587). The root is canonicalized and the deepest EXISTING ancestor of the target is resolved with realpathSync.native and re-checked against it: a target whose canonical path lies under the canonical root is contained under any spelling; non-existent trailing components cannot change the verdict (callers report missing targets as broken anyway).

      The lexical layer decides only when the realpath layer cannot run — when the root itself cannot be canonicalized, or when nothing along the target resolves — and it fails closed for a lexical escape in both cases.

      Returns the target as passed when contained, null on escape. Not race-resistant across the check and a later open — acceptable for a validator scanning an unpacked tree it controls; flagged for any future fd-based (O_NOFOLLOW) hardening.

      Parameters

      • unpackedDir: string
      • resolvedPath: string

      Returns string | null