fix(CTRL-001): reject path traversal in .fab import manifest
manifest.AppName / HDDSubdirs / VolumeNames are attacker-controlled JSON inside an imported .fab and reach filepath.Join+MkdirAll/extractTar with a trusted base (restore.go:339/606/678). UnmarshalManifest did zero validation, so '../..' in any of them escaped the stacks / HDD destination dir. - New appexport.ValidateSegment + validateManifestPaths; UnmarshalManifest now fails the parse on a traversal segment (the chokepoint). - Defence-in-depth ValidateSegment guards at the HDD-subdir and volume-name join loops in restore.go. - ConfigFiles deliberately NOT validated (holds dotfiles like .felhom.yml; never used in a restore join). - Permanent regression test (was the deep-sweep failing audit test) now asserts rejection of traversal + acceptance of legit names. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -589,6 +589,11 @@ func (e *Exporter) restoreHDDData(tmpDir string, manifest *Manifest, composePath
|
||||
}
|
||||
|
||||
for _, subdir := range manifest.HDDSubdirs {
|
||||
// [CTRL-001] defence-in-depth: refuse any subdir that is not a single
|
||||
// safe segment before it reaches MkdirAll/extractTar on a user drive.
|
||||
if err := ValidateSegment("hdd_subdir", subdir); err != nil {
|
||||
return err
|
||||
}
|
||||
tarPath := filepath.Join(hddDir, subdir+".tar")
|
||||
tarInfo, err := os.Stat(tarPath)
|
||||
if err != nil {
|
||||
@@ -670,6 +675,11 @@ func (e *Exporter) restoreVolumeData(tmpDir string, manifest *Manifest) error {
|
||||
volDir := filepath.Join(tmpDir, "data", "volumes")
|
||||
|
||||
for _, volName := range manifest.VolumeNames {
|
||||
// [CTRL-001] defence-in-depth: refuse any volume name that is not a
|
||||
// single safe segment before it reaches a tar path / docker volume op.
|
||||
if err := ValidateSegment("volume_name", volName); err != nil {
|
||||
return err
|
||||
}
|
||||
tarPath := filepath.Join(volDir, volName+".tar")
|
||||
tarInfo, err := os.Stat(tarPath)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user