Skip to content

Detect dangerous chmod with stat module constants in B103#1410

Open
jonasboos wants to merge 2 commits into
PyCQA:mainfrom
jonasboos:fix-1390-b103-stat-constants
Open

Detect dangerous chmod with stat module constants in B103#1410
jonasboos wants to merge 2 commits into
PyCQA:mainfrom
jonasboos:fix-1390-b103-stat-constants

Conversation

@jonasboos
Copy link
Copy Markdown

Problem

The B103 plugin only detects dangerous file permissions when is called with integer literals (e.g., ). When stat module constants like or bitwise-OR expressions like are used, the check is silently skipped because the AST node type is or , not .

As reported in #1390, code like this goes undetected:

import stat
os.chmod('config.ini', stat.S_IWGRP | stat.S_IWOTH)  # Not flagged
os.chmod('~/hidden', stat.S_IXOTH)                     # Not flagged

Fix

Add _resolve_stat_expression() that recursively evaluates AST nodes:

  • ast.Attribute nodes like stat.S_IWOTH → resolved via lookup table
  • ast.BinOp (BitOr) nodes like stat.S_IWGRP | stat.S_IWOTH → resolved by evaluating both sides
  • Falls back gracefully if resolution fails (same behavior as before)

This enables B103 to flag dangerous permissions expressed via the stat module with the same severity/confidence levels as integer literal usage.

Testing

  • Added stat.S_IWGRP | stat.S_IWOTH to example file
  • Updated functional test expectations
  • All unit and functional tests pass

Resolves: #1390

The B103 plugin only detected dangerous file permissions when chmod was
called with integer literals (e.g., 0o777). When stat module constants
like stat.S_IWOTH or expressions like stat.S_IWGRP | stat.S_IWOTH were
used, the check was silently skipped because the AST node type was
Attribute or BinOp, not int.

Add _resolve_stat_expression() to recursively evaluate AST nodes that
are stat constant references or bitwise-OR combinations of them. This
enables detection of dangerous permissions expressed via the stat module.

Resolves: PyCQA#1390
Copilot AI review requested due to automatic review settings May 10, 2026 19:15
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request enhances the B103 “bad file permissions” plugin so it can detect dangerous chmod permission masks expressed using stat module constants (e.g., stat.S_IWOTH) and bitwise-OR expressions (e.g., stat.S_IWGRP | stat.S_IWOTH), closing a known false-negative gap.

Changes:

  • Added _resolve_stat_expression() to evaluate AST nodes representing stat constants and | combinations into an integer mode.
  • Updated the example os-chmod.py to include a stat.S_IWGRP | stat.S_IWOTH case.
  • Updated functional test expectations to account for additional B103 findings.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
bandit/plugins/general_bad_file_permissions.py Adds AST resolution logic for stat constants and bitwise-OR expressions to improve B103 detection coverage.
examples/os-chmod.py Adds an example using stat constants combined via `
tests/functional/test_functional.py Updates expected severity/confidence counts for the os-chmod.py functional scan output.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +67 to +69
# Only includes flags that are relevant to file permission checks.
_STAT_CONSTANTS = {
name: getattr(stat, name) for name in dir(stat) if name.startswith("S_I")
if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
left = _resolve_stat_expression(node.left)
right = _resolve_stat_expression(node.right)
if left is not None and right is not None:
Comment on lines +118 to +122
raw_args = context._context["call"].args
if len(raw_args) >= 2:
resolved = _resolve_stat_expression(raw_args[1])
if resolved is not None:
mode = resolved
@jonasboos
Copy link
Copy Markdown
Author

@copilot apply changes based on the comments in this thread

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

False negative: B103 fails to detect dangerous permissions set via stat module constants

2 participants