diff options
author | Martin Polden <mpolden@mpolden.no> | 2018-03-01 13:44:20 +0100 |
---|---|---|
committer | Martin Polden <mpolden@mpolden.no> | 2018-03-02 09:13:10 +0100 |
commit | 40823dad0a3b0aeee9108db084a08933df19ad23 (patch) | |
tree | 1f1ffb3b40b4c685cfdcc4c75b1928c1581a48eb /node-repository | |
parent | c164479ddba82944b0837d428ef6313576968550 (diff) |
Fail gracefully on path traversal attempts
Diffstat (limited to 'node-repository')
2 files changed, 10 insertions, 0 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/Authorizer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/Authorizer.java index 327974599c3..55a1a1e620d 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/Authorizer.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/Authorizer.java @@ -54,10 +54,17 @@ public class Authorizer implements BiPredicate<Principal, URI> { /** Returns whether principal can access node identified by hostname */ private boolean canAccess(String hostname, Principal principal) { + // Ignore potential path traversal. Node repository happily passes arguments unsanitized all the way down to + // curator... + if (hostname.chars().allMatch(c -> c == '.')) { + return false; + } + // Node can always access itself if (principal.getName().equals(hostname)) { return true; } + // Parent node can access its children return nodeRepository.getNode(hostname) .flatMap(Node::parentHostname) diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/AuthorizerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/AuthorizerTest.java index 811db071969..097c8d92165 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/AuthorizerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/AuthorizerTest.java @@ -69,6 +69,9 @@ public class AuthorizerTest { assertFalse(authorized("node1", "/nodes/v2/node/node2")); assertFalse(authorized("node1", "/nodes/v2/state/dirty/")); assertFalse(authorized("node1", "/nodes/v2/state/dirty/node2")); + // Path traversal fails gracefully + assertFalse(authorized("node1", "/nodes/v2/node/.")); + assertFalse(authorized("node1", "/nodes/v2/node/..")); assertFalse(authorized("node1", "/nodes/v2/acl/node2")); assertFalse(authorized("node1", "/nodes/v2/node/?parentHost=node2")); // Node resource always takes precedence over filter |