User able to view vault path despite the deny

I have applied the following vault policies

super-policy:
  - capabilities:
      - create
      - read
      - update
      - patch
      - delete
      - list
      - sudo
    path: /*
  - capabilities:
      - deny
    path: /specific
specific-policy:
  - capabilities:
      - create
      - read
      - update
      - patch
      - delete
      - list
    path: /specific
  - capabilities:
      - create
      - read
      - update
      - patch
      - delete
      - list
    path: /specific/*

A user has been assigned both the specific-policy and the super-policy.

Why is he able to see the specific path given that the super-policy has a deny capability` for this path?

update 1: each policy has been assigned to a group and the user I am talking about is a member of both groups FWIW

update 2: I have aggregated all the policies applied to the specific user here

path "/*" {
  capabilities = ["create", "delete", "list", "patch", "read", "sudo", "update"]
}

path "/specific" {
  capabilities = ["deny"]
}
path "/testing" {
  capabilities = ["create", "delete", "list", "patch", "read", "update"]
}

path "/testing/*" {
  capabilities = ["create", "delete", "list", "patch", "read", "update"]
}
path "/specific" {
  capabilities = ["create", "delete", "list", "patch", "read", "update"]
}

path "/specific/*" {
  capabilities = ["create", "delete", "list", "patch", "read", "update"]
}
path "/testing" {
  capabilities = ["list"]
}

path "/testing/*" {
  capabilities = ["list"]
}

Τhe user is able to

a) see the /specific path in the ui
b) perform a vault kv get -mount=specific foo/bar/lala

It’s kind of weird that you’re representing Vault policies as a custom YAML format, different from the native formats the product inherently supports.

Also your policies mention the path specific but then your question talks about the path restricted. Those paths are different so of course the deny does not apply.

That was a typo, updated to specific

I think you need to show us real Vault CLI commands or something, so we can see what is actually being invoked.

In the presented scenario, the user does NOT have access to specific, because it is denied. They do however have access to specific/*, which isn’t.

I tried to make the question a bit more clear, check my update whenever possible

Vault is behaving as expected given this policy input.

IIRC, visibility in the UI is controlled by a test for “Does this user have access to any sub-path within the particular mount.” - which in this case they do.

That’s going to translate into a request to either:

  • specific/foo/bar/lala (if a KV v1)
  • specific/data/foo/bar/lala (if a KV v2)

Neither of these are exact matches of the string specific, which is what the deny rule is for.

I imagine you probably want to deny specific/*.

Although, do be aware that such a deny can still be overridden by allowing access on specific/even-more-specific.

So this should deny access only to the /specific path and not to its subpaths. E.g. If I have this policy

path "/*" {
  capabilities = ["create", "delete", "list", "patch", "read", "sudo", "update"]
}

path "/specific" {
  capabilities = ["deny"]
}

I should be able to

a) view the /specific path in the UI
b) perform a `vault kv get -mount=specific foo/bar/lala