diff --git a/CHANGELOG.md b/CHANGELOG.md index 67b8e3884c..b9bf84217f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ #### Bugs * Fix #4534: Java Generator CLI default handling of skipGeneratedAnnotations +* Fix #4535: The shell command string will now have single quotes sanitized * Fix #4547: preventing timing issues with leader election cancel #### Improvements diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/core/v1/PodOperationsImpl.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/core/v1/PodOperationsImpl.java index dc0bcbe910..fa873acc0f 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/core/v1/PodOperationsImpl.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/core/v1/PodOperationsImpl.java @@ -185,8 +185,8 @@ public Loggable withLogWaitTimeout(Integer logWaitTimeout) { public PortForward portForward(int port, ReadableByteChannel in, WritableByteChannel out) { try { return new PortForwarderWebsocket(httpClient, this.context.getExecutor()).forward(getResourceUrl(), port, in, out); - } catch (Throwable t) { - throw KubernetesClientException.launderThrowable(t); + } catch (Exception e) { + throw KubernetesClientException.launderThrowable(e); } } @@ -194,8 +194,8 @@ public PortForward portForward(int port, ReadableByteChannel in, WritableByteCha public LocalPortForward portForward(int port) { try { return new PortForwarderWebsocket(httpClient, this.context.getExecutor()).forward(getResourceUrl(), port); - } catch (Throwable t) { - throw KubernetesClientException.launderThrowable(t); + } catch (Exception e) { + throw KubernetesClientException.launderThrowable(e); } } @@ -203,8 +203,8 @@ public LocalPortForward portForward(int port) { public LocalPortForward portForward(int port, int localPort) { try { return new PortForwarderWebsocket(httpClient, this.context.getExecutor()).forward(getResourceUrl(), port, localPort); - } catch (Throwable t) { - throw KubernetesClientException.launderThrowable(t); + } catch (Exception e) { + throw KubernetesClientException.launderThrowable(e); } } @@ -274,8 +274,8 @@ public ExecWatch exec(String... command) { try { URL url = getExecURLWithCommandParams(actualCommands); return setupConnectionToPod(url.toURI()); - } catch (Throwable t) { - throw KubernetesClientException.launderThrowable(forOperationType("exec"), t); + } catch (Exception e) { + throw KubernetesClientException.launderThrowable(forOperationType("exec"), e); } } @@ -284,8 +284,8 @@ public ExecWatch attach() { try { URL url = getAttachURL(); return setupConnectionToPod(url.toURI()); - } catch (Throwable t) { - throw KubernetesClientException.launderThrowable(forOperationType("attach"), t); + } catch (Exception e) { + throw KubernetesClientException.launderThrowable(forOperationType("attach"), e); } } @@ -591,7 +591,7 @@ public BytesLimitTerminateTimeTailPrettyLoggable usingTimestamps() { } public static String shellQuote(String value) { - return "'" + value.replace("'", "'\\\\''") + "'"; + return "'" + value.replace("'", "'\\''") + "'"; } @Override diff --git a/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/dsl/internal/uploadable/PodUploadTest.java b/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/dsl/internal/uploadable/PodUploadTest.java index 68caa55667..3a7d347954 100644 --- a/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/dsl/internal/uploadable/PodUploadTest.java +++ b/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/dsl/internal/uploadable/PodUploadTest.java @@ -179,6 +179,24 @@ void createExecCommandForUpload_withNormalFile_shouldCreateValidExecCommandForUp assertThat(result, equalTo("mkdir -p '/tmp/foo' && base64 -d - > '/tmp/foo/cp.log'")); } + @Test + void createExecCommandForUpload_withSingleQuoteInPath() { + // When + String result = PodUpload.createExecCommandForUpload("/tmp/fo'o/cp.log"); + + // Then + assertThat(result, equalTo("mkdir -p '/tmp/fo\'\\'\'o' && base64 -d - > '/tmp/fo\'\\'\'o/cp.log'")); + } + + @Test + void createExecCommandForUpload_withMultipleSingleQuotesInPath() { + // When + String result = PodUpload.createExecCommandForUpload("/tmp/f'o'o/c'p.log"); + + // Then + assertThat(result, equalTo("mkdir -p '/tmp/f\'\\'\'o\'\\'\'o' && base64 -d - > '/tmp/f\'\\'\'o\'\\'\'o/c\'\\'\'p.log'")); + } + void uploadFileAndVerify(PodUploadTester fileUploadMethodToTest) throws IOException, InterruptedException { this.operation = operation.file("/mock/dir/file"); WebSocket.Builder builder = Mockito.mock(WebSocket.Builder.class, Mockito.RETURNS_SELF); diff --git a/kubernetes-itests/src/test/java/io/fabric8/kubernetes/PodIT.java b/kubernetes-itests/src/test/java/io/fabric8/kubernetes/PodIT.java index 30f25414e6..5bc1c2db3c 100644 --- a/kubernetes-itests/src/test/java/io/fabric8/kubernetes/PodIT.java +++ b/kubernetes-itests/src/test/java/io/fabric8/kubernetes/PodIT.java @@ -274,6 +274,7 @@ void uploadFile() throws IOException { assertUploaded("pod-standard", tmpFile, "/tmp/toBeUploaded"); assertUploaded("pod-standard", tmpFile, "/tmp/001_special_!@#\\$^&(.mp4"); + assertUploaded("pod-standard", tmpFile, "/tmp/002'special"); } private void assertUploaded(String podName, final Path tmpFile, String filename) throws IOException {