Skip to content

Incorrect Line Reporting for B106 on Multiline Function Calls #1328

@maciej-dss

Description

@maciej-dss

Describe the bug

The B106:hardcoded_password_funcarg check incorrectly reports the line number for findings within multiline function calls. Instead of flagging the specific line containing the hardcoded string, Bandit flags the first line of the function call. This behavior complicates remediation, as placing a # nosec comment on the reported line silences the warning, even though the issue exists on a different line. Conversely, placing the # nosec on the correct line with the hardcoded value fails to suppress the warning.

Bandit 1.8.6 - It was not on the list for selecting the version, but I tested this for versions 1.8.0-1.8.6 and it happens on all versions.

Reproduction steps

1. Have this code

from pydantic import BaseModel

class TokenExchangeRequest(BaseModel):
    client_id: str
    client_secret: str
    grant_type: str
    requested_token_use: str
    scope: str
    assertion: str

class AuthService:
    def __init__(self, client_id: str, client_secret: str):
        self.client_id = client_id
        self.client_secret = client_secret

    def _get_token_exchange_request(self, teams_token: str) -> dict[str, str]:
        return TokenExchangeRequest(
            client_id=self.client_id,
            client_secret=self.client_secret,
            grant_type="urn:ietf:params:oauth:grant-type:jwt-bearer",
            requested_token_use="on_behalf_of",
            scope="https://graph.microsoft.com/.default",
            assertion=teams_token,
        ).model_dump()

2. Run bandit
3. Result

Test results:
>> Issue: [B106:hardcoded_password_funcarg] Possible hardcoded password: 'on_behalf_of'
   Severity: Low   Confidence: Medium
   CWE: CWE-259 (https://cwe.mitre.org/data/definitions/259.html)
   More Info: https://bandit.readthedocs.io/en/1.8.6/plugins/b106_hardcoded_password_funcarg.html
   Location: ./api/services/ms_graph/auth.py:19:15
18          def _get_token_exchange_request(self, teams_token: str) -> dict[str, str]:
19              return TokenExchangeRequest(
20                  client_id=self.client_id,
21                  client_secret=self.client_secret,
22                  grant_type="urn:ietf:params:oauth:grant-type:jwt-bearer",
23                  requested_token_use="on_behalf_of",
24                  scope="https://graph.microsoft.com/.default",
25                  assertion=teams_token,
26              ).model_dump()
27

4. Add nosec on line 19 as per location above.
5. Bandit result

✗ poetry run bandit -r . -c pyproject.toml
[main]  INFO    profile include tests: None
[main]  INFO    profile exclude tests: None
[main]  INFO    cli include tests: None
[main]  INFO    cli exclude tests: None
[main]  INFO    using config: pyproject.toml
[main]  INFO    running on Python 3.12.10
Working... ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸━━━━━━━━━  77% 0:00:01[tester]        WARNING nosec encountered (B106), but no failed test on line 19
Working... ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:03

6. Move nosec from line 19 to line 23 where the issue really is.
7. Run bandit again

✗ poetry run bandit -r . -c pyproject.toml
[main]  INFO    profile include tests: None
[main]  INFO    profile exclude tests: None
[main]  INFO    cli include tests: None
[main]  INFO    cli exclude tests: None
[main]  INFO    using config: pyproject.toml
[main]  INFO    running on Python 3.12.10
Working... ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸━━━━━━━━━  76% 0:00:01[tester]        WARNING nosec encountered (B106), but no failed test on line 19
Working... ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:03
Run started:2025-11-17 09:36:05.981935

Expected behavior

Bandit should report the line number where the hardcoded string literal is defined. In the example above, the issue should be reported on line 23. This would allow for precise and clear suppression of the finding by placing # nosec on the correct line.

Bandit version

1.8.3 (Default)

Python version

3.12

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions