Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,915 changes: 1,915 additions & 0 deletions examples/fastapi-simple-docker-pip/Pipfile.lock

Large diffs are not rendered by default.

26 changes: 14 additions & 12 deletions examples/fastapi-simple-docker-pip/app/auth/auth.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import uuid
from typing import Annotated, Dict
from typing import Annotated, Any, Dict

from fastapi import Depends, HTTPException, Query, status
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
Expand All @@ -14,13 +14,15 @@

security_scheme = HTTPBearer()


def get_auth_provider() -> AuthProvider:
return MockAuthProvider()


async def get_access_token(
token: Annotated[HTTPAuthorizationCredentials, Depends(security_scheme)],
auth_provider: Annotated[AuthProvider, Depends(get_auth_provider)]
) -> Dict[str, any] | HTTPException:
auth_provider: Annotated[AuthProvider, Depends(get_auth_provider)],
) -> Dict[str, Any] | HTTPException:
try:
Comment on lines +25 to 26
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Don’t include HTTPException in return type; dependencies should return data or raise.
The function always returns a dict or raises. Narrow the typing.

-) -> Dict[str, Any] | HTTPException:
+) -> Dict[str, Any]:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
) -> Dict[str, Any] | HTTPException:
try:
) -> Dict[str, Any]:
try:
🤖 Prompt for AI Agents
In examples/fastapi-simple-docker-pip/app/auth/auth.py around lines 25-26, the
return type currently includes HTTPException but the function never returns an
HTTPException (it raises on error), so change the annotation to return Dict[str,
Any] (or the more specific dict type you expect) and remove HTTPException from
the union; ensure any error paths raise HTTPException instead of returning it so
the signature matches behavior.

payload = jwt.decode(
token.credentials, "", algorithms=["HS256"], options={"verify_signature": False}
Expand All @@ -42,19 +44,20 @@ async def get_access_token(
) from e
return access_token


async def get_current_user(
access_token: Annotated[Dict[str, any], Depends(get_access_token)],
access_token: Annotated[Dict[str, Any], Depends(get_access_token)],
auth_provider: Annotated[AuthProvider, Depends(get_auth_provider)],
impersonation_sub: str | None = Query(None, description="Impersonation user sub."),
) -> User | HTTPException:
user_data = auth_provider.get_user(access_token['sub'])
user_data = auth_provider.get_user(access_token["sub"])
Comment on lines 52 to +53
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Same here: return a User, not a union with HTTPException.

-) -> User | HTTPException:
+) -> User:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
) -> User | HTTPException:
user_data = auth_provider.get_user(access_token['sub'])
user_data = auth_provider.get_user(access_token["sub"])
) -> User:
user_data = auth_provider.get_user(access_token["sub"])
🤖 Prompt for AI Agents
In examples/fastapi-simple-docker-pip/app/auth/auth.py around lines 52 to 53,
the function signature and/or return annotation incorrectly uses a union type
User | HTTPException; change the annotation to return User only and ensure the
function raises HTTPException on error instead of returning it, i.e., remove
HTTPException from the return type and replace any return of an HTTPException
instance with raising that exception so callers always receive a User on success
and exceptions are propagated on failure.

user = User(
id=uuid.UUID(user_data['id'], version=4),
sub=user_data['sub'],
username=user_data['username'],
is_premium=user_data.get('is_premium', False),
email=user_data.get('email', ""),
groups=user_data.get('groups', []),
id=uuid.UUID(user_data["id"], version=4),
sub=user_data["sub"],
username=user_data["username"],
is_premium=user_data.get("is_premium", False),
email=user_data.get("email", ""),
groups=user_data.get("groups", []),
)
if not settings.auth_provider_enabled:
return user
Expand All @@ -63,4 +66,3 @@ async def get_current_user(
return user
except Exception as e:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))

Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from abc import ABC, abstractmethod
from typing import Any, List, Dict
from typing import Any, Dict, List


class AuthProvider(ABC):
@abstractmethod
Expand All @@ -11,7 +12,9 @@ def get_user(self, user_id: str) -> Dict[str, Any]:
pass

@abstractmethod
def create_user(self, email: str, attributes: List[Dict[str, Any]], groups: List[str]) -> Dict[str, Any]:
def create_user(
self, email: str, attributes: List[Dict[str, Any]], groups: List[str]
) -> Dict[str, Any]:
pass

@abstractmethod
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
from typing import Any, List, Dict
from typing import Any, Dict, List

from .generic_auth_provider import AuthProvider


class MockAuthProvider(AuthProvider):
def authenticate_user(self, token: str) -> Dict[str, Any]:
return {
"sub": "123e4567-e89b-12d3-a456-426614174000",
"username": "mockuser",
"is_premium": True,
"email": "[email protected]",
"groups": ["user", "admin"]
"groups": ["user", "admin"],
}

def get_user(self, user_id: str) -> Dict[str, Any]:
Expand All @@ -18,13 +20,13 @@ def get_user(self, user_id: str) -> Dict[str, Any]:
"username": "mockuser",
"is_premium": True,
"email": "[email protected]",
"groups": ["user", "admin"]
"groups": ["user", "admin"],
}

def create_user(self, email: str, attributes: List[Dict[str, Any]], groups: List[str]) -> Dict[str, Any]:
return {
"response": "User created successfully"
}
def create_user(
self, email: str, attributes: List[Dict[str, Any]], groups: List[str]
) -> Dict[str, Any]:
return {"response": "User created successfully"}

def update_user(self, email: str, attributes: List[Dict[str, Any]], groups: List[str]) -> None:
pass
Expand Down
11 changes: 11 additions & 0 deletions examples/fastapi-simple-docker-pip/app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class AppSettings(BaseSettings):
version: str = Field(alias="APP_VERSION", default="0.1.2")
stage: str = Field(alias="STAGE", default="local")


class EmailSettings(BaseSettings):
model_config = SettingsConfigDict(extra="ignore")
smtp_host: str | None = Field(alias="EMAIL_SMTP_HOST", default=None)
Expand All @@ -17,9 +18,19 @@ class EmailSettings(BaseSettings):
to_email: str | None = Field(alias="EMAIL_TO_EMAIL", default=None)


class DatabaseSettings(BaseSettings):
url: str = Field(alias="DATABASE_URL", default="sqlite:///./test.db")


class AuthSettings(BaseSettings):
auth_provider_enabled: bool = Field(alias="AUTH_PROVIDER_ENABLED", default=False)

Comment on lines +25 to +27
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Deduplicate AUTH_PROVIDER_ENABLED; expose a cohesive AuthSettings group.

Same flag exists in AuthSettings and again at Settings; remove duplication to avoid drift.

Apply:

 class AuthSettings(BaseSettings):
     auth_provider_enabled: bool = Field(alias="AUTH_PROVIDER_ENABLED", default=False)
 
 class Settings(BaseSettings):
     app: AppSettings = AppSettings()
     email: EmailSettings = EmailSettings()
-    database: DatabaseSettings = DatabaseSettings()
-    auth_provider_enabled: bool = Field(alias="AUTH_PROVIDER_ENABLED", default=False)
+    database: DatabaseSettings = DatabaseSettings()
+    auth: AuthSettings = AuthSettings()

Search for usages to update call sites:

Also applies to: 29-34


🏁 Script executed:

#!/bin/bash
rg -nP '\bauth_provider_enabled\b' examples/fastapi-simple-docker-pip | sed 's/^/HIT: /'

Length of output: 479


Deduplicate AUTH_PROVIDER_ENABLED and update call sites

To avoid configuration drift, consolidate the AUTH_PROVIDER_ENABLED flag into AuthSettings and remove its duplicate from Settings. Then update all references accordingly.

Changes required:

  • In examples/fastapi-simple-docker-pip/app/config.py:
    • Remove the duplicate auth_provider_enabled field on Settings
    • Add an auth: AuthSettings = AuthSettings() property
  • In examples/fastapi-simple-docker-pip/app/auth/auth.py (and any other call sites):
    • Replace settings.auth_provider_enabled with settings.auth.auth_provider_enabled (hit at line 62)

Suggested patch:

--- a/examples/fastapi-simple-docker-pip/app/config.py
+++ b/examples/fastapi-simple-docker-pip/app/config.py
@@ class AuthSettings(BaseSettings):
     auth_provider_enabled: bool = Field(alias="AUTH_PROVIDER_ENABLED", default=False)
 
 class Settings(BaseSettings):
     app: AppSettings = AppSettings()
     email: EmailSettings = EmailSettings()
-    database: DatabaseSettings = DatabaseSettings()
-    auth_provider_enabled: bool = Field(alias="AUTH_PROVIDER_ENABLED", default=False)
+    database: DatabaseSettings = DatabaseSettings()
+    auth: AuthSettings = AuthSettings()
--- a/examples/fastapi-simple-docker-pip/app/auth/auth.py
+++ b/examples/fastapi-simple-docker-pip/app/auth/auth.py
@@ -59,7 +59,7 @@ def authenticate(request: Request, settings: Settings = Depends(get_settings)):
     # previous logic
-    if not settings.auth_provider_enabled:
+    if not settings.auth.auth_provider_enabled:
         raise HTTPException(status_code=403, detail="Auth provider disabled")
     # continue...

• Verify there are no other references to settings.auth_provider_enabled.
• Ensure documentation and tests (if any) are updated to use the new settings.auth.auth_provider_enabled path.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
class AuthSettings(BaseSettings):
auth_provider_enabled: bool = Field(alias="AUTH_PROVIDER_ENABLED", default=False)
# examples/fastapi-simple-docker-pip/app/config.py
class AuthSettings(BaseSettings):
auth_provider_enabled: bool = Field(alias="AUTH_PROVIDER_ENABLED", default=False)
class Settings(BaseSettings):
app: AppSettings = AppSettings()
email: EmailSettings = EmailSettings()
database: DatabaseSettings = DatabaseSettings()
auth: AuthSettings = AuthSettings()
Suggested change
class AuthSettings(BaseSettings):
auth_provider_enabled: bool = Field(alias="AUTH_PROVIDER_ENABLED", default=False)
# examples/fastapi-simple-docker-pip/app/auth/auth.py
def authenticate(request: Request, settings: Settings = Depends(get_settings)):
# previous logic
if not settings.auth.auth_provider_enabled:
raise HTTPException(status_code=403, detail="Auth provider disabled")
# continue...
🤖 Prompt for AI Agents
In examples/fastapi-simple-docker-pip/app/config.py around lines 25-27, Settings
currently duplicates the AUTH_PROVIDER_ENABLED flag; remove the duplicate
auth_provider_enabled from Settings and add an auth: AuthSettings =
AuthSettings() property so the setting lives only on AuthSettings; then update
all call sites (notably examples/fastapi-simple-docker-pip/app/auth/auth.py line
62) to replace settings.auth_provider_enabled with
settings.auth.auth_provider_enabled; finally scan the codebase (and docs/tests)
to ensure no remaining references to settings.auth_provider_enabled and update
them to the new path.


class Settings(BaseSettings):
app: AppSettings = AppSettings()
email: EmailSettings = EmailSettings()
database: DatabaseSettings = DatabaseSettings()
auth_provider_enabled: bool = Field(alias="AUTH_PROVIDER_ENABLED", default=False)


settings = Settings()
Original file line number Diff line number Diff line change
@@ -1,50 +1,41 @@
from uuid import UUID

from app.schemas.note import NoteBase
from app.schemas.note import NoteOut


class NoteRepository:
def __init__(self):
def __init__(self) -> None:
pass

def get_note_by_id(self, note_id: UUID) -> NoteBase:
mock_note = NoteBase(
id=str(note_id),
title="Mocked Note",
description="This is a mocked note.",
summary="summary",
media_url="https://localhost",
preview_image_url="https://localhost",
owner_id=str(UUID("12345678-1234-5678-1234-567812345678")),
created_at="2021-01-01T00:00:00",
updated_at="2021-01-01T00:00:00"
)

def get_note_by_id(self, note_id: UUID) -> NoteOut:
mock_note = NoteOut(
title="Mocked Note",
description="This is a mocked note.",
summary="summary",
media_url="https://localhost",
preview_image_url="https://localhost",
owner_id=str(UUID("12345678-1234-5678-1234-567812345678")),
)

return mock_note

def get_all_notes(self) -> list[NoteBase]:
def get_all_notes(self) -> list[NoteOut]:
mock_note_list = [
NoteBase(
id=str(UUID("12345678-1234-5678-1234-567812345678")),
title="Mocked Note",
description="This is a mocked note.",
summary="summary",
media_url="https://localhost",
preview_image_url="https://localhost",
owner_id=str(UUID("12345678-1234-5678-1234-567812345678")),
created_at="2021-01-01T00:00:00",
updated_at="2021-01-01T00:00:00"
NoteOut(
title="Mocked Note",
description="This is a mocked note.",
summary="summary",
media_url="https://localhost",
preview_image_url="https://localhost",
owner_id=str(UUID("12345678-1234-5678-1234-567812345678")),
),
NoteBase(
id=str(UUID("87654321-4321-8765-4321-876543218765")),
title="Mocked Note",
description="This is a mocked note.",
summary="summary",
media_url="https://localhost",
preview_image_url="https://localhost",
owner_id=str(UUID("12345678-1234-5678-1234-567812345678")),
created_at="2021-01-01T00:00:00",
updated_at="2021-01-01T00:00:00"
NoteOut(
title="Mocked Note",
description="This is a mocked note.",
summary="summary",
media_url="https://localhost",
preview_image_url="https://localhost",
owner_id=str(UUID("87654321-4321-8765-4321-876543218765")),
),
]
return [NoteBase.model_validate(note) for note in mock_note_list]
return mock_note_list
4 changes: 4 additions & 0 deletions examples/fastapi-simple-docker-pip/app/schemas/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
from .note import NoteBase, NoteCreate, NoteOut, NoteUpdate
from .sorting import Sorting
from .user import User

__all__ = [
"NoteBase",
"NoteCreate",
"NoteOut",
"NoteUpdate",
"Sorting",
"User",
]
2 changes: 2 additions & 0 deletions examples/fastapi-simple-docker-pip/app/schemas/note.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ class NoteBase(BaseModel):
class NoteCreate(NoteBase):
id: str


class NoteUpdate(NoteBase):
id: str


class NoteOut(NoteBase):
class Config:
from_attributes = True
8 changes: 8 additions & 0 deletions examples/fastapi-simple-docker-pip/app/schemas/sorting.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from typing import List, Optional

from pydantic import BaseModel


class Sorting(BaseModel):
sort_by: Optional[List[str]] = None
sort_order: Optional[List[str]] = None
13 changes: 13 additions & 0 deletions examples/fastapi-simple-docker-pip/app/schemas/user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from typing import List
from uuid import UUID

from pydantic import BaseModel


class User(BaseModel):
id: UUID
sub: str
username: str
is_premium: bool = False
email: str = ""
groups: List[str] = []
Comment on lines +7 to +13
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid mutable default for lists and validate email type.

Use Field(default_factory=list) and EmailStr. This prevents shared mutable defaults and enforces email format.

-from pydantic import BaseModel
+from pydantic import BaseModel, Field, EmailStr
@@
 class User(BaseModel):
     id: UUID
     sub: str
     username: str
     is_premium: bool = False
-    email: str = ""
-    groups: List[str] = []
+    email: EmailStr | None = None
+    groups: List[str] = Field(default_factory=list)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
class User(BaseModel):
id: UUID
sub: str
username: str
is_premium: bool = False
email: str = ""
groups: List[str] = []
from pydantic import BaseModel, Field, EmailStr
class User(BaseModel):
id: UUID
sub: str
username: str
is_premium: bool = False
email: EmailStr | None = None
groups: List[str] = Field(default_factory=list)
🤖 Prompt for AI Agents
In examples/fastapi-simple-docker-pip/app/schemas/user.py around lines 7-13,
replace the mutable list default and plain string email with proper Pydantic
types: change groups to use Field(default_factory=list) to avoid shared mutable
defaults, change email to use EmailStr (or Optional[EmailStr] with a default of
None) to validate email format, and add the necessary imports (from pydantic
import Field, EmailStr and typing Optional if used). Ensure the field
annotations and defaults are updated accordingly.

Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import AsyncGenerator

import pytest
from fastapi import status
from httpx import AsyncClient
Expand All @@ -6,21 +8,24 @@


@pytest.fixture
async def client():
async with AsyncClient(app=app, base_url="http://test") as ac:
async def client() -> AsyncGenerator[AsyncClient, None]:
async with AsyncClient(base_url="http://test") as ac:
yield ac
Comment on lines +11 to 13
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fixture no longer mounts the ASGI app; requests won’t reach FastAPI

Without an ASGI transport (or app=app), the client will try real HTTP to http://test.

Apply:

-from httpx import AsyncClient
+from httpx import AsyncClient, ASGITransport
@@
-async def client() -> AsyncGenerator[AsyncClient, None]:
-    async with AsyncClient(base_url="http://test") as ac:
+async def client() -> AsyncGenerator[AsyncClient, None]:
+    transport = ASGITransport(app=app)
+    async with AsyncClient(transport=transport, base_url="http://test") as ac:
         yield ac

(Optional) manage startup/shutdown:

# from asgi_lifespan import LifespanManager
# async with LifespanManager(app):
#     ...
🤖 Prompt for AI Agents
In examples/fastapi-simple-docker-pip/tests/integration/test_main_routes.py
around lines 11-13, the AsyncClient fixture does not mount the FastAPI ASGI app
so requests will go over real HTTP to http://test; update the fixture to pass
the app instance to AsyncClient via the app or transport parameter so it uses
the ASGI app, and optionally wrap usage with an ASGI lifespan manager to run
startup/shutdown (e.g., use LifespanManager or an equivalent context to ensure
app startup/shutdown during the test).



@pytest.mark.asyncio
async def test_root_endpoint(client): # pylint: disable=redefined-outer-name
async def test_root_endpoint(
client: AsyncClient, # pylint: disable=redefined-outer-name
) -> None:
response = await client.get("/")
assert response.status_code == status.HTTP_200_OK
assert response.json() == {"message": "Hello World"}


@pytest.mark.asyncio
async def test_healthcheck_endpoint(client): # pylint: disable=redefined-outer-name
async def test_healthcheck_endpoint(
client: AsyncClient, # pylint: disable=redefined-outer-name
) -> None:
response = await client.get("/healthz")
assert response.status_code == status.HTTP_200_OK
assert response.json() == {"status": "ok"}

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
client = TestClient(app)


def test_healthcheck():
def test_healthcheck() -> None:
response = client.get("/healthz")
assert response.status_code == 200
assert response.json() == {"status": "ok"}
34 changes: 34 additions & 0 deletions examples/green-house-migration/.bandit
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Bandit configuration file
# See: https://bandit.readthedocs.io/en/latest/config.html

exclude_dirs: ["tests", "legacy", "scripts/development"]

skips: ["B101", "B601", "B102", "B103"]
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Over-broad skips reduce security coverage.

Skipping B102/B103/B601 globally hides real issues. Keep B101 (asserts) if needed; consider removing others.

Apply:

-skips: ["B101", "B601", "B102", "B103"]
+skips: ["B101"]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
skips: ["B101", "B601", "B102", "B103"]
skips: ["B101"]
🤖 Prompt for AI Agents
In examples/green-house-migration/.bandit around line 6, the file currently
skips B101, B601, B102, B103 which is overly broad; remove B102, B103 and B601
from the global skips and keep at most B101 (or none) globally, or replace the
global skips with targeted per-file/per-test ignores and inline comments
justifying any remaining exceptions; update the skips line accordingly and run
bandit to verify coverage.


# Test files and directories
tests: ["test_*.py", "*_test.py"]

Comment on lines +9 to +10
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Misuse of “tests” key disables Bandit checks.

In Bandit config, tests: selects plugin IDs (e.g., B101…), not filename globs. As written, Bandit may run zero tests.

Apply:

-# Test files and directories
-tests: ["test_*.py", "*_test.py"]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
tests: ["test_*.py", "*_test.py"]
🤖 Prompt for AI Agents
In examples/green-house-migration/.bandit around lines 9-10, the config uses the
"tests" key incorrectly (Bandit expects plugin IDs there), which can cause no
checks to run; change that key to "targets" (or remove it) and supply the
intended file/directory globs (e.g., tests patterns) under "targets", or if you
truly intended to select specific plugin IDs keep "tests" but replace the values
with valid plugin IDs (Bxxx); ensure the rest of the config uses correct Bandit
keys so scans run as expected.

# Target Python versions
target_version: ["py38", "py39", "py310", "py311", "py312"]

# Output format
output_format: json
output_file: bandit-report.json

# Verbose output
verbose: true

# Debug mode
debug: false

# Profile to use
profile: default

# Aggressive mode
aggressive: false

# Recursive directory scanning
recursive: true

# Number of processes to use
jobs: 1
Comment on lines +15 to +34
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

❓ Verification inconclusive

CLI options in config may be ignored.

Keys like output_format, output_file, verbose, debug, aggressive, recursive, jobs are CLI flags and may not be honored from config. Prefer setting them in CI invocation.

Update CI to call:

Would you like me to open a PR to adjust the CI job?


🏁 Script executed:

bandit -r examples/green-house-migration -x tests,legacy,scripts/development -f json -o bandit-report.json -q

Length of output: 208


CLI-only options in .bandit aren’t applied at runtime

The .bandit file only supports the following arguments (and plugin-specific settings) when supplied via the -c/--configfile flag:

All other flags—output_format, output_file, verbose, debug, aggressive, recursive, and jobs—must be passed on the command line and will be ignored if placed in the config.

Please update your CI job to invoke Bandit with those options explicitly. For example:

bandit \
  -r examples/green-house-migration \
  -x tests,legacy,scripts/development \
  -f json \
  -o bandit-report.json \
  -q

Would you like me to open a PR to adjust the CI workflow accordingly?

🤖 Prompt for AI Agents
In examples/green-house-migration/.bandit around lines 15 to 34: the config
places CLI-only Bandit flags (output_format, output_file, verbose, debug,
aggressive, recursive, jobs) in the .bandit file but those are ignored at
runtime; keep only supported keys (exclude/exclude_dirs, skips, tests, targets)
in this file and move the other flags into the CI job command that invokes
bandit so they are passed on the command line (e.g., add -f/--format,
-o/--output, -q/-v for verbosity, -r/--recursive and --jobs to the bandit
invocation that scans examples/green-house-migration).

41 changes: 41 additions & 0 deletions examples/green-house-migration/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# EditorConfig is awesome: https://EditorConfig.org

# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file*]
end_of_line = lf
insert_final_newline = true
charset = utf-8im_trailing_whitespace = true
Comment on lines +6 to +9
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix malformed global settings (broken comment and merged keys).

Split and correct properties; current line 9 breaks both charset and trim_trailing_whitespace.

-# Unix-style newlines with a newline ending every file*]
+# Unix-style newlines with a newline at the end of every file
 end_of_line = lf
 insert_final_newline = true
-charset = utf-8im_trailing_whitespace = true
+charset = utf-8
+trim_trailing_whitespace = true
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Unix-style newlines with a newline ending every file*]
end_of_line = lf
insert_final_newline = true
charset = utf-8im_trailing_whitespace = true
# Unix-style newlines with a newline at the end of every file
end_of_line = lf
insert_final_newline = true
charset = utf-8
trim_trailing_whitespace = true
🤖 Prompt for AI Agents
In examples/green-house-migration/.editorconfig around lines 6 to 9, the global
settings line is malformed (a broken comment marker and merged keys). Replace
the corrupted lines with proper separate properties: ensure the comment is
fixed/removed, set end_of_line = lf and insert_final_newline = true on their own
lines, and split the merged "charset = utf-8im_trailing_whitespace = true" into
two valid lines "charset = utf-8" and "trim_trailing_whitespace = true".


# Python files
[*.py]
indent_style = space
indent_size =4

# YAML files
[*.[object Object]yml,yaml}]
indent_style = space
indent_size =2

Comment on lines +17 to +20
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

YAML section selector is corrupted.

Pattern should match yml/yaml; current selector includes “[object Object]” and mismatched braces.

-[*.[object Object]yml,yaml}]
+[*.{yml,yaml}]
 indent_style = space
-indent_size =2
+indent_size = 2
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
[*.[object Object]yml,yaml}]
indent_style = space
indent_size =2
[*.{yml,yaml}]
indent_style = space
indent_size = 2
🤖 Prompt for AI Agents
In examples/green-house-migration/.editorconfig around lines 17 to 20, the YAML
section selector is corrupted (it currently contains “[object Object]” and
mismatched braces). Replace the malformed selector with a correct glob that
targets yml and yaml files (use a pattern with brace expansion for extensions)
and keep the existing indent_style and indent_size settings; ensure the selector
syntax uses proper brackets and commas so the editor recognizes both .yml and
.yaml files.

# JSON files
[*.json]
indent_style = space
indent_size = 2

# Markdown files
[*.md]
trim_trailing_whitespace = false

# JavaScript files
[*.{js,jsx,ts,tsx}]
indent_style = space
indent_size =2

# HTML files
[*.html]
indent_style = space
indent_size = 2# CSS files
[*.css]
indent_style = space
indent_size = 2
Comment on lines +35 to +41
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Split HTML/CSS blocks; current line merges a value and a comment.

As written, indent_size = 2# CSS files makes the value invalid and may break parsing.

 [*.html]
 indent_style = space
-indent_size = 2# CSS files
-[*.css]
-indent_style = space
-indent_size = 2
+indent_size = 2
+
+# CSS files
+[*.css]
+indent_style = space
+indent_size = 2
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# HTML files
[*.html]
indent_style = space
indent_size = 2# CSS files
[*.css]
indent_style = space
indent_size = 2
# HTML files
[*.html]
indent_style = space
indent_size = 2
# CSS files
[*.css]
indent_style = space
indent_size = 2
🤖 Prompt for AI Agents
In examples/green-house-migration/.editorconfig around lines 35 to 41, the HTML
and CSS blocks are merged on one line so the comment `# CSS files` attaches to
the value making `indent_size = 2# CSS files` invalid; split the blocks and
comments onto separate lines so the HTML block ends with `indent_size = 2`, then
add a blank line or a new comment line before the CSS block header `[*.css]` and
its `indent_style`/`indent_size` entries, ensuring no trailing comment text is
appended to the value.

Loading