ChmodCalc

chmod 777 — rwxrwxrwx

Everything, to everyone. This page is not a lecture about it — it is a list of what 777 actually changes, which of the errors indexed on this site it clears, which ones it causes, and what to use instead when the shared-write problem is real.

chmod — directory mode
whoreadwriteexecutedigit
Owner7
Group7
Others7
special bits — the fourth digit

ls -l → drwxrwxrwx

chmod 777 /var/www/html/uploads
chmod u=rwx,g=rwx,o=rwx /var/www/html/uploads

Absolute symbolic form — identical result, and the only form that can name the setuid, setgid and sticky bits.

chmod go+w /var/www/html/uploads

Relative form: what changed from 755. It leaves every other bit alone, which is what you want on a file you did not create.

what 777 grants on this directory

  • Ownerrwxlist the names inside, create, delete and rename entries and enter it and reach a known name inside
  • Grouprwxlist the names inside, create, delete and rename entries and enter it and reach a known name inside
  • Othersrwxlist the names inside, create, delete and rename entries and enter it and reach a known name inside
  • !! World-writable: any account on the machine can change this. Several programs refuse to use such a file at all — see the error index.

programs that refuse this mode

  • OpenSSH server (sshd)

    Authentication refused: bad ownership or modes for directory /var/www/html/uploads

    fix: chmod 700 /var/www/html/uploads

What it grants

7 is 4+2+1, three times over. Every class — owner, group, everyone else — gets read, write and execute. On a regular file that means any account can rewrite the contents and run it. On a directory it means any account can create entries, rename entries and, crucially, delete entries it does not own, because removing a file writes to the directory and never touches the file.

That last property is the one that causes real damage, and it is silent. There is no error message when another user's process deletes your upload; the file is simply not there any more. Which is why the fix for a genuinely shared directory is not 777.

777 versus 1777

The leading digit changes the semantics without changing who may read or write. Here is 777 with each of the eight possible leading digits, and what ls -l prints for each:

All eight special-bit variants of 777. The symbolic column is generated by the same function the calculator uses, so the s and t characters are where a real listing puts them.
Mode ls -l Bits set What it changes on a directory
0777 rwxrwxrwx none nothing beyond the nine bits
1777 rwxrwxrwt sticky only an entry’s owner (or the directory’s owner) may remove or rename it
2777 rwxrwsrwx setgid new entries inherit the directory’s group instead of the creator’s
3777 rwxrwsrwt setgid + sticky entries inherit the directory’s group, and only their owners may delete them
4777 rwsrwxrwx setuid nothing — Linux ignores setuid on directories
5777 rwsrwxrwt setuid + sticky only an entry’s owner (or the directory’s owner) may remove or rename it
6777 rwsrwsrwx setuid + setgid new entries inherit the directory’s group instead of the creator’s
7777 rwsrwsrwt setuid + setgid + sticky entries inherit the directory’s group, and only their owners may delete them

1777 is what /tmp uses, and the reason is quoted directly from POSIX §4.5: with S_ISVTX set on a writable directory, a process may remove or rename a file only if it is the owner of the file, the owner of the directory, or has appropriate privileges. Anyone can still create files. Nobody can delete anyone else's. That is the shared-drop-directory behaviour people are reaching for when they type 777, and it costs one extra digit.

Source: POSIX.1-2024 (IEEE Std 1003.1-2024), XBD §4.5 Directory Protection — The Open Group’s own free HTML edition, read directly.

Which errors 777 actually causes

This is the part that turns "777 is bad practice" into something you can act on. Of the rules indexed on this site, these are the ones a mode of 777 trips — they were not failing before you escalated, and they are failing now:

Rules that a mode of 777 fires. Computed by evaluating each rule at 0777, not selected by hand.
What you see Where it comes from Fires on Fix
Permissions 0644 for '/home/deploy/.ssh/id_ed25519' are too open.

OpenSSH client (ssh, scp, sftp, git over ssh) · stderr, before the connection is attempted

shown for mode 644 on ~/.ssh/id_ed25519 (a private key)

  • @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  • @ WARNING: UNPROTECTED PRIVATE KEY FILE! @
  • @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  • It is required that your private key files are NOT accessible by others.
  • This private key will be ignored.

verbatim format string: Permissions 0%3.3o for '%s' are too open.

OpenSSH (portable) — authfile.c · sshkey_perm_ok()

(st.st_uid == getuid()) && (st.st_mode & 077) != 0

quoted verbatim from the source

4032 of the 4096 modes fire it.

chmod 600 /home/deploy/.ssh/id_ed25519

least-privilege mode 600

Bad owner or permissions on /home/deploy/.ssh/config

OpenSSH client (ssh) · stderr; ssh exits immediately (fatal)

shown for mode 664 on ~/.ssh/config

verbatim format string: Bad owner or permissions on %s

OpenSSH (portable) — readconf.c · read_config_file_depth(), SSHCONF_CHECKPERM branch

((sb.st_uid != 0 && sb.st_uid != getuid()) || (sb.st_mode & 022) != 0)

quoted verbatim from the source

3072 of the 4096 modes fire it.

chmod 600 /home/deploy/.ssh/config

least-privilege mode 600

Authentication refused: bad ownership or modes for file /home/deploy/.ssh/authorized_keys

OpenSSH server (sshd) · the server’s log — /var/log/auth.log or journalctl -u sshd

shown for mode 664 on ~/.ssh/authorized_keys on the server

verbatim format string: bad ownership or modes for file %s

OpenSSH (portable) — misc.c · safe_path()

OpenSSH (portable) — auth2-pubkeyfile.c · auth_openfile()

safe_path() in misc.c writes this into an error buffer; auth_openfile() in auth2-pubkeyfile.c prints the buffer with logit("Authentication refused: %s", line).

(!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) || (stp->st_mode & 022) != 0

quoted verbatim from the source

3072 of the 4096 modes fire it.

chmod 600 /home/deploy/.ssh/authorized_keys

least-privilege mode 600

(deploy) BAD FILE MODE (/var/spool/cron/deploy)

cron (cronie) · syslog / journalctl -u crond

shown for mode 700 on the crontab file itself, e.g. /var/spool/cron/deploy

verbatim format string: (%s) %s (%s)%s%s

cronie — src/database.c · check_open()

cronie — src/misc.c · log_it()

check_open() in database.c calls log_it(uname, pid, "BAD FILE MODE", tabname, 0); log_it() in misc.c formats it for syslog with the format above, and the two trailing conversions stay empty because the err argument is 0.

(statbuf.st_mode & 07533) != 0400

quoted verbatim from the source

4088 of the 4096 modes fire it.

chmod 600 /var/spool/cron/deploy

least-privilege mode 600

/etc/sudoers.d/deploy is world writable

sudo · stderr, and sudo refuses to run

shown for mode 646 on /etc/sudoers or a file in /etc/sudoers.d/

verbatim format string: %s is world writable

sudo — plugins/sudoers/sudoers.c · open_sudoers()

sudo — lib/util/secure_path.c · sudo_check_secure()

sudo_check_secure() in lib/util/secure_path.c classifies the mode and returns SUDO_PATH_WORLD_WRITABLE; open_sudoers() in plugins/sudoers/sudoers.c turns that return value into the message above.

sb->st_mode & S_IWOTH → SUDO_PATH_WORLD_WRITABLE, in sudo_check_secure()

quoted verbatim from the source

2048 of the 4096 modes fire it.

chmod 440 /etc/sudoers.d/deploy

least-privilege mode 440

Authentication refused: bad ownership or modes for directory /home/deploy/.ssh

OpenSSH server (sshd) · the server’s log — /var/log/auth.log or journalctl -u sshd

shown for mode 775 on ~/.ssh, and every directory above it up to the home directory

verbatim format string: bad ownership or modes for directory %s

OpenSSH (portable) — misc.c · safe_path()

OpenSSH (portable) — auth2-pubkeyfile.c · auth_openfile()

Same two-file assembly as the file variant: safe_path() fills the buffer while walking upward from the key file, auth_openfile() prefixes "Authentication refused: ".

stat(buf, &st) == -1 || (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) || (st.st_mode & 022) != 0 — inside the loop that walks each parent in turn

quoted verbatim from the source

3072 of the 4096 modes fire it.

chmod 700 /home/deploy/.ssh

least-privilege mode 700

sudoers-world-writable — Two mode conditions, not one: the next branch, ISSET(sb->st_mode, S_IWGRP) && (gid == (gid_t)-1 || sb->st_gid != gid), rejects a group-writable file too unless its group is the one sudo expects — so 664 fails here for a different reason than 666 does. Fix these with visudo, which validates before replacing the file.

Those rows are shown here for the one property this page is about — that 777 trips them. The per-row caveats, and the 6 rules 777 does not trip, are on the error index.

The sudo row deserves emphasis because the failure mode is so unhelpful: a world-writable file in /etc/sudoers.d/ makes sudo refuse to run at all, which on a machine where you reach root only through sudo means you have locked yourself out. Use visudo -f for those files; it validates before replacing, and it sets the mode for you.

What to use instead, per problem

  • "The web server can't read my files." The server needs read on the file and search on every directory above it. That is 644 for files and 755 for directories — nine bits changed to five.
  • "My application can't write to the upload directory." Give the directory to the application's user with chown, then 755. Ownership is the right lever here; widening the mode gives the same access to every other process on the box as well.
  • "Several people need to write to this directory." A shared group, mode 2775, and a umask of 002. The setgid bit makes new entries inherit the group; the umask keeps the group-write bit from being masked off at creation.
  • "Anyone should be able to drop files here." 1777. The sticky bit is the entire point.
  • "My script won't run." chmod +x, which sets three bits and no more. If you want it private, 700.

Undoing it

There is no "restore previous modes" — the old values are not recorded anywhere once chmod has run. What you can do is re-establish a sane baseline by type:

find /var/www/html -type d -exec chmod 755 {} +
find /var/www/html -type f -exec chmod 644 {} +

Then walk back the exceptions by hand: scripts that need to be executable, keys that need to be 600, and anything owned by a service account. If the tree came from Git, a fresh clone restores the one mode bit Git tracks — it records only whether a file is executable, not the full mode — so a clone gives you correct execute bits and default everything else.

777 is not a stronger version of the mode you needed. It is a different mode that happens to include the bit you were missing, along with the others you were not — and at 777 that trips 6 of the rules indexed on this site, every one of them quoted above from the source that enforces it.

## Questions people actually ask

What does chmod 777 do?

It sets rwxrwxrwx — read, write and execute for the owner, the group and everyone else. Every account on the machine can read the contents, change them, and run the file. On a directory it additionally means anyone can create, rename and delete entries, including entries belonging to other people.

Is chmod 777 ever correct?

On a shared drop directory, yes — but as 1777, not 777. The sticky bit restricts deletion to the owner of each entry, which is the whole difference between /tmp working and a shared directory where anyone can remove anyone else's files. Plain 777 on a directory that several users write to is a mistake that shows up as mysteriously vanishing files and never as an error message.

Why did chmod 777 not fix my error?

Because 2 of the 12 messages in this site's error index are not caused by file modes at all, and several of the ones that are get worse at 777. cronie refuses a world-writable crontab, sudo refuses a world-writable sudoers file, and sshd refuses a group-writable ~/.ssh. Escalating to 777 turns a fixable problem into a different problem.

How do I undo chmod -R 777?

Split the tree by type and set each half to something sane: find /path -type d -exec chmod 755 {} + then find /path -type f -exec chmod 644 {} +. That will be right for a web root. It will not restore anything that was deliberately different — an executable script that is now 644, or a key that is now readable — so check those by hand afterwards. This is the reason to reach for the two find commands the first time and leave the recursive one alone.

Does 777 make a file world-writable and world-readable at once?

Yes, both, and that is the point people miss when they use it as a debugging step. 256 of the 512 three-digit modes are world-writable; 777 is simply the most permissive of them. If your goal was "let the web server read this", the mode you wanted changed one bit, not nine.

What is 777 in symbolic notation?

rwxrwxrwx, or u=rwx,g=rwx,o=rwx as a chmod argument, or a+rwx as a relative one. With the sticky bit it becomes rwxrwxrwt — note the trailing t where the others-execute character would be, which is how ls -l shows you a sticky directory.

elsewhere on this site

  • The chmod calculator itself — all 512 three-digit modes in one table.
  • chmod 600 — Owner-only read and write — the mode OpenSSH demands of a private key.
  • chmod 700 — The private directory, and the difference between what ssh recommends and what sshd enforces.

other tools we run