CVE-2021-22538: Incorrect Default Permissions (CWE-276)
value: A privilege escalation vulnerability impacting the Google Exposure Notification Verification Server (versions prior to 0.23.1), allows an attacker who (1) has UserWrite permissions and (2) is using a carefully crafted request or malicious proxy, to create another user with higher privileges than their own. This occurs due to insufficient checks on the allowed set of permissions. The new user creation event would be captured in the Event Log.
CWE description: During installation, installed file permissions are set to allow anyone to modify those files.
CVSS v3 base score: 8.8
Published: 2021-03-31T21:15Z
Repository: https://github.com/google/exposure-notifications-verification-server
Language: Go
Files changed: pkg/rbac/rbac.go, pkg/rbac/rbac_test.go
Commit date: 2021-03-15 11:11:56 -0400
Commit message: Merge pull request from GHSA-5v95-v8c8-3rh6

This fixes a security vulnerability where, with a carefully crafted request or malicious proxy, a user with UserWrite permissions could create another user with higher privileges than their own due to insufficient checks on the allowed set of permissions.
Diff: diff --git a/pkg/rbac/rbac.go b/pkg/rbac/rbac.go
index 18c433bd..94a0c927 100644
--- a/pkg/rbac/rbac.go
+++ b/pkg/rbac/rbac.go
@@ -62,10 +62,20 @@ func Can(given Permission, target Permission) bool {
 // permissions. It verifies that the calling permission has a superset of all
 // provided permissions (to prevent privilege escalation).
 func CompileAndAuthorize(actorPermission Permission, toUpdate []Permission) (Permission, error) {
 	var permission Permission
 	for _, update := range toUpdate {
+		// Verify the provided permission is a known permission. This prevents a
+		// security vulnerability whereby a carefully crafted request is able to
+		// provide a value that correctly passes an the bitwise AND check and then
+		// modifies the target permission using OR to escalate privilege.
+		if _, ok := PermissionMap[update]; !ok {
+			if update != LegacyRealmAdmin && update != LegacyRealmUser {
+				return 0, fmt.Errorf("provided permission %v is unknown", update)
+			}
+		}
+
 		// Verify that the user making changes has the permissions they are trying
 		// to grant. It is not valid for someone to grant permissions larger than
 		// they currently have.
 		if !Can(actorPermission, update) {
 			return 0, fmt.Errorf("actor does not have all scopes which are being granted")
diff --git a/pkg/rbac/rbac_test.go b/pkg/rbac/rbac_test.go
index d5e3dd2e..d68bc01c 100644
--- a/pkg/rbac/rbac_test.go
+++ b/pkg/rbac/rbac_test.go
@@ -55,10 +55,34 @@ func TestRequiredPermissions(t *testing.T) {
 
 		if _, err := CompileAndAuthorize(0, []Permission{APIKeyRead}); err == nil {
 			t.Errorf("expected error")
 		}
 	})
+
+	t.Run("legacy_admin", func(t *testing.T) {
+		t.Parallel()
+
+		if _, err := CompileAndAuthorize(LegacyRealmAdmin, []Permission{LegacyRealmAdmin}); err != nil {
+			t.Error(err)
+		}
+	})
+
+	t.Run("legacy_user", func(t *testing.T) {
+		t.Parallel()
+
+		if _, err := CompileAndAuthorize(LegacyRealmAdmin, []Permission{LegacyRealmUser}); err != nil {
+			t.Error(err)
+		}
+	})
+
+	t.Run("escalate", func(t *testing.T) {
+		t.Parallel()
+
+		if _, err := CompileAndAuthorize(UserRead|UserWrite, []Permission{16383}); err == nil {
+			t.Errorf("expected error")
+		}
+	})
 }
 
 func TestImpliedBy(t *testing.T) {
 	t.Parallel()
 

Fixed code: 		// Verify the provided permission is a known permission. This prevents a
		// security vulnerability whereby a carefully crafted request is able to
		// provide a value that correctly passes an the bitwise AND check and then
		// modifies the target permission using OR to escalate privilege.
		if _, ok := PermissionMap[update]; !ok {
			if update != LegacyRealmAdmin && update != LegacyRealmUser {
				return 0, fmt.Errorf("provided permission %v is unknown", update)
			}
		}


	t.Run("legacy_admin", func(t *testing.T) {
		t.Parallel()

		if _, err := CompileAndAuthorize(LegacyRealmAdmin, []Permission{LegacyRealmAdmin}); err != nil {
			t.Error(err)
		}
	})

	t.Run("legacy_user", func(t *testing.T) {
		t.Parallel()

		if _, err := CompileAndAuthorize(LegacyRealmAdmin, []Permission{LegacyRealmUser}); err != nil {
			t.Error(err)
		}
	})

	t.Run("escalate", func(t *testing.T) {
		t.Parallel()

		if _, err := CompileAndAuthorize(UserRead|UserWrite, []Permission{16383}); err == nil {
			t.Errorf("expected error")
		}
	})