Skip to content

Commit 1809b9b

Browse files
authored
Merge pull request from GHSA-x3r5-q6mj-m485
sanitize target names and delegate role names
2 parents a9a0f5e + 31ca710 commit 1809b9b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+2418
-346
lines changed

Diff for: Cargo.lock

+25-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: tough-kms/CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## [0.3.4] - 2021-10-19
8+
### Changes
9+
- Update dependencies.
10+
711
## [0.3.3] - 2021-09-15
812
### Changes
913
- Update dependencies.
@@ -60,6 +64,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6064
### Added
6165
- Everything!
6266

67+
[0.3.4]: https://github.com/awslabs/tough/compare/tough-kms-v0.3.3...tough-kms-v0.3.4
6368
[0.3.3]: https://github.com/awslabs/tough/compare/tough-kms-v0.3.2...tough-kms-v0.3.3
6469
[0.3.2]: https://github.com/awslabs/tough/compare/tough-kms-v0.3.1...tough-kms-v0.3.2
6570
[0.3.1]: https://github.com/awslabs/tough/compare/tough-kms-v0.3.0...tough-kms-v0.3.1

Diff for: tough-kms/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "tough-kms"
3-
version = "0.3.3"
3+
version = "0.3.4"
44
description = "Implements AWS KMS as a key source for TUF signing keys"
55
authors = ["Shailesh Gothi <gothisg@amazon.com>"]
66
license = "MIT OR Apache-2.0"
@@ -15,7 +15,7 @@ rusoto-native-tls = ["rusoto_core/native-tls", "rusoto_credential", "rusoto_kms/
1515
rusoto-rustls = ["rusoto_core/rustls", "rusoto_credential", "rusoto_kms/rustls"]
1616

1717
[dependencies]
18-
tough = { version = "0.11.3", path = "../tough", features = ["http"] }
18+
tough = { version = "0.12.0", path = "../tough", features = ["http"] }
1919
ring = { version = "0.16.16", features = ["std"] }
2020
rusoto_core = { version = "0.47", optional = true, default-features = false }
2121
rusoto_credential = { version = "0.47", optional = true }

Diff for: tough-ssm/CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## [0.6.4] - 2021-10-19
8+
### Changes
9+
- Update dependencies.
10+
711
## [0.6.3] - 2021-09-15
812
### Changes
913
- Update dependencies.
@@ -69,6 +73,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6973
### Added
7074
- Everything!
7175

76+
[0.6.4]: https://github.com/awslabs/tough/compare/tough-ssm-v0.6.3...tough-ssm-v0.6.4
7277
[0.6.3]: https://github.com/awslabs/tough/compare/tough-ssm-v0.6.2...tough-ssm-v0.6.3
7378
[0.6.2]: https://github.com/awslabs/tough/compare/tough-ssm-v0.6.1...tough-ssm-v0.6.2
7479
[0.6.1]: https://github.com/awslabs/tough/compare/tough-ssm-v0.6.0...tough-ssm-v0.6.1

Diff for: tough-ssm/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "tough-ssm"
3-
version = "0.6.3"
3+
version = "0.6.4"
44
description = "Implements AWS SSM as a key source for TUF signing keys"
55
authors = ["Zac Mrowicki <mrowicki@amazon.com>"]
66
license = "MIT OR Apache-2.0"
@@ -15,7 +15,7 @@ rusoto-native-tls = ["rusoto_core/native-tls", "rusoto_credential", "rusoto_ssm/
1515
rusoto-rustls = ["rusoto_core/rustls", "rusoto_credential", "rusoto_ssm/rustls"]
1616

1717
[dependencies]
18-
tough = { version = "0.11.3", path = "../tough", features = ["http"] }
18+
tough = { version = "0.12.0", path = "../tough", features = ["http"] }
1919
rusoto_core = { version = "0.47", optional = true, default-features = false }
2020
rusoto_credential = { version = "0.47", optional = true }
2121
rusoto_ssm = { version = "0.47", optional = true, default-features = false }

Diff for: tough/CHANGELOG.md

+11-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## [0.12.0] - 2021-10-19
8+
### Breaking Changes
9+
- Target names are now specified with a struct, `TargetName`, instead of `String`.
10+
11+
### Changes
12+
- Update dependencies.
13+
- Fix an issue where delegated role names with path traversal constructs could cause files to be written in unexpected locations.
14+
- Fix a similar issue with path traversal constructs in target names.
15+
716
## [0.11.3] - 2021-09-15
817
### Changes
918
- Update dependencies.
@@ -149,7 +158,8 @@ For changes that require modification of calling code see #120 and #121.
149158
### Added
150159
- Everything!
151160

152-
[Unreleased]: https://github.com/awslabs/tough/compare/tough-v0.11.3...HEAD
161+
[Unreleased]: https://github.com/awslabs/tough/compare/tough-v0.12.0...HEAD
162+
[0.12.0]: https://github.com/awslabs/tough/compare/tough-v0.11.3...tough-v0.12.0
153163
[0.11.3]: https://github.com/awslabs/tough/compare/tough-v0.11.2...tough-v0.11.3
154164
[0.11.2]: https://github.com/awslabs/tough/compare/tough-v0.11.1...tough-v0.11.2
155165
[0.11.1]: https://github.com/awslabs/tough/compare/tough-v0.11.0...tough-v0.11.1

Diff for: tough/Cargo.toml

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "tough"
3-
version = "0.11.3"
3+
version = "0.12.0"
44
description = "The Update Framework (TUF) repository client"
55
authors = ["iliana destroyer of worlds <iweller@amazon.com>"]
66
license = "MIT OR Apache-2.0"
@@ -15,7 +15,9 @@ globset = { version = "0.4.8" }
1515
hex = "0.4.2"
1616
log = "0.4.8"
1717
olpc-cjson = { version = "0.1.0", path = "../olpc-cjson" }
18+
path-absolutize = "3"
1819
pem = "1.0.0"
20+
percent-encoding = "2"
1921
reqwest = { version = "0.11.1", optional = true, default-features = false, features = ["blocking"] }
2022
ring = { version = "0.16.16", features = ["std"] }
2123
serde = { version = "1.0.125", features = ["derive"] }
@@ -30,6 +32,7 @@ walkdir = "2.3.2"
3032
[dev-dependencies]
3133
hex-literal = "0.3.3"
3234
httptest = "0.15"
35+
maplit = "1.0.1"
3336

3437
[features]
3538
http = ["reqwest"]

Diff for: tough/src/cache.rs

+22-27
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
use crate::error::{self, Result};
22
use crate::fetch::{fetch_max_size, fetch_sha256};
33
use crate::schema::{RoleType, Target};
4-
use crate::Repository;
4+
use crate::{encode_filename, Prefix, Repository, TargetName};
55
use snafu::{OptionExt, ResultExt};
6-
use std::fs::OpenOptions;
76
use std::io::{Read, Write};
87
use std::path::Path;
98

@@ -38,8 +37,9 @@ impl Repository {
3837

3938
// Fetch targets and save them to the outdir
4039
if let Some(target_list) = targets_subset {
41-
for target_name in target_list.iter() {
42-
self.cache_target(&targets_outdir, target_name.as_ref())?;
40+
for raw_name in target_list.iter() {
41+
let target_name = TargetName::new(raw_name.as_ref())?;
42+
self.cache_target(&targets_outdir, &target_name)?;
4343
}
4444
} else {
4545
let targets = &self.targets.signed.targets_map();
@@ -162,10 +162,10 @@ impl Repository {
162162
.meta
163163
.get(&format!("{}.json", name))?
164164
.version,
165-
name
165+
encode_filename(name)
166166
))
167167
} else {
168-
Some(format!("{}.json", name))
168+
Some(format!("{}.json", encode_filename(name)))
169169
}
170170
}
171171

@@ -203,24 +203,16 @@ impl Repository {
203203

204204
/// Saves a signed target to the specified `outdir`. Retains the digest-prepended filename if
205205
/// consistent snapshots are used.
206-
fn cache_target<P: AsRef<Path>>(&self, outdir: P, name: &str) -> Result<()> {
207-
let t = self
208-
.targets
209-
.signed
210-
.find_target(name)
211-
.context(error::CacheTargetMissing {
212-
target_name: name.to_owned(),
213-
})?;
214-
let (sha, filename) = self.target_digest_and_filename(t, name);
215-
let mut reader = self.fetch_target(t, &sha, filename.as_str())?;
216-
let path = outdir.as_ref().join(filename);
217-
let mut f = OpenOptions::new()
218-
.write(true)
219-
.create(true)
220-
.open(&path)
221-
.context(error::CacheTargetWrite { path: path.clone() })?;
222-
let _ = std::io::copy(&mut reader, &mut f).context(error::CacheTargetWrite { path })?;
223-
Ok(())
206+
fn cache_target<P: AsRef<Path>>(&self, outdir: P, name: &TargetName) -> Result<()> {
207+
self.save_target(
208+
name,
209+
outdir,
210+
if self.consistent_snapshot {
211+
Prefix::Digest
212+
} else {
213+
Prefix::None
214+
},
215+
)
224216
}
225217

226218
/// Gets the max size of the snapshot.json file as specified by the timestamp file.
@@ -242,13 +234,16 @@ impl Repository {
242234
pub(crate) fn target_digest_and_filename(
243235
&self,
244236
target: &Target,
245-
name: &str,
237+
name: &TargetName,
246238
) -> (Vec<u8>, String) {
247239
let sha256 = &target.hashes.sha256.clone().into_vec();
248240
if self.consistent_snapshot {
249-
(sha256.clone(), format!("{}.{}", hex::encode(sha256), name))
241+
(
242+
sha256.clone(),
243+
format!("{}.{}", hex::encode(sha256), name.resolved()),
244+
)
250245
} else {
251-
(sha256.clone(), name.to_owned())
246+
(sha256.clone(), name.resolved().to_owned())
252247
}
253248
}
254249

0 commit comments

Comments
 (0)