diff --git a/CHANGELOG.md b/CHANGELOG.md
index 521746d6c318..9057a35aa5d3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,56 @@
+## Fleet 4.48.0 (Apr 02, 2024)
+
+### Bug fixes
+
+## Changelog
+
+### Endpoint operations
+
+- Added integration with Google Calendar.
+
+* Fleet admins can enable Google Calendar integration by using a Google service account with domain-wide delegation.
+* Calendar integration is enabled at the team level for specific team policies.
+* If the policy is failing, a calendar event will be put on the host user's calendar for the 3rd Tuesday of the month.
+* During the event, Fleet will fire a webhook. IT admins should use this webhook to trigger a script or MDM command that will remediate the issue.
+
+- Reduced the number of 'Deadlock found' errors seen by the server when multiple hosts share the same UUID.
+- Removed outdated tooltips from UI.
+- Added hover states to clickable elements.
+- Added cross-platform check for duplicate MDM profiles names in batch set MDM profiles API.
+
+### Device management (MDM)
+
+- Added Windows MDM support to the `osquery-perf` host-simulation command.
+- Added a missing database index to the MDM Windows enrollments table that will improve performance at scale.
+- Migrate MDM-related endpoints to new paths, deprecating (but still supporting indefinitely) the old endpoints.
+- Adds API functionality for creating DDM declarations, both individually and as a batch.
+- Added DDM activities to the fleet UI.
+- Added the `enable_release_device_manually` configuration setting for a team and no team. **Note** that the macOS automatic enrollment profile cannot set the `await_device_configured` option anymore, this setting is controlled by Fleet via the new `enable_release_device_manually` option.
+- Automatically release a macOS DEP-enrolled device after enrollment commands and profiles have been delivered, unless `enable_release_device_manually` is set to `true`.
+
+### Vulnerability management
+
+- Added Visual Studio extensions to Fleet's software inventory.
+
+### Bug fixes
+
+- Fixed a bug where valid MDM enrollments would show up as unmanaged (EnrollmentState 3).
+- Fixed flash message from closing when a modal closes.
+- Fixed a bug where OS version information would not get detected on Windows Server 2019.
+- Fixed issue where getting host details failed when attempting to read the host's bitlocker status from the datastore.
+- Fixed false negative vulnerabilities on macOS Homebrew python packages.
+- Fixed styling of live query disabled warning.
+- Fixed issue where Windows MDM profile processing was skipping `<Add>` commands.
+- Fixed UI's ability to bulk delete hosts when "All teams" is selected.
+- Fixed error state rendering on the global Host status expiry settings page, fix error state alignment for tooltip-wrapper field labels across organization settings.
+- Fixed `GET fleet/os_versions` and `GET fleet/os_versions/[id]` so team users no longer have access to os versions on hosts from other teams.
+- `fleetctl gitops` now batch processes queries and policies.
+- Fixed UI bug to render the query platform correctly for queries imported from the standard query library.
+- Fixed issue where microsoft edge was not reporting vulnerabilities.
+- Fixed a bug where all Windows MDM enrollments were detected as automatic.
+- Fixed a bug where `null` or excluded `smtp_settings` caused a UI 500.
+- Fixed query reports so they reset when there is a change to the selected platform or selected minimum osquery version.
+- Fixed live query sort of sql result sort for both string and numerical columns.
 ## Fleet 4.47.3 (Mar 26, 2024)
 
 ### Bug fixes
diff --git a/charts/fleet/Chart.yaml b/charts/fleet/Chart.yaml
index f0558d302ea8..792846d9bb0d 100644
--- a/charts/fleet/Chart.yaml
+++ b/charts/fleet/Chart.yaml
@@ -8,7 +8,7 @@ version: v6.0.2
 home: https://github.com/fleetdm/fleet
 sources:
   - https://github.com/fleetdm/fleet.git
-appVersion: v4.47.3
+appVersion: v4.48.0
 dependencies:
   - name: mysql
     condition: mysql.enabled
diff --git a/charts/fleet/values.yaml b/charts/fleet/values.yaml
index af4099168f08..f553a50326d4 100644
--- a/charts/fleet/values.yaml
+++ b/charts/fleet/values.yaml
@@ -2,7 +2,7 @@
 # All settings related to how Fleet is deployed in Kubernetes
 hostName: fleet.localhost
 replicas: 3 # The number of Fleet instances to deploy
-imageTag: v4.47.3 # Version of Fleet to deploy
+imageTag: v4.48.0 # Version of Fleet to deploy
 podAnnotations: {} # Additional annotations to add to the Fleet pod
 serviceAccountAnnotations: {} # Additional annotations to add to the Fleet service account
 resources:
diff --git a/infrastructure/dogfood/terraform/aws/variables.tf b/infrastructure/dogfood/terraform/aws/variables.tf
index 991c9135ded0..cb0d1593dec0 100644
--- a/infrastructure/dogfood/terraform/aws/variables.tf
+++ b/infrastructure/dogfood/terraform/aws/variables.tf
@@ -56,7 +56,7 @@ variable "database_name" {
 
 variable "fleet_image" {
   description = "the name of the container image to run"
-  default     = "fleetdm/fleet:v4.47.3"
+  default     = "fleetdm/fleet:v4.48.0"
 }
 
 variable "software_inventory" {
diff --git a/infrastructure/dogfood/terraform/gcp/variables.tf b/infrastructure/dogfood/terraform/gcp/variables.tf
index b3cddde5ca3a..afe4e46243ff 100644
--- a/infrastructure/dogfood/terraform/gcp/variables.tf
+++ b/infrastructure/dogfood/terraform/gcp/variables.tf
@@ -68,5 +68,5 @@ variable "redis_mem" {
 }
 
 variable "image" {
-  default = "fleet:v4.47.3"
+  default = "fleet:v4.48.0"
 }
diff --git a/terraform/byo-vpc/README.md b/terraform/byo-vpc/README.md
index 27920c181930..0cc44fdec0a8 100644
--- a/terraform/byo-vpc/README.md
+++ b/terraform/byo-vpc/README.md
@@ -33,7 +33,7 @@ No requirements.
 |------|-------------|------|---------|:--------:|
 | <a name="input_alb_config"></a> [alb\_config](#input\_alb\_config) | n/a | <pre>object({<br>    name                 = optional(string, "fleet")<br>    subnets              = list(string)<br>    security_groups      = optional(list(string), [])<br>    access_logs          = optional(map(string), {})<br>    certificate_arn      = string<br>    allowed_cidrs        = optional(list(string), ["0.0.0.0/0"])<br>    allowed_ipv6_cidrs   = optional(list(string), ["::/0"])<br>    egress_cidrs         = optional(list(string), ["0.0.0.0/0"])<br>    egress_ipv6_cidrs    = optional(list(string), ["::/0"])<br>    extra_target_groups  = optional(any, [])<br>    https_listener_rules = optional(any, [])<br>    tls_policy           = optional(string, "ELBSecurityPolicy-TLS-1-2-2017-01")<br>    idle_timeout         = optional(number, 60)<br>  })</pre> | n/a | yes |
 | <a name="input_ecs_cluster"></a> [ecs\_cluster](#input\_ecs\_cluster) | The config for the terraform-aws-modules/ecs/aws module | <pre>object({<br>    autoscaling_capacity_providers = optional(any, {})<br>    cluster_configuration = optional(any, {<br>      execute_command_configuration = {<br>        logging = "OVERRIDE"<br>        log_configuration = {<br>          cloud_watch_log_group_name = "/aws/ecs/aws-ec2"<br>        }<br>      }<br>    })<br>    cluster_name = optional(string, "fleet")<br>    cluster_settings = optional(map(string), {<br>      "name" : "containerInsights",<br>      "value" : "enabled",<br>    })<br>    create                                = optional(bool, true)<br>    default_capacity_provider_use_fargate = optional(bool, true)<br>    fargate_capacity_providers = optional(any, {<br>      FARGATE = {<br>        default_capacity_provider_strategy = {<br>          weight = 100<br>        }<br>      }<br>      FARGATE_SPOT = {<br>        default_capacity_provider_strategy = {<br>          weight = 0<br>        }<br>      }<br>    })<br>    tags = optional(map(string))<br>  })</pre> | <pre>{<br>  "autoscaling_capacity_providers": {},<br>  "cluster_configuration": {<br>    "execute_command_configuration": {<br>      "log_configuration": {<br>        "cloud_watch_log_group_name": "/aws/ecs/aws-ec2"<br>      },<br>      "logging": "OVERRIDE"<br>    }<br>  },<br>  "cluster_name": "fleet",<br>  "cluster_settings": {<br>    "name": "containerInsights",<br>    "value": "enabled"<br>  },<br>  "create": true,<br>  "default_capacity_provider_use_fargate": true,<br>  "fargate_capacity_providers": {<br>    "FARGATE": {<br>      "default_capacity_provider_strategy": {<br>        "weight": 100<br>      }<br>    },<br>    "FARGATE_SPOT": {<br>      "default_capacity_provider_strategy": {<br>        "weight": 0<br>      }<br>    }<br>  },<br>  "tags": {}<br>}</pre> | no |
-| <a name="input_fleet_config"></a> [fleet\_config](#input\_fleet\_config) | The configuration object for Fleet itself. Fields that default to null will have their respective resources created if not specified. | <pre>object({<br>    mem                          = optional(number, 4096)<br>    cpu                          = optional(number, 512)<br>    image                        = optional(string, "fleetdm/fleet:v4.47.3")<br>    family                       = optional(string, "fleet")<br>    sidecars                     = optional(list(any), [])<br>    depends_on                   = optional(list(any), [])<br>    mount_points                 = optional(list(any), [])<br>    volumes                      = optional(list(any), [])<br>    extra_environment_variables  = optional(map(string), {})<br>    extra_iam_policies           = optional(list(string), [])<br>    extra_execution_iam_policies = optional(list(string), [])<br>    extra_secrets                = optional(map(string), {})<br>    security_groups              = optional(list(string), null)<br>    security_group_name          = optional(string, "fleet")<br>    iam_role_arn                 = optional(string, null)<br>    service = optional(object({<br>      name = optional(string, "fleet")<br>      }), {<br>      name = "fleet"<br>    })<br>    database = optional(object({<br>      password_secret_arn = string<br>      user                = string<br>      database            = string<br>      address             = string<br>      rr_address          = optional(string, null)<br>      }), {<br>      password_secret_arn = null<br>      user                = null<br>      database            = null<br>      address             = null<br>      rr_address          = null<br>    })<br>    redis = optional(object({<br>      address = string<br>      use_tls = optional(bool, true)<br>      }), {<br>      address = null<br>      use_tls = true<br>    })<br>    awslogs = optional(object({<br>      name      = optional(string, null)<br>      region    = optional(string, null)<br>      create    = optional(bool, true)<br>      prefix    = optional(string, "fleet")<br>      retention = optional(number, 5)<br>      }), {<br>      name      = null<br>      region    = null<br>      prefix    = "fleet"<br>      retention = 5<br>    })<br>    loadbalancer = optional(object({<br>      arn = string<br>      }), {<br>      arn = null<br>    })<br>    extra_load_balancers = optional(list(any), [])<br>    networking = optional(object({<br>      subnets         = list(string)<br>      security_groups = optional(list(string), null)<br>      }), {<br>      subnets         = null<br>      security_groups = null<br>    })<br>    autoscaling = optional(object({<br>      max_capacity                 = optional(number, 5)<br>      min_capacity                 = optional(number, 1)<br>      memory_tracking_target_value = optional(number, 80)<br>      cpu_tracking_target_value    = optional(number, 80)<br>      }), {<br>      max_capacity                 = 5<br>      min_capacity                 = 1<br>      memory_tracking_target_value = 80<br>      cpu_tracking_target_value    = 80<br>    })<br>    iam = optional(object({<br>      role = optional(object({<br>        name        = optional(string, "fleet-role")<br>        policy_name = optional(string, "fleet-iam-policy")<br>        }), {<br>        name        = "fleet-role"<br>        policy_name = "fleet-iam-policy"<br>      })<br>      execution = optional(object({<br>        name        = optional(string, "fleet-execution-role")<br>        policy_name = optional(string, "fleet-execution-role")<br>        }), {<br>        name        = "fleet-execution-role"<br>        policy_name = "fleet-iam-policy-execution"<br>      })<br>      }), {<br>      name = "fleetdm-execution-role"<br>    })<br>  })</pre> | <pre>{<br>  "autoscaling": {<br>    "cpu_tracking_target_value": 80,<br>    "max_capacity": 5,<br>    "memory_tracking_target_value": 80,<br>    "min_capacity": 1<br>  },<br>  "awslogs": {<br>    "create": true,<br>    "name": null,<br>    "prefix": "fleet",<br>    "region": null,<br>    "retention": 5<br>  },<br>  "cpu": 256,<br>  "database": {<br>    "address": null,<br>    "database": null,<br>    "password_secret_arn": null,<br>    "rr_address": null,<br>    "user": null<br>  },<br>  "depends_on": [],<br>  "extra_environment_variables": {},<br>  "extra_execution_iam_policies": [],<br>  "extra_iam_policies": [],<br>  "extra_load_balancers": [],<br>  "extra_secrets": {},<br>  "family": "fleet",<br>  "iam": {<br>    "execution": {<br>      "name": "fleet-execution-role",<br>      "policy_name": "fleet-iam-policy-execution"<br>    },<br>    "role": {<br>      "name": "fleet-role",<br>      "policy_name": "fleet-iam-policy"<br>    }<br>  },<br>  "iam_role_arn": null,<br>  "image": "fleetdm/fleet:v4.31.1",<br>  "loadbalancer": {<br>    "arn": null<br>  },<br>  "mem": 512,<br>  "mount_points": [],<br>  "networking": {<br>    "security_groups": null,<br>    "subnets": null<br>  },<br>  "redis": {<br>    "address": null,<br>    "use_tls": true<br>  },<br>  "security_group_name": "fleet",<br>  "security_groups": null,<br>  "service": {<br>    "name": "fleet"<br>  },<br>  "sidecars": [],<br>  "volumes": []<br>}</pre> | no |
+| <a name="input_fleet_config"></a> [fleet\_config](#input\_fleet\_config) | The configuration object for Fleet itself. Fields that default to null will have their respective resources created if not specified. | <pre>object({<br>    mem                          = optional(number, 4096)<br>    cpu                          = optional(number, 512)<br>    image                        = optional(string, "fleetdm/fleet:v4.48.0")<br>    family                       = optional(string, "fleet")<br>    sidecars                     = optional(list(any), [])<br>    depends_on                   = optional(list(any), [])<br>    mount_points                 = optional(list(any), [])<br>    volumes                      = optional(list(any), [])<br>    extra_environment_variables  = optional(map(string), {})<br>    extra_iam_policies           = optional(list(string), [])<br>    extra_execution_iam_policies = optional(list(string), [])<br>    extra_secrets                = optional(map(string), {})<br>    security_groups              = optional(list(string), null)<br>    security_group_name          = optional(string, "fleet")<br>    iam_role_arn                 = optional(string, null)<br>    service = optional(object({<br>      name = optional(string, "fleet")<br>      }), {<br>      name = "fleet"<br>    })<br>    database = optional(object({<br>      password_secret_arn = string<br>      user                = string<br>      database            = string<br>      address             = string<br>      rr_address          = optional(string, null)<br>      }), {<br>      password_secret_arn = null<br>      user                = null<br>      database            = null<br>      address             = null<br>      rr_address          = null<br>    })<br>    redis = optional(object({<br>      address = string<br>      use_tls = optional(bool, true)<br>      }), {<br>      address = null<br>      use_tls = true<br>    })<br>    awslogs = optional(object({<br>      name      = optional(string, null)<br>      region    = optional(string, null)<br>      create    = optional(bool, true)<br>      prefix    = optional(string, "fleet")<br>      retention = optional(number, 5)<br>      }), {<br>      name      = null<br>      region    = null<br>      prefix    = "fleet"<br>      retention = 5<br>    })<br>    loadbalancer = optional(object({<br>      arn = string<br>      }), {<br>      arn = null<br>    })<br>    extra_load_balancers = optional(list(any), [])<br>    networking = optional(object({<br>      subnets         = list(string)<br>      security_groups = optional(list(string), null)<br>      }), {<br>      subnets         = null<br>      security_groups = null<br>    })<br>    autoscaling = optional(object({<br>      max_capacity                 = optional(number, 5)<br>      min_capacity                 = optional(number, 1)<br>      memory_tracking_target_value = optional(number, 80)<br>      cpu_tracking_target_value    = optional(number, 80)<br>      }), {<br>      max_capacity                 = 5<br>      min_capacity                 = 1<br>      memory_tracking_target_value = 80<br>      cpu_tracking_target_value    = 80<br>    })<br>    iam = optional(object({<br>      role = optional(object({<br>        name        = optional(string, "fleet-role")<br>        policy_name = optional(string, "fleet-iam-policy")<br>        }), {<br>        name        = "fleet-role"<br>        policy_name = "fleet-iam-policy"<br>      })<br>      execution = optional(object({<br>        name        = optional(string, "fleet-execution-role")<br>        policy_name = optional(string, "fleet-execution-role")<br>        }), {<br>        name        = "fleet-execution-role"<br>        policy_name = "fleet-iam-policy-execution"<br>      })<br>      }), {<br>      name = "fleetdm-execution-role"<br>    })<br>  })</pre> | <pre>{<br>  "autoscaling": {<br>    "cpu_tracking_target_value": 80,<br>    "max_capacity": 5,<br>    "memory_tracking_target_value": 80,<br>    "min_capacity": 1<br>  },<br>  "awslogs": {<br>    "create": true,<br>    "name": null,<br>    "prefix": "fleet",<br>    "region": null,<br>    "retention": 5<br>  },<br>  "cpu": 256,<br>  "database": {<br>    "address": null,<br>    "database": null,<br>    "password_secret_arn": null,<br>    "rr_address": null,<br>    "user": null<br>  },<br>  "depends_on": [],<br>  "extra_environment_variables": {},<br>  "extra_execution_iam_policies": [],<br>  "extra_iam_policies": [],<br>  "extra_load_balancers": [],<br>  "extra_secrets": {},<br>  "family": "fleet",<br>  "iam": {<br>    "execution": {<br>      "name": "fleet-execution-role",<br>      "policy_name": "fleet-iam-policy-execution"<br>    },<br>    "role": {<br>      "name": "fleet-role",<br>      "policy_name": "fleet-iam-policy"<br>    }<br>  },<br>  "iam_role_arn": null,<br>  "image": "fleetdm/fleet:v4.31.1",<br>  "loadbalancer": {<br>    "arn": null<br>  },<br>  "mem": 512,<br>  "mount_points": [],<br>  "networking": {<br>    "security_groups": null,<br>    "subnets": null<br>  },<br>  "redis": {<br>    "address": null,<br>    "use_tls": true<br>  },<br>  "security_group_name": "fleet",<br>  "security_groups": null,<br>  "service": {<br>    "name": "fleet"<br>  },<br>  "sidecars": [],<br>  "volumes": []<br>}</pre> | no |
 | <a name="input_migration_config"></a> [migration\_config](#input\_migration\_config) | The configuration object for Fleet's migration task. | <pre>object({<br>    mem = number<br>    cpu = number<br>  })</pre> | <pre>{<br>  "cpu": 1024,<br>  "mem": 2048<br>}</pre> | no |
 | <a name="input_rds_config"></a> [rds\_config](#input\_rds\_config) | The config for the terraform-aws-modules/rds-aurora/aws module | <pre>object({<br>    name                            = optional(string, "fleet")<br>    engine_version                  = optional(string, "8.0.mysql_aurora.3.02.2")<br>    instance_class                  = optional(string, "db.t4g.large")<br>    subnets                         = optional(list(string), [])<br>    allowed_security_groups         = optional(list(string), [])<br>    allowed_cidr_blocks             = optional(list(string), [])<br>    apply_immediately               = optional(bool, true)<br>    monitoring_interval             = optional(number, 10)<br>    db_parameter_group_name         = optional(string)<br>    db_parameters                   = optional(map(string), {})<br>    db_cluster_parameter_group_name = optional(string)<br>    db_cluster_parameters           = optional(map(string), {})<br>    enabled_cloudwatch_logs_exports = optional(list(string), [])<br>    master_username                 = optional(string, "fleet")<br>    snapshot_identifier             = optional(string)<br>    cluster_tags                    = optional(map(string), {})<br>    preferred_maintenance_window    = optional(string, "thu:23:00-fri:00:00")<br>  })</pre> | <pre>{<br>  "allowed_cidr_blocks": [],<br>  "allowed_security_groups": [],<br>  "apply_immediately": true,<br>  "cluster_tags": {},<br>  "db_cluster_parameter_group_name": null,<br>  "db_cluster_parameters": {},<br>  "db_parameter_group_name": null,<br>  "db_parameters": {},<br>  "enabled_cloudwatch_logs_exports": [],<br>  "engine_version": "8.0.mysql_aurora.3.02.2",<br>  "instance_class": "db.t4g.large",<br>  "master_username": "fleet",<br>  "monitoring_interval": 10,<br>  "name": "fleet",<br>  "preferred_maintenance_window": "thu:23:00-fri:00:00",<br>  "snapshot_identifier": null,<br>  "subnets": []<br>}</pre> | no |
 | <a name="input_redis_config"></a> [redis\_config](#input\_redis\_config) | n/a | <pre>object({<br>    name                          = optional(string, "fleet")<br>    replication_group_id          = optional(string)<br>    elasticache_subnet_group_name = optional(string, "")<br>    allowed_security_group_ids    = optional(list(string), [])<br>    subnets                       = list(string)<br>    allowed_cidrs                 = list(string)<br>    availability_zones            = optional(list(string), [])<br>    cluster_size                  = optional(number, 3)<br>    instance_type                 = optional(string, "cache.m5.large")<br>    apply_immediately             = optional(bool, true)<br>    automatic_failover_enabled    = optional(bool, false)<br>    engine_version                = optional(string, "6.x")<br>    family                        = optional(string, "redis6.x")<br>    at_rest_encryption_enabled    = optional(bool, true)<br>    transit_encryption_enabled    = optional(bool, true)<br>    parameter = optional(list(object({<br>      name  = string<br>      value = string<br>    })), [])<br>    log_delivery_configuration = optional(list(map(any)), [])<br>    tags                       = optional(map(string), {})<br>  })</pre> | <pre>{<br>  "allowed_cidrs": null,<br>  "allowed_security_group_ids": [],<br>  "apply_immediately": true,<br>  "at_rest_encryption_enabled": true,<br>  "automatic_failover_enabled": false,<br>  "availability_zones": [],<br>  "cluster_size": 3,<br>  "elasticache_subnet_group_name": "",<br>  "engine_version": "6.x",<br>  "family": "redis6.x",<br>  "instance_type": "cache.m5.large",<br>  "log_delivery_configuration": [],<br>  "name": "fleet",<br>  "parameter": [],<br>  "replication_group_id": null,<br>  "subnets": null,<br>  "tags": {},<br>  "transit_encryption_enabled": true<br>}</pre> | no |
diff --git a/terraform/byo-vpc/byo-db/byo-ecs/variables.tf b/terraform/byo-vpc/byo-db/byo-ecs/variables.tf
index 367832f457de..20b8249bff7c 100644
--- a/terraform/byo-vpc/byo-db/byo-ecs/variables.tf
+++ b/terraform/byo-vpc/byo-db/byo-ecs/variables.tf
@@ -13,7 +13,7 @@ variable "fleet_config" {
   type = object({
     mem                          = optional(number, 4096)
     cpu                          = optional(number, 512)
-    image                        = optional(string, "fleetdm/fleet:v4.47.3")
+    image                        = optional(string, "fleetdm/fleet:v4.48.0")
     family                       = optional(string, "fleet")
     sidecars                     = optional(list(any), [])
     depends_on                   = optional(list(any), [])
diff --git a/terraform/byo-vpc/byo-db/variables.tf b/terraform/byo-vpc/byo-db/variables.tf
index 7c8ff1738f8a..88cb0c03fb8c 100644
--- a/terraform/byo-vpc/byo-db/variables.tf
+++ b/terraform/byo-vpc/byo-db/variables.tf
@@ -74,7 +74,7 @@ variable "fleet_config" {
   type = object({
     mem                          = optional(number, 4096)
     cpu                          = optional(number, 512)
-    image                        = optional(string, "fleetdm/fleet:v4.47.3")
+    image                        = optional(string, "fleetdm/fleet:v4.48.0")
     family                       = optional(string, "fleet")
     sidecars                     = optional(list(any), [])
     depends_on                   = optional(list(any), [])
diff --git a/terraform/byo-vpc/example/main.tf b/terraform/byo-vpc/example/main.tf
index daefdcbc542e..28311ecee138 100644
--- a/terraform/byo-vpc/example/main.tf
+++ b/terraform/byo-vpc/example/main.tf
@@ -17,7 +17,7 @@ provider "aws" {
 }
 
 locals {
-  fleet_image = "fleetdm/fleet:v4.47.3"
+  fleet_image = "fleetdm/fleet:v4.48.0"
   domain_name = "example.com"
 }
 
diff --git a/terraform/byo-vpc/variables.tf b/terraform/byo-vpc/variables.tf
index f74561183feb..4ad249b0b03d 100644
--- a/terraform/byo-vpc/variables.tf
+++ b/terraform/byo-vpc/variables.tf
@@ -167,7 +167,7 @@ variable "fleet_config" {
   type = object({
     mem                          = optional(number, 4096)
     cpu                          = optional(number, 512)
-    image                        = optional(string, "fleetdm/fleet:v4.47.3")
+    image                        = optional(string, "fleetdm/fleet:v4.48.0")
     family                       = optional(string, "fleet")
     sidecars                     = optional(list(any), [])
     depends_on                   = optional(list(any), [])
diff --git a/terraform/example/main.tf b/terraform/example/main.tf
index 5a2fcf5491fb..04b2691900e2 100644
--- a/terraform/example/main.tf
+++ b/terraform/example/main.tf
@@ -59,8 +59,8 @@ module "fleet" {
 
   fleet_config = {
     # To avoid pull-rate limiting from dockerhub, consider using our quay.io mirror
-    # for the Fleet image. e.g. "quay.io/fleetdm/fleet:v4.47.3"
-    image = "fleetdm/fleet:v4.47.3" # override default to deploy the image you desire
+    # for the Fleet image. e.g. "quay.io/fleetdm/fleet:v4.48.0"
+    image = "fleetdm/fleet:v4.48.0" # override default to deploy the image you desire
     # See https://fleetdm.com/docs/deploy/reference-architectures#aws for appropriate scaling
     # memory and cpu.
     autoscaling = {
diff --git a/terraform/variables.tf b/terraform/variables.tf
index e8b6e29b67dd..a5cb956185c2 100644
--- a/terraform/variables.tf
+++ b/terraform/variables.tf
@@ -215,7 +215,7 @@ variable "fleet_config" {
   type = object({
     mem                          = optional(number, 4096)
     cpu                          = optional(number, 512)
-    image                        = optional(string, "fleetdm/fleet:v4.47.3")
+    image                        = optional(string, "fleetdm/fleet:v4.48.0")
     family                       = optional(string, "fleet")
     sidecars                     = optional(list(any), [])
     depends_on                   = optional(list(any), [])
diff --git a/tools/fleetctl-npm/package.json b/tools/fleetctl-npm/package.json
index 19de34bf6c7c..80a5a278cbef 100644
--- a/tools/fleetctl-npm/package.json
+++ b/tools/fleetctl-npm/package.json
@@ -1,6 +1,6 @@
 {
   "name": "fleetctl",
-  "version": "v4.47.3",
+  "version": "v4.48.0",
   "description": "Installer for the fleetctl CLI tool",
   "bin": {
     "fleetctl": "./run.js"
diff --git a/tools/release/publish_release.sh b/tools/release/publish_release.sh
index e4bfe6e99e47..78d67e3693bc 100755
--- a/tools/release/publish_release.sh
+++ b/tools/release/publish_release.sh
@@ -429,17 +429,17 @@ if [ "$force" = "false" ]; then
 fi
 # 4.47.2
 start_milestone="${start_version:1}"
-# 4.47.3
+# 4.48.0
 target_milestone="${next_ver:1}"
 # 79
 target_milestone_number=`gh api repos/:owner/:repo/milestones | jq -r ".[] | select(.title==\"$target_milestone\") | .number"`
-# patch-fleet-v4.47.3
+# patch-fleet-v4.48.0
 target_patch_branch="patch-fleet-$next_ver"
 if [[ "$main_release" == "true" ]]; then
     target_patch_branch="prepare-fleet-$next_ver"
 fi
 
-# fleet-v4.47.3
+# fleet-v4.48.0
 next_tag="fleet-$next_ver"
 
 if [ "$print_info" = "true" ]; then