Summary
bad-file-permissions (S103) has false negatives and false positives.
The upstream rule checks 0o33 but Ruff’s S103 only checks 0o12.
$ cat >s103_1.py <<'# EOF'
import os
os.chmod("/etc/secrets.txt", 0o21)
# EOF
$ flake8 ./s103_1.py
./s103_1.py:2:1: S103 Chmod setting a permissive mask 0o21 on file (/etc/secrets.txt).
$ ruff --isolated check s103_1.py --select S103
All checks passed!
Only the bits of 0o33 matter for the permissiveness check. S103 should not be suppressed when those bits can statically be determined in the result of a bitwise OR, even when the full result can’t.
import os
def f(path, mode):
os.chmod(path, mode | 0o777)
There is a false positive when the result of a bitwise AND can statically be determined to be valid, even when a subexpression has an invalid value.
$ cat >s103_2.py <<'# EOF'
import os
os.chmod("/etc/secrets.txt", 0o777777 & 0o700)
os.chmod("/etc/secrets.txt", 0o777777 & 0o777) # This is a true positive for the wrong reason.
# EOF
$ ruff --isolated check s103_2.py --select S103 --output-format concise -q
s103_2.py:2:30: S103 `os.chmod` setting an invalid mask on file or directory
s103_2.py:3:30: S103 `os.chmod` setting an invalid mask on file or directory
Version
ruff 0.12.0 (87f0feb 2025-06-17)
Summary
bad-file-permissions(S103) has false negatives and false positives.The upstream rule checks
0o33but Ruff’s S103 only checks0o12.Only the bits of
0o33matter for the permissiveness check. S103 should not be suppressed when those bits can statically be determined in the result of a bitwise OR, even when the full result can’t.There is a false positive when the result of a bitwise AND can statically be determined to be valid, even when a subexpression has an invalid value.
Version
ruff 0.12.0 (87f0feb 2025-06-17)