1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
use dev_prefix::*;
use core::prefix::*;
use core;


/// validate that all files that could be affected by
/// the project are within the repo and the `settings.artifact_paths`
/// partof: #SPC-security
pub fn validate(repo: &Path, project: &Project) -> Result<()> {
    let mut files: HashSet<&PathBuf> = HashSet::new();
    files.extend(project.artifacts.values().map(|a| &a.path));
    files.extend(project.files.iter());
    files.extend(project.repo_map.keys());

    // PARENT_PATH is never written to, so ignore
    files.remove(&*core::types::PARENT_PATH);

    for f in files {
        if !f.is_absolute() {
            let msg = format!("{} is not an absolute path", f.display());
            return Err(ErrorKind::Internal(msg).into());
        }
        // only allow files that are in the cwd repo
        if !f.starts_with(repo) {
            let msg = format!("{} is not a subdir of cwd repo {}",
                              f.display(),
                              repo.display());
            return Err(ErrorKind::Security(msg).into());
        }
        // only allow files that are in the artifact_paths
        if !project.settings.artifact_paths.iter().any(|p| f.starts_with(p)) {
            let msg = format!("{} is not a subdir of any artifact_paths {:?}",
                              f.display(),
                              project.settings.artifact_paths);
            return Err(ErrorKind::Security(msg).into());
        }
        // files that do not already exist are invalid
        if !f.exists() {
            let msg = format!("{} does not already exist and cannot be created here",
                              f.display());
            return Err(ErrorKind::Security(msg).into());
        }
    }
    Ok(())
}