Page MenuHomePhabricator

D8546.diff
No OneTemporary

D8546.diff

diff --git a/src/future/exec/CommandException.php b/src/future/exec/CommandException.php
--- a/src/future/exec/CommandException.php
+++ b/src/future/exec/CommandException.php
@@ -60,18 +60,20 @@
$limit = 1000;
$len = strlen($string);
- if ($len <= $limit) {
- return $string;
+ if ($len > $limit) {
+ $cut = $len - $limit;
+ $suffix = "... (".number_format($cut)." more bytes) ...";
+ if ($cut > strlen($suffix)) {
+ $string = substr($string, 0, $limit).$suffix;
+ }
}
- $cut = $len - $limit;
- $suffix = "... (".number_format($cut)." more bytes) ...";
+ // Strip out any credentials for the purpose of building a human readable
+ // summary of the exception, since these are rarely-if-ever useful when
+ // debugging, but can expose otherwise sensitive information.
+ $string = phutil_censor_credentials($string);
- if ($cut > strlen($suffix)) {
- return substr($string, 0, $limit).$suffix;
- } else {
- return $string;
- }
+ return $string;
}
}
diff --git a/src/utils/__tests__/PhutilUtilsTestCase.php b/src/utils/__tests__/PhutilUtilsTestCase.php
--- a/src/utils/__tests__/PhutilUtilsTestCase.php
+++ b/src/utils/__tests__/PhutilUtilsTestCase.php
@@ -514,5 +514,35 @@
}
}
+ public function testCensorCredentials() {
+ $cases = array(
+ '' => '',
+ 'abc' => 'abc',
+
+ // NOTE: We're liberal about censoring here, since we can't tell
+ // if this is a truncated password at the end of an input string
+ // or a domain name. The version with a "/" isn't censored.
+ 'http://example.com' => 'http://xxxxx',
+ 'http://example.com/' => 'http://example.com/',
+
+ 'http://username@example.com' => 'http://xxxxx@example.com',
+ 'http://user:pass@example.com' => 'http://xxxxx@example.com',
+
+ // We censor these because they might be truncated credentials at the end
+ // of the string.
+ 'http://user' => 'http://xxxxx',
+ "http://user\n" => "http://xxxxx\n",
+
+ 'svn+ssh://user:pass@example.com' => 'svn+ssh://xxxxx@example.com',
+ );
+
+ foreach ($cases as $input => $expect) {
+ $this->assertEqual(
+ $expect,
+ phutil_censor_credentials($input),
+ pht('Credential censoring for: %s', $input));
+ }
+ }
+
}
diff --git a/src/utils/utils.php b/src/utils/utils.php
--- a/src/utils/utils.php
+++ b/src/utils/utils.php
@@ -1052,3 +1052,19 @@
}
return $result;
}
+
+
+/**
+ * Attempt to censor any plaintext credentials from a string.
+ *
+ * The major use case here is to censor usernames and passwords from command
+ * output. For example, when `git fetch` fails, the output includes credentials
+ * for authenticated HTTP remotes.
+ *
+ * @param string Some block of text.
+ * @return string A similar block of text, but with credentials that could
+ * be identified censored.
+ */
+function phutil_censor_credentials($string) {
+ return preg_replace(',(?<=://)([^/@\s]+)(?=@|$),', 'xxxxx', $string);
+}

File Metadata

Mime Type
text/plain
Expires
Sat, Apr 19, 8:01 PM (2 w, 5 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7675664
Default Alt Text
D8546.diff (2 KB)

Event Timeline