fix(aws): refuse credentials in repo URLs and HEAD as a branch
- validate_repo_url rejects https URLs with userinfo (user:pass@ or token@), pointing at the project's Git HTTPS token setting (m4). - validate_branch rejects HEAD (m5). - The FIXED_ENVIRONMENT doc comment sits on FIXED_ENVIRONMENT again (m6). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2772647690
commit
7f113f58ac
2 files changed
+33
-2
No files matched your search
@@ -74,10 +74,10 @@ const KEY_REPOS: &str = "TRIPLEC_REPOS";
|
||||
const KEY_WIP_PUSH: &str = "TRIPLEC_WIP_PUSH";
|
||||
const KEY_IDLE: &str = "TRIPLEC_IDLE_STOP_MINUTES";
|
||||
const KEY_STORAGE: &str = "TRIPLEC_STORAGE";
|
||||
/// The task definition's whole `environment` (R2): constants, no project data.
|
||||
/// Seconds ECS waits after SIGTERM before SIGKILL (Fargate allows 2–120).
|
||||
pub const STOP_TIMEOUT_SECS: i32 = 120;
|
||||
|
||||
/// The task definition's whole `environment` (R2): constants, no project data.
|
||||
const FIXED_ENVIRONMENT: [(&str, &str); 2] = [("TRIPLEC_HOST", "aws"), ("COLORTERM", "truecolor")];
|
||||
|
||||
fn other(message: impl Into<String>) -> AwsError {
|
||||
|
||||
@@ -585,6 +585,15 @@ fn validate_repo_url(url: &str) -> Result<(), String> {
|
||||
return bad("must not start with '-'");
|
||||
}
|
||||
let ok = if let Some(rest) = url.strip_prefix("https://") {
|
||||
// Credentials in the URL would sit in the project secret and in
|
||||
// `.git/config` in the clear, and leak into every clone's remote.
|
||||
let authority = rest.split(['/', '?', '#']).next().unwrap_or("");
|
||||
if authority.contains('@') {
|
||||
return bad(
|
||||
"must not carry credentials (user:password@ or token@); put the token in the \
|
||||
project's Git HTTPS token setting (Access) instead",
|
||||
);
|
||||
}
|
||||
!rest.is_empty()
|
||||
} else if let Some(rest) = url.strip_prefix("ssh://") {
|
||||
!rest.is_empty()
|
||||
@@ -610,6 +619,11 @@ fn validate_branch(branch: &str) -> Result<(), String> {
|
||||
if branch.starts_with('-') || branch.starts_with('/') || branch.ends_with('/') {
|
||||
return bad("must not start with '-' or start/end with '/'");
|
||||
}
|
||||
// `HEAD` passes check-ref-format but `git clone --branch HEAD` fails
|
||||
// (and a branch named HEAD is refused by `git branch`).
|
||||
if branch == "HEAD" {
|
||||
return bad("HEAD is not a branch; leave the branch empty for the default branch");
|
||||
}
|
||||
if branch == "@" || branch.ends_with('.') || branch.contains("..") || branch.contains("@{") || branch.contains("//") {
|
||||
return bad("is not a valid branch name");
|
||||
}
|
||||
@@ -1405,13 +1419,30 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_https_url_with_credentials_is_refused_pointing_at_the_token_setting() {
|
||||
let check = |u: &str| validate_aws_workspace(&with_repos(vec![repo(u, None, "x")]));
|
||||
for bad in [
|
||||
"https://user:pass@github.com/o/r.git",
|
||||
"https://ghp_abc@github.com/o/r.git",
|
||||
"https://oauth2:tok@gitlab.com/o/r",
|
||||
] {
|
||||
let e = check(bad).unwrap_err();
|
||||
assert!(e.contains("Git HTTPS token"), "{e}");
|
||||
}
|
||||
// An @ in the path is not userinfo; ssh and scp forms keep their user.
|
||||
for good in ["https://h/o/r@v2.git", "ssh://git@h/o/r.git", "git@github.com:o/r.git"] {
|
||||
assert!(check(good).is_ok(), "{good}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn branches_follow_check_ref_format() {
|
||||
let ok = |b: Option<&str>| validate_aws_workspace(&with_repos(vec![repo("https://h/r", b, "x")])).is_ok();
|
||||
for good in [None, Some("main"), Some("feat/aws-1"), Some("v1.2.3"), Some("a@b")] {
|
||||
assert!(ok(good), "{good:?}");
|
||||
}
|
||||
for bad in ["", "-x", "a..b", "a b", "a~1", "a^", "a:b", "a?", "a*", "a[", "a\\b", "a.lock", "x/.hidden", "a/", "/a", "a//b", "a@{1}", "@", "a."] {
|
||||
for bad in ["", "-x", "a..b", "a b", "a~1", "a^", "a:b", "a?", "a*", "a[", "a\\b", "a.lock", "x/.hidden", "a/", "/a", "a//b", "a@{1}", "@", "a.", "HEAD"] {
|
||||
assert!(!ok(Some(bad)), "{bad:?}");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user