On macOS, encountering the message bash: permission denied typically means the account you are using cannot execute the target file from Bash. This is often a permissions, ownership, or system security policy issue rather than a Bash bug. This guide explains the common causes, how to safely inspect and fix permissions, the role of System Integrity Protection (SIP), and best practices to avoid breaking system tools. The aim is to give you an evergreen, fact-first workflow you can apply to scripts, binaries, and installed tools.
Understanding the error message and context
When Bash reports bash: permission denied, it means the process identified by your user ID cannot read and execute the file you requested. This can occur with shell scripts, compiled binaries, or any executable file. Unlike some error messages that are ambiguous, this one directly points to execution permission issues and access controls. Common triggers include running a downloaded script without marking it as executable, editing system tools without admin rights, or interacting with files owned by another user. Recognizing this as a permissions and security control problem is the first step toward a safe fix.
File permissions and ownership on macOS
macOS uses Unix-style permissions to control who can read, write, or execute a file. Every file has an owner, a group, and other users, each with specific permission bits. When you run a command, Bash checks these bits and your user identity to decide whether to allow access. If the execute bit is missing for your user category, or if ownership restricts execution, Bash returns permission denied. Knowing how to read and modify these bits safely is essential for both everyday scripts and system-level binaries.
Checking current permissions and ownership
Use ls -l in Terminal to see permissions, owner, and group for any file. The first character indicates the file type, followed by three groups of three characters for owner, group, and others, showing read (r), write (w), and execute (x) status. To see macOS-specific attributes like the quarantine attribute, prepend xattr -l to the path. Below is a concise reference table you can use to map the numeric codes, permission symbols, and their meanings.
| Numeric mode | Symbolic permissions | Meaning |
|---|---|---|
| 7 | rwx | Read, write, execute |
| 6 | rw- | Read, write, no execute |
| 5 | r-x | Read, execute, no write |
| 4 | r-- | Read, no write, no execute
For a script like /Users/you/myscript.sh, you can inspect with:
ls -l /Users/you/myscript.shto view permissions and owner.xattr -l /Users/you/myscript.shto check quarantine attributes.
How to add execute permission safely
If the file is missing execute permission for your user, you can add it with chmod. For a user-owned script, a common safe approach is to enable user execute only:
chmod u+x ~/myscript.shallows only you to execute it.chmod +x ~/myscript.shallows all categories to execute, which is less restrictive.
Use the more restrictive option whenever possible to reduce unintended execution risks. Always verify the script contents before adding execute permission, especially for files obtained from untrusted sources.
macOS System Integrity Protection (SIP) and its effects
System Integrity Protection (SIP) is a macOS security technology that limits what even privileged users can modify in protected system locations, such as /usr, /bin, /sbin, and /private. SIP is active by default and can cause bash: permission denied when Bash tries to run a system binary that has been altered or replaced by another tool, such as certain language runtimes or third-party shells. SIP protects integrity but may interfere with legitimate developer workflows involving system directories.
How to check SIP status
To see whether SIP is active, restart your Mac and hold Command-R to enter Recovery, open Terminal, and run:
csrutil status
You will see one of the following, which are informational, not errors:
System Integrity Protection status: enabled.System Integrity Protection status: disabled.
Notes:
- You cannot disable SIP permanently from Recovery; you can only temporarily disable it for a single restart.
- Disabling SIP is not recommended for security and stability reasons.
Common scenarios and safe solutions
Below are recurring situations that trigger bash: permission denied, along with secure, actionable fixes.
Running a downloaded script
When you download a shell script, macOS may mark it as unsafe. You can verify and fix this by:
- Checking with
ls -lto confirm the lack of execute permission. - Removing quarantine with
xattr -d com.apple.quarantine /path/to/script. - Adding execute permission safely for your user only:
chmod u+x /path/to/script.
Modifying system-managed tools
Editing or replacing files in /usr/bin or /bin can trigger SIP denials. Instead, install language runtimes and tools in user-owned locations, such as /usr/local or via a package manager like Homebrew, which follow macOS conventions. If you must work near system directories, consider using virtual environments or containers to isolate changes.
Using an editor or IDE that changes file ownership
Some GUI editors may save files as root or alter ownership unintentionally. Verify with ls -l and, if needed, correct ownership with sudo chown $(whoami) /path/to/file. Prefer command-line editors or configure your editor to preserve your user ownership.
Best practices to avoid future 'permission denied' issues
Adopting a few habits can save you from repeated troubleshooting and help keep your system stable.
- Avoid using sudo or root to run everyday Bash commands or scripts.
- Download scripts from trusted sources and review them before execution.
- Prefer user-level installations for development tools (e.g., Homebrew, asdf, nvm).
- Understand the difference between system directories and user-writable locations.
- Use quarantine management and execute permission changes deliberately, not by habit.
When to seek additional help
If the issue persists after verifying permissions, quarantine flags, and SIP status, consider the following:
- Check Console.app for related security or system logs.
- Confirm the file is not corrupted or intended for a different architecture.
- Verify that your user account has the necessary parent directory execute permissions to traverse the path.
- Consult documentation for the specific tool or script author, as some installers have platform-specific requirements.
Summary and quick cheat sheet
- Diagnose: Run
ls -land check ownership and execute bits. - Fix permissions: Use
chmod u+x filefor user-owned scripts. - Quarantine: Remove with
xattr -d com.apple.quarantine filewhen appropriate. - SIP awareness: SIP protects system files; avoid disabling it and prefer user-space tooling.
- Tooling: Install development tools in user-owned paths to stay clear of SIP-protected locations.