Documentation
¶
Index ¶
- Variables
- func CheckPath(userPath string) (string, error)
- func DirMode() os.FileMode
- func PrivateDirs() bool
- func SandboxUser() string
- type Manager
- func (m *Manager) Create(sessionID uuid.UUID) (string, error)
- func (m *Manager) CreateSnapshot(sessionID, snapshotID uuid.UUID) (archivePath string, sizeBytes int64, err error)
- func (m *Manager) Delete(sessionID uuid.UUID) error
- func (m *Manager) DeleteSnapshot(archivePath string) error
- func (m *Manager) Exists(sessionID uuid.UUID, userPath string) (bool, error)
- func (m *Manager) OpenFile(sessionID uuid.UUID, userPath string) (*os.File, error)
- func (m *Manager) RestoreSnapshot(sessionID uuid.UUID, archivePath string) error
- func (m *Manager) SafePath(sessionID uuid.UUID, userPath string) (string, error)
- func (m *Manager) SessionDirs() ([]uuid.UUID, error)
- func (m *Manager) SessionPath(sessionID uuid.UUID) string
- func (m *Manager) WriteFile(sessionID uuid.UUID, userPath string, r io.Reader, maxBytes int64) (int64, error)
Constants ¶
This section is empty.
Variables ¶
var ErrPathTraversal = errors.New("path traversal detected")
ErrPathTraversal is returned for a path with a ".." component.
Functions ¶
func CheckPath ¶ added in v0.4.7
CheckPath rejects a user-provided path that contains a ".." component and returns the path with percent-encoding fully decoded. Callers use it to answer with an error instead of quietly rewriting "../x" to "/x".
The path is URL-decoded in a loop until stable to catch double/triple-encoded traversals (%252e%252e%2f), and the check is per component, not strings.Contains, so "foo..txt" stays valid.
func DirMode ¶ added in v0.4.7
DirMode is the mode for session directories: 0o700 when the sandbox user owns them, otherwise 0o777 so a differently-numbered sandbox user (e.g. "nobody", UID 65534) can write. In the 0o777 case the parent WORKSPACE_BASE_DIR is created 0o700 so other host users cannot reach the session directories.
func PrivateDirs ¶ added in v0.4.7
func PrivateDirs() bool
PrivateDirs reports whether session directories are owned by the sandbox user and can therefore be created owner-only.
func SandboxUser ¶ added in v0.4.7
func SandboxUser() string
SandboxUser returns the user ("uid:gid" or a name) sandbox processes run as.
By default sandboxes run as the same uid:gid as the API process. They then own the bind-mounted session directory, which can stay 0o700. If the API runs as root (not the Compose default) there is no private uid to share, so the legacy "nobody" user is used together with world-writable (0o777) session directories. SANDBOX_USER overrides the choice; any value other than the API's own uid:gid keeps the 0o777 directories because the user cannot be assumed to own them.
Types ¶
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
func (*Manager) Create ¶
Create initializes an isolated workspace directory for a session.
os.MkdirAll honours the process umask, which can strip permission bits; the explicit os.Chmod afterwards is umask-independent.
func (*Manager) CreateSnapshot ¶
func (m *Manager) CreateSnapshot(sessionID, snapshotID uuid.UUID) (archivePath string, sizeBytes int64, err error)
CreateSnapshot creates a gzip-compressed tar archive of the session workspace. The archive is written to {baseDir}/snapshots/<snapshotID>.tar.gz and the archive path + uncompressed size are returned.
func (*Manager) DeleteSnapshot ¶
DeleteSnapshot removes a snapshot archive from disk.
func (*Manager) Exists ¶ added in v0.3.2
Exists reports whether userPath refers to a real file/dir inside the session workspace. Symlinks that escape the workspace root are treated as absent (not an oracle for host paths).
func (*Manager) OpenFile ¶
OpenFile opens a file inside the workspace for reading. Symlink targets are validated to remain inside the workspace.
func (*Manager) RestoreSnapshot ¶
RestoreSnapshot extracts a snapshot archive into the session workspace. Files in the archive overwrite existing files; the workspace is not cleared first so existing files not in the snapshot are preserved.
func (*Manager) SafePath ¶
SafePath resolves a user-provided path within the workspace, enforcing:
- URL-decoded (loop until stable) to catch double/triple-encoded traversals
- No ".." path components (checked after full decoding, before Clean)
- Resolved path stays inside the workspace root (filepath.Clean + HasPrefix)
func (*Manager) SessionDirs ¶ added in v0.4.1
SessionDirs returns the session IDs that have a directory under the base directory. Entries whose name is not a UUID (snapshots/, warm pool) are skipped.
func (*Manager) WriteFile ¶
func (m *Manager) WriteFile(sessionID uuid.UUID, userPath string, r io.Reader, maxBytes int64) (int64, error)
WriteFile writes data to a safe path inside the workspace, creating intermediate directories as needed.
Security: guards against symlink-escape attacks where a container process creates a symlink inside /workspace pointing to a host path outside the workspace root. Two layers of protection are applied:
- The entire parent-directory chain is symlink-resolved and verified to stay inside the workspace root before any write takes place.
- The file is opened with O_NOFOLLOW so that if the final path component is itself a symlink (e.g. created in a TOCTOU window) the open fails.
Permissions: directories use DirMode and files 0o644. os.Chmod is called after creation to bypass the process umask.