Fork of daniellemaywood.uk/gleam — Wasm codegen work
2

Configure Feed

Select the types of activity you want to include in your feed.

Restrict tarball creation

+60 -9
+8 -1
CHANGELOG.md
··· 514 514 515 515 - Restrict custom documentation page `path` and `source` values so `gleam docs 516 516 build` cannot escape the docs output directory or project root. 517 - ([evipepota](https://github.com/evipepota)) 517 + ([evipepota](https://github.com/evipepota) and 518 + ([Louis Pilfold](https://github.com/lpil)) 519 + 520 + - Restrict publication tarball creation so they cannot contain files from 521 + outside the project root. 522 + ([Abdelrahman Ahmed Aboelkasem](https://github.com/0x2face), 523 + ([Aly](https://github.com/spect3r1), and 524 + ([Louis Pilfold](https://github.com/lpil))
+1 -1
compiler-cli/src/fs.rs
··· 477 477 } 478 478 479 479 /// Walks through all files in the directory, even if ignored. 480 - pub fn private_files(dir: &Utf8Path) -> impl Iterator<Item = Utf8PathBuf> + '_ { 480 + pub fn priv_directory_files(dir: &Utf8Path) -> impl Iterator<Item = Utf8PathBuf> + '_ { 481 481 ignore::WalkBuilder::new(dir) 482 482 .follow_links(true) 483 483 .standard_filters(false)
+33 -7
compiler-cli/src/publish.rs
··· 544 544 Target::JavaScript => vec![], 545 545 }; 546 546 let src_files = project_files(Utf8Path::new(""))?; 547 - let contents_tar_gz = contents_tarball(&src_files, &generated_files)?; 547 + let contents_tar_gz = contents_tarball(&paths, &src_files, &generated_files)?; 548 548 let version = "3"; 549 549 let metadata = metadata_config( 550 550 &built.root_package.config, ··· 648 648 } 649 649 650 650 fn contents_tarball( 651 + paths: &ProjectPaths, 651 652 files: &[Utf8PathBuf], 652 653 data_files: &[(Utf8PathBuf, String)], 653 654 ) -> Result<Vec<u8>, Error> { ··· 656 657 let mut tarball = 657 658 tar::Builder::new(GzEncoder::new(&mut contents_tar_gz, Compression::default())); 658 659 for path in files { 659 - add_path_to_tar(&mut tarball, path)?; 660 + add_path_to_tar(&mut tarball, paths, path)?; 660 661 } 661 662 for (path, contents) in data_files { 662 663 add_to_tar(&mut tarball, path, contents.as_bytes())?; ··· 673 674 .chain(fs::native_files(&src)) 674 675 .collect(); 675 676 let private = base_path.join(Utf8Path::new("priv")); 676 - let mut private_files: Vec<Utf8PathBuf> = fs::private_files(&private).collect(); 677 + let mut private_files: Vec<Utf8PathBuf> = fs::priv_directory_files(&private).collect(); 677 678 files.append(&mut private_files); 678 679 let mut add = |path| { 679 680 let path = base_path.join(path); ··· 755 756 .map_err(|e| Error::add_tar(path, e)) 756 757 } 757 758 758 - fn add_path_to_tar<P, W>(tarball: &mut tar::Builder<W>, path: P) -> Result<()> 759 + fn add_path_to_tar<P, W>(tarball: &mut tar::Builder<W>, paths: &ProjectPaths, path: P) -> Result<()> 759 760 where 760 761 P: AsRef<Utf8Path>, 761 762 W: Write, 762 763 { 763 764 let path = path.as_ref(); 764 - tracing::info!(file=?path, "Adding file to tarball"); 765 + let path = fs::canonicalise(path)?; 766 + 767 + if !path.starts_with(paths.root()) { 768 + return Err(Error::TarPathOutsideOfProjectRoot { path }); 769 + } 770 + 771 + tracing::info!(file=?&path, "Adding file to tarball"); 765 772 tarball 766 - .append_path(path) 767 - .map_err(|e| Error::add_tar(path, e)) 773 + .append_path(&path) 774 + .map_err(|e| Error::add_tar(&path, e)) 775 + } 776 + 777 + #[test] 778 + fn add_to_tar_symlink_rejection_test() { 779 + let tmp_dir = tempfile::tempdir().unwrap(); 780 + let path = std::fs::canonicalize(tmp_dir.path()).unwrap(); 781 + let path = Utf8Path::from_path(&path).expect("Non Utf-8 Path"); 782 + let paths = ProjectPaths::new(path.join("package")); 783 + let mut contents_tar_gz = Vec::new(); 784 + let mut tarball = tar::Builder::new(&mut contents_tar_gz); 785 + 786 + // This file is outside the root of the project, so it should 787 + // not be possible to add it to the tar archive. 788 + let outside_path = path.join("outside.txt"); 789 + std::fs::write(&outside_path, "Hello").unwrap(); 790 + match add_path_to_tar(&mut tarball, &paths, &outside_path).unwrap_err() { 791 + Error::TarPathOutsideOfProjectRoot { path } => assert_eq!(path, outside_path), 792 + other => panic!("Unexpected error {other:?}"), 793 + } 768 794 } 769 795 770 796 #[derive(Debug, Clone)]
+18
compiler-core/src/error.rs
··· 418 418 419 419 #[error("Incorrect Hex one-time-password")] 420 420 IncorrectHexOneTimePassword, 421 + 422 + #[error("{path} could not be added to the tarball as it is outside the project root")] 423 + TarPathOutsideOfProjectRoot { path: Utf8PathBuf }, 421 424 } 422 425 423 426 #[derive(Debug, Eq, PartialEq, Clone, Copy)] ··· 988 991 You'll need to re-authenticate to continue using Hex." 989 992 .into(), 990 993 hint: Some("Run 'gleam hex authenticate' to log in again.".into()), 994 + level: Level::Error, 995 + location: None, 996 + }], 997 + 998 + Error::TarPathOutsideOfProjectRoot { path } => vec![Diagnostic { 999 + title: "Cannot add path to tar archive".into(), 1000 + text: wrap(&format!( 1001 + "The path {path} is outside this Gleam project, \ 1002 + so we cannot safely add it to the archive for publishing. If we permitted this \ 1003 + then malicious actors could abuse this functionality to trick you into sharing \ 1004 + your private information. 1005 + 1006 + Move the file into your Gleam project and try again." 1007 + )), 1008 + hint: None, 991 1009 level: Level::Error, 992 1010 location: None, 993 1011 }],