Skip to content

CWE-276: Incorrect Default Permissions

Overview

Incorrect default permissions occur when a file, directory, database, cloud storage bucket, service, or installed component is created with overly permissive defaults - a world-readable/writable mode, a permissive storage policy, or a default-allow network rule - before any application-level access control has a chance to run. Installer scripts, deployment templates, infrastructure-as-code, and platform or cloud provider defaults are part of the attack surface here, not just application code.

Relationship to Other CWEs

CWE-276 is a child of CWE-732 (Incorrect Permission Assignment for Critical Resource) - the narrower case where the wrong permission is the one a resource is created with rather than one assigned later. Fix CWE-276 by changing the default that new resources inherit; fix CWE-732 by fixing the specific assignment. Where the finding is a bad chmod call or an ACL bug in application logic, CWE-732's page is the closer fit.

MITRE's own entry is split, so read a CWE-276 citation before acting on it. The name is general - Incorrect Default Permissions, any resource, any phase - while the description is narrow: "During installation, installed file permissions are set to allow anyone to modify those files." MITRE records the inconsistency itself and, as of CWE 4.19, lists the entry as being considered for deprecation or significant revision because of it. This page follows the name, because that is the reading scanners and triage tools use, and because the installation-only reading has nowhere to send a public storage bucket. Two consequences:

  • If the finding really is installed file permissions, everything here applies and the narrow reading and the broad one agree.
  • If it is an unchanged default administrative account or password, this is the wrong page even under the broad reading. That is CWE-1392 (Use of Default Credentials) or CWE-1393 (Use of Default Password); neither has a page here, and CWE-798 (Use of Hard-coded Credentials) carries the credential-handling remediation. Everything below is about permissions and policies, not credentials. The one place credentials appear is the note at the end of Remediation Steps, and it is there because the same provisioning code usually sets both, not because a default-credential finding belongs on this page.

OWASP Classification

A01:2025 - Broken Access Control

Risk

High: Resources provisioned with overly permissive defaults are exposed the moment they are created, before any later hardening step runs. Common real-world instances - world-writable files, publicly-readable storage buckets, and 0.0.0.0/0 ingress rules - need no vulnerability in application logic at all to exploit, only a scan for the default.

Remediation Steps

Core Principle: Make every creation path set an explicit, restrictive permission or policy at creation time, rather than inheriting whatever the OS, platform, framework, or installer ships with by default.

Trace the Data Path

  • Source: Every place a resource is created or provisioned - file/directory creation, database or bucket provisioning, service installation, container image build, IaC template, or first-boot sequence
  • Sink: The point where the resource becomes reachable - a file opened by another process, a bucket exposed to the internet, a network rule taking effect
  • Missing Controls: No explicit permission or policy set at creation time, so the resource inherits the OS umask, platform default ACL, or cloud default policy unexamined

Set Explicit Restrictive Defaults at Creation Time (Primary Defense)

  • Default to deny: newly created resources should start with the minimum access needed, not the platform's out-of-the-box default
  • Specify file mode/umask explicitly in code or deployment scripts, set bucket/storage policies to private with explicit allow rules, and set security group/firewall rules to default-deny

Fix Templates and Installers, Not Just Running Instances (Defense in Depth)

  • Update the IaC template, installer, or image build so every newly created resource inherits the corrected default, rather than patching only the currently running instances
  • Review installer scripts, container images, IaC templates (Terraform, CloudFormation, Helm charts), and platform/cloud defaults with the same scrutiny as application code
  • Keep an application-level authorization check at the point of use, so that a future regression in the default is not enough on its own to expose the resource

Test Against a Fresh Provision

  • Provision a fresh instance from the corrected template or installer and verify its permissions, policies, and network rules match least privilege before any manual hardening step
  • Use automated configuration and cloud security scanners to catch drift between the intended default and what actually gets created
  • Re-scan with the security scanner to confirm the finding is resolved

Adjacent: Default Credentials in the Same Provisioning Code (Not This CWE)

Installers, images and IaC templates that ship a permissive default permission usually ship a default account alongside it, so a CWE-276 fix is a natural moment to deal with both. Record the credential half as its own finding under CWE-1392 / CWE-1393, not under CWE-276, and remediate it from CWE-798: generate or require a credential per install rather than shipping a fixed one, and disable the default account rather than only rotating its password - an enabled, discoverable account stays a target for credential stuffing whatever its password is. Closing the permission finding does not close the credential one, and a re-scan against CWE-276 will not say anything about it either way.

Common Vulnerable Patterns

// VULNERABLE - pseudo-code
createFile(path, data)          // no explicit mode - the platform decides (on POSIX the call asks for
                                //   0666 and the umask clears bits from it: 0644 under the usual 022,
                                //   world-writable under 000)
createStorageBucket(name)       // no explicit policy - inherits provider default (sometimes public)

// Attack: any user or internet client reaches the resource through its default access level
// Result: unintended read or write access to sensitive data

Why this is vulnerable: the code does not choose a permission, so something else does - the platform's umask, the provider's default policy, the parent directory's inheritance rules. That default is set for compatibility rather than for this application's data, and it varies between the developer's machine, the build agent and production, which is why the same code produces a private file in testing and a readable one in deployment.

The timing matters as much as the value. A resource created permissively and tightened afterwards is exposed for the interval between the two calls, and that interval is reachable - a local attacker polling a predictable path, or an internet scanner enumerating storage buckets, does not need long. The fix that cannot be reordered is passing the mode or policy as part of the create call, so there is no moment at which the resource exists with the wrong permission. Where a platform offers no such parameter, creating in a directory that is already restricted achieves the same thing by inheritance.

Secure Patterns

// SECURE - pseudo-code
createFile(path, data, mode=OWNER_READ_WRITE_ONLY)
createStorageBucket(name, policy=PRIVATE, explicitAllow=[intendedPrincipals])

Why this works: The permission or policy is set explicitly at the moment of creation, so the resource is never briefly - or permanently - exposed at whatever the platform's out-of-the-box default happens to be. Because the restriction is encoded in the template or code path that creates the resource, every future instance inherits the corrected default automatically.

Common Pitfalls

  • Hardening the running instance but not the template: Manually tightening permissions on an existing bucket or file while the Terraform module, installer, or image build that created it still produces the permissive default for the next deployment.
  • Assuming a managed platform's default is safe: Trusting that a cloud provider's or framework's out-of-the-box setting is secure by default, when several major providers have shipped permissive defaults (public-read storage, open management ports) that require an explicit opt-out.

Additional Resources