Best Practices

AWS AppConfig Dynamic Config Security

AppConfig ships configuration changes to running applications in seconds. That makes it a powerful tool and a compelling target. Here is how to run AppConfig safely.

Nayan Dey
Senior Security Engineer
7 min read

AWS AppConfig is one of those services that starts innocent and ends up operating as a production control plane. You start by using it for feature flags. A quarter later it is holding connection strings. A year later your entire runtime configuration is in AppConfig and any change to any profile is live in production in under sixty seconds. That is the power of AppConfig, and it is also the threat model.

This post is about how to run AppConfig so that the speed and flexibility do not quietly become an attack surface. I am going to assume you have used AppConfig enough to know what applications, environments, and configuration profiles are. If not, the AWS docs cover the basics.

What AppConfig changes in the threat model

Traditional configuration management has a deploy step. You update a config file, you push a release, the change goes through the deploy pipeline. Your CI/CD controls are your config controls.

AppConfig decouples configuration from deploy. A configuration profile can be updated via the StartDeployment API at any time, and the change propagates to running applications via the AppConfig agent or extension within seconds. If an attacker obtains permissions to update a profile and trigger a deployment, they can change application behavior in production without touching your CI/CD pipeline, without producing a Git commit, without a code review, and without running any of the signing or scanning that your deploy pipeline does.

This is by design. AppConfig is for configuration that needs to change faster than your deploy cadence. But it means the IAM permissions that control AppConfig deployments are production deployment permissions, and most organizations treat them as ordinary API permissions.

The IAM actions that matter

The permissions to watch are appconfig:StartDeployment, appconfig:CreateHostedConfigurationVersion, appconfig:UpdateConfigurationProfile, and appconfig:CreateDeploymentStrategy. Any principal with these permissions can change production application behavior through AppConfig.

The audit question: who has these permissions in your production accounts? In most organizations, the answer is something like "everyone in the developer role because we grant appconfig:* to make it easy to iterate." This is the same category of mistake as granting iam:* to developers. Fix it.

The pattern that works:

  1. Developers can create configuration versions in non-production environments. They cannot call StartDeployment in production.
  2. A dedicated release role in each production account can call StartDeployment, but only with specific deployment strategies that include a bake time and a rollback trigger.
  3. A break-glass role exists for emergency fast deployments, gated by MFA and alerting.

Enforce via SCP that appconfig:StartDeployment in production accounts is only allowed from the release role, and that the release role's trust policy only accepts sessions originating from the deployment pipeline's OIDC provider.

Deployment strategies as safety rails

AppConfig deployment strategies define the rollout profile: how fast, what bake time, what growth factor, what failure threshold. A badly chosen strategy is a way to push a bad configuration to one hundred percent of production instantly. A well-chosen strategy bakes at each stage and rolls back on alarm.

AWS ships several predefined strategies: AppConfig.AllAtOnce, AppConfig.Linear50PercentEvery30Seconds, AppConfig.Canary10Percent20Minutes. The predefined strategies are convenient but do not have bake time appropriate for most production workloads. The Canary10Percent20Minutes strategy is the closest to safe; AllAtOnce should essentially never be used in production.

For production, define your own deployment strategies: start at one percent, wait ten minutes, bake for forty minutes, grow to twenty-five percent, wait twenty minutes, then to one hundred percent. Attach CloudWatch alarms as deployment triggers. If any of the alarms fire during the deployment, AppConfig rolls back automatically.

Enforce via SCP that production deployments can only use a specific list of approved deployment strategy ARNs. Developers cannot introduce a new strategy with no bake time just because they are in a hurry.

Configuration validators

AppConfig supports validators: AWS Lambda functions or JSON Schema documents that run against a configuration before it deploys. If the validator rejects, the deployment fails. This is the primary defense against malformed configurations reaching production.

Two validator patterns worth adopting:

Schema validator. Attach a JSON Schema validator to every structured configuration profile. The schema describes the required fields, their types, and their valid ranges. An attacker who manages to call CreateHostedConfigurationVersion with a malformed payload triggers a deployment failure rather than a production incident.

Lambda semantic validator. For configurations whose correctness cannot be captured in JSON Schema (references to specific resources, flag dependencies, feature flag sanity checks), attach a Lambda validator that runs domain-specific validation. The validator function has its own IAM role and logs every validation decision to CloudWatch, which gives you an audit trail of every proposed configuration whether or not it was accepted.

Require validators on every production configuration profile. An unvalidated profile is a profile that will eventually ship a bad configuration to production at the worst possible moment.

Feature flags specifically

AppConfig's feature flag type (introduced in 2022) has additional semantics: each flag has a name, an enabled state, and optional attributes. The risk profile is the same as freeform configuration, but the surface is more structured and the mitigations are more targeted.

Do not put secrets in flag attributes. Flag attributes are visible to every application that fetches the flag, logged by the AppConfig agent in debug mode, and often end up in application logs via feature-flag evaluation logging libraries. Flag attributes are public within your application. Keep secrets in Secrets Manager.

Deprecate flags aggressively. A feature flag that has been enabled for three years is not a feature flag, it is dead code with a runtime switch. Every flag that has not been toggled in ninety days should go on a deprecation list. Audit and remove regularly. I have seen AppConfig applications with four hundred feature flags, three hundred and fifty of which had not been evaluated meaningfully in months.

Use flag versioning. Flag version history lets you see who changed what and when, with a full audit trail. Enable versioning on every feature-flag profile and retain versions for at least a year.

Agent and extension deployment

Applications retrieve AppConfig configurations via the AppConfig agent (a sidecar or daemon) or the AppConfig Lambda extension. Either way, the retrieval role is the application's IAM role, which needs appconfig:GetLatestConfiguration and appconfig:StartConfigurationSession on the specific configuration profile.

The minimal policy is narrow:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["appconfig:GetLatestConfiguration", "appconfig:StartConfigurationSession"],
      "Resource": "arn:aws:appconfig:us-east-1:123456789012:application/abc/environment/prod/configuration/my-flags"
    }
  ]
}

No appconfig:*. No wildcards. Specific configuration ARNs only. If the application should not be allowed to fetch a particular profile, the role does not grant access. This is per-environment and per-profile scoping.

CloudTrail and drift detection

Every configuration deployment generates a StartDeployment CloudTrail event with the deployment strategy ARN, the configuration version, and the principal that triggered it. Send these events to an EventBridge rule that posts to a dedicated Slack or Teams channel. If an unexpected principal triggers a production deployment, the alert fires before anyone has to go looking.

For high-sensitivity configurations (authorization rules, rate limits, trust relationships), add a second alarm: any change to the configuration profile's content generates an EventBridge event with the old and new versions, and a human reviews the diff within the hour. This is expensive in terms of human attention and entirely justified for configuration that controls security behavior.

How Safeguard Helps

Safeguard tracks every AppConfig application, environment, and configuration profile across your AWS organization, identifies profiles without validators, and flags deployment strategies that lack a bake time or rollback trigger. We correlate StartDeployment events to the originating principal and alert when production deployments are triggered by roles outside the approved release set. For feature-flag profiles specifically, Safeguard surfaces stale flags that have not been evaluated recently and flag attributes that appear to contain secrets, giving you the cleanup list you have been meaning to put together.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.