Restrict file location for SSH and certificates credentials#533
Restrict file location for SSH and certificates credentials#533Kevin-CB wants to merge 1 commit into
Conversation
daniel-beck
left a comment
There was a problem hiding this comment.
Fix looks correct, but the tests could be improved.
| FilePath secretsDir = UnbindableDir.create(workspace).getDirPath(); | ||
| FilePath resolvedPath = secretsDir.child("keystore-" + payload); | ||
|
|
||
| assertFalse(resolvedPath.exists(), "Keystore file should not exist outside secure directory"); |
| if (workspace != null) { | ||
| final UnbindableDir secrets = UnbindableDir.create(workspace); | ||
| final FilePath secret = secrets.getDirPath().child("keystore-" + keystoreVariable); | ||
| String safeKeystoreVariable = new FilePath(new File(keystoreVariable)).getName(); |
There was a problem hiding this comment.
Looks familiar 👍 Also looks correctly adapted for the prefix unique to this case.
jtnord
left a comment
There was a problem hiding this comment.
the variable should not even be used for file names, create a unique file in the directory.
| String safeKeystoreVariable = new FilePath(new File(keystoreVariable)).getName(); | ||
| final FilePath secret = secrets.getDirPath().child("keystore-" + safeKeystoreVariable); |
There was a problem hiding this comment.
keystore variable is supposed to be the name of an environment variable not the temporary file!?
this should be a temporary file and not take in user specified paths.
e.g.
withCredentials([certificate(credentialsId: 'id1', keystoreVariable: 'hello')]) {
sh 'echo path is $hello and should exist'
withCredentials([certificate(credentialsId: 'id2', keystoreVariable: 'hello')]) {
sh 'echo path is $hello and should exist but be different to before'
}
sh 'echo path is $hello and should still exist (but the path for the previous id2 should be deleted'
}
So rather than attempting to sanitize somthing, this should surely just create a unique file without any user supplied being used.
(additionally - this does not sanitize against max filename lengths!)
There was a problem hiding this comment.
I tend to agree. But:
Also
should probably block anything that does not look like a valid variable name. (Too late for this attack.)There was a problem hiding this comment.
I think the original intent of using specific file names was to simplify diagnosis from build logs. But the bound file path is treated as a secret and masked anyway. So we might as well use arbitrary filenames (like random UUIDs).
| String safeKeystoreVariable = new FilePath(new File(keystoreVariable)).getName(); | ||
| final FilePath secret = secrets.getDirPath().child("keystore-" + safeKeystoreVariable); |
There was a problem hiding this comment.
| String safeKeystoreVariable = new FilePath(new File(keystoreVariable)).getName(); | |
| final FilePath secret = secrets.getDirPath().child("keystore-" + safeKeystoreVariable); | |
| final FilePath secret = secrets.getDirPath().createTempFile("keystore-", ".ks"); |
There was a problem hiding this comment.
createTempFile perhaps overkill given that each binding calls
|
Closed in favor of #534 |
#532
Testing done
Confirmed locally the file is not created outside the expected directory with the following pipeline
did the same for certificate creds.
Submitter checklist