Safeguard
Application Security•

CWE-276 Incorrect Default Permissions: Find and Fix Them

CWE-276 is software that installs files others can modify. See how world-writable defaults arise in installers and images, how to audit them, and how to fix them.

Safeguard Security Team
6 min read

CWE-276, Incorrect Default Permissions, describes software that, during installation, sets file permissions so that anyone can modify those files.

MITRE lists the platforms as language and technology independent, and it includes ICS and OT environments in its list. That fits experience: this weakness appears wherever something is installed, from a desktop installer to a container image to a controller on a factory floor.

It hits the people who ship software and the people who run it. Authors choose the defaults. Operators inherit them, usually without checking.

How it happens

Defaults are chosen once, early, and rarely revisited. A few typical routes:

  • An installer creates files with a permissive mode because that avoided a permission error during testing.
  • A packaging script runs chmod -R 777 to "make it work".
  • A build copies files from a developer machine whose umask was permissive.
  • A container image runs everything as root and leaves application directories writable by all.
  • A service creates its own data and log directories without setting a mode.

MITRE's observed examples are old, and they show the range of consequences:

  • CVE-2005-1941 (Gold): executables installed world-writable.
  • CVE-2002-1713 (Gold): home directories installed world-readable.
  • CVE-2001-1550 (Gold): world-writable log files allow information loss, and a world-readable file has cleartext passwords.
  • CVE-2002-1711 (Gold): a world-readable directory.

A vulnerable installer step might look like this:

# Vulnerable: installs the binary and config open to everyone
install -m 0777 myapp /usr/local/bin/myapp
install -m 0666 myapp.conf /etc/myapp.conf

And a Dockerfile with the same flaw:

# Vulnerable: application tree writable by every user in the container
COPY . /app
RUN chmod -R 777 /app
USER root

What an attacker gains

MITRE lists confidentiality and integrity impact: reading application data and modifying application data.

Think through what each looks like in practice. A world-writable executable lets any local user replace it with their own code, which then runs the next time anyone, perhaps a privileged account, starts it. A world-writable config file lets an attacker change what the program does. A world-readable file with credentials hands them over.

Local access is a lower bar than it sounds. A shared host, a compromised low privilege account, or a container escape starting point is often enough.

How to find it

MITRE's detection notes describe several techniques with partial coverage, including analysis of binaries and bytecode, host based vulnerability scanning, and application interface scanners. In practice, start with the filesystem, because the fact is right there to read.

Find world-writable files and directories:

find /usr/local /opt /etc /var/lib/myapp -xdev -type f -perm -0002 2>/dev/null
find /usr/local /opt /etc /var/lib/myapp -xdev -type d -perm -0002 ! -perm -1000 2>/dev/null

The second command skips directories with the sticky bit, which is the one legitimate use of world-writable directories.

Find files owned by root but writable by others, and files that hold secrets but are readable by others:

find /etc -xdev -type f -perm -0004 \( -name '*.conf' -o -name '*.env' -o -name '*.key' \)

Then check what you ship:

  • Run the same commands inside a built container image, not only on a host.
  • Add a test to your build that fails if any packaged file has group or world write bits set.
  • Review installer and packaging scripts for chmod calls with broad modes and for recursive changes.

Dependencies can carry the problem too. If a third party package ships files with permissive modes, that is part of your attack surface. You can use the free in-browser dependency scan at gold.safeguard.sh/scan to see what you are pulling in. It needs no login, the file stays on your machine, and it covers up to 100 dependencies.

How to fix it

Choose permissions on purpose, as a design decision, and enforce them in the build.

  1. Start closed. Files are owned by root or the service account and are not writable by others. Executables typically need read and execute for others at most.
  2. Give secrets a private mode. Credentials and keys at 0600 or 0640 with the right group.
  3. Separate code from data. Program files should be read-only to the service. Data and log directories are the places the service may write.
  4. Run as a non-root user. In containers, set USER to an unprivileged account and give it write access only where needed.
  5. Fix at install time. Create files with an explicit mode instead of relying on defaults or the umask.
  6. Gate it. Add an automated check so a world-writable file fails the build.

Corrected versions:

install -m 0755 -o root -g root myapp /usr/local/bin/myapp
install -m 0640 -o root -g myapp myapp.conf /etc/myapp.conf
install -d -m 0750 -o myapp -g myapp /var/lib/myapp
FROM debian:bookworm-slim
RUN useradd --system --no-create-home myapp
COPY --chown=root:root --chmod=0755 myapp /usr/local/bin/myapp
USER myapp

A build time check that fails on world-writable files:

if find ./dist -type f -perm -0002 | grep -q .; then
  echo "world-writable files found" >&2
  exit 1
fi

Try it yourself

Scan a container image for misconfigurations and see how findings are reported in the demo below. Then run the find commands above inside one of your own images.

Click through it at your own pace, or open it full screen.

Quick check

Why is a world-writable executable more serious than a world-readable one?

Write access lets any local user replace the program with their own code, which runs when someone starts it. Read access exposes content but does not change what runs.

Is a world-writable directory ever acceptable?

Only with the sticky bit set, as with a shared temp directory, so users cannot delete or rename each other's files. Application directories should not be world-writable.

Where should I check for this besides the host?

Inside container images and in the packaged build output, since permissions set at build time ship to every deployment.

Sources

Never miss an update

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

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.