mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-07-26 11:49:16 +00:00
bee0dfd094
A previous fix canonicalized each Sencho-managed path (compose base, data dir, application root, OS temp root, upload spool, Trivy binary, Trivy cache) with fs.realpath so a managed path that is itself a symlink could not be reached through a bind to its real target. fs.realpath returns ENOENT for a dangling symlink whose final leaf does not exist yet, so that case fell through to the configured path only and the implied target was lost. With TRIVY_BIN pointing at a symlink to a not yet created binary, a bind to the symlink target's existing parent directory was still classified as browsable and writable. A stack editor could create the leaf there and have a later pre or post deploy scan execute the attacker supplied binary, which the default image runs as root. The same gap applied to dangling symlinked upload spool, Trivy cache, and OS temp roots. Resolve managed paths with a helper that follows the symlink chain even when the final leaf is absent: it follows a dangling link through readlink (resolving a relative target against the link's own directory) and, for a missing leaf, resolves the longest existing ancestor and re-appends the absent suffix, so the real target location is always represented in the overlap set. A bounded hop count guards against a symlink cycle that never surfaces as ELOOP, falling back to the lexical path with a log. An unexpected resolution failure (EACCES, ELOOP) keeps the configured path as the containment anchor, continues discovery for the other managed paths, and is logged. Tests: a mock-based regression test that fails before the fix, a real-filesystem dangling-symlink test on Linux and macOS CI, a relative-symlink-target case, and a non-ENOENT failure case asserting discovery degrades safely.