Skip to content

Commit

Permalink
Merge pull request #17 from mschwager/mschwager-fastapi-support
Browse files Browse the repository at this point in the history
Fix #5, add FastAPI support
  • Loading branch information
mschwager authored Feb 26, 2024
2 parents ba92a57 + 6ce127a commit 44f5195
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Support for Express routes defined on the app ([#16](https://github.com/mschwager/route-detect/issues/16))
- Support for Java Jakarta namespace ([#15](https://github.com/mschwager/route-detect/issues/15))
- Official support for Python 3.12
- Support for Python FastAPI (`fastapi`)

### Removed

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Web application HTTP route authn and authz bugs are some of the most common secu

Supported web frameworks (`route-detect` IDs in parentheses):

- Python: Django (`django`, `django-rest-framework`), Flask (`flask`), Sanic (`sanic`)
- Python: Django (`django`, `django-rest-framework`), Flask (`flask`), Sanic (`sanic`), FastAPI (`fastapi`)
- PHP: Laravel (`laravel`), Symfony (`symfony`), CakePHP (`cakephp`)
- Ruby: Rails\* (`rails`), Grape (`grape`)
- Java: JAX-RS (`jax-rs`), Spring (`spring`)
Expand Down
2 changes: 2 additions & 0 deletions routes/rules/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
DJANGO = CURDIR / "django.yml"
DJANGO_REST_FRAMEWORK = CURDIR / "django-rest-framework.yml"
SANIC = CURDIR / "sanic.yml"
FASTAPI = CURDIR / "fastapi.yml"
LARAVEL = CURDIR / "laravel.yml"
SYMFONY = CURDIR / "symfony.yml"
CAKEPHP = CURDIR / "cakephp.yml"
Expand All @@ -33,6 +34,7 @@
DJANGO,
DJANGO_REST_FRAMEWORK,
SANIC,
FASTAPI,
LARAVEL,
SYMFONY,
CAKEPHP,
Expand Down
80 changes: 80 additions & 0 deletions routes/rules/fastapi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
rules:
- id: fastapi-route-authenticated
patterns:
- pattern-either:
- pattern: |
@$APP.$METHOD($PATH, ...)
def $FUNC(..., token, ...):
...
- pattern: |
@$APP.$METHOD($PATH, ...)
def $FUNC(..., current_user, ...):
...
- pattern: |
@$APP.$METHOD($PATH, ...)
def $FUNC(..., auth_result, ...):
...
- metavariable-pattern:
metavariable: $METHOD
pattern-either:
- pattern: websocket
- pattern: get
- pattern: put
- pattern: post
- pattern: delete
- pattern: options
- pattern: head
- pattern: patch
- pattern: trace
message: Found authenticated FastAPI route
metadata:
references:
- https://fastapi.tiangolo.com/reference/apirouter
- https://fastapi.tiangolo.com/tutorial/security/first-steps/
- https://fastapi.tiangolo.com/tutorial/security/oauth2-jwt/
- https://auth0.com/blog/build-and-secure-fastapi-server-with-auth0/
route-detect:
fill: green
languages: [python]
severity: INFO
- id: fastapi-route-unauthenticated
patterns:
- pattern: |
@$APP.$METHOD($PATH, ...)
def $FUNC(...):
...
- pattern-not: |
@$APP.$METHOD($PATH, ...)
def $FUNC(..., token, ...):
...
- pattern-not: |
@$APP.$METHOD($PATH, ...)
def $FUNC(..., current_user, ...):
...
- pattern-not: |
@$APP.$METHOD($PATH, ...)
def $FUNC(..., auth_result, ...):
...
- metavariable-pattern:
metavariable: $METHOD
pattern-either:
- pattern: websocket
- pattern: get
- pattern: put
- pattern: post
- pattern: delete
- pattern: options
- pattern: head
- pattern: patch
- pattern: trace
message: Found unauthenticated FastAPI route
metadata:
references:
- https://fastapi.tiangolo.com/reference/apirouter
- https://fastapi.tiangolo.com/tutorial/security/first-steps/
- https://fastapi.tiangolo.com/tutorial/security/oauth2-jwt/
- https://auth0.com/blog/build-and-secure-fastapi-server-with-auth0/
route-detect:
fill: red
languages: [python]
severity: INFO
60 changes: 60 additions & 0 deletions tests/test_rules/fastapi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
from typing import Annotated, Union

from fastapi import APIRouter, Depends, FastAPI
from fastapi.security import OAuth2PasswordBearer
from pydantic import BaseModel

app = FastAPI()
router = APIRouter()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")


# ruleid: fastapi-route-unauthenticated
@app.get("/")
def read_root():
return {"Hello": "World"}


# ruleid: fastapi-route-unauthenticated
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}


# ruleid: fastapi-route-unauthenticated
@router.get("/users/")
def read_users():
return [{"name": "Rick"}, {"name": "Morty"}]


app.include_router(router)


# ruleid: fastapi-route-authenticated
@app.get("/items/")
async def read_items(token: Annotated[str, Depends(oauth2_scheme)]):
return {"token": token}


class User(BaseModel):
username: str
email: Union[str, None] = None
full_name: Union[str, None] = None
disabled: Union[bool, None] = None


def fake_decode_token(token):
return User(
username=token + "fakedecoded", email="[email protected]", full_name="John Doe"
)


async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
user = fake_decode_token(token)
return user


# ruleid: fastapi-route-authenticated
@app.get("/users/me")
async def read_users_me(current_user: Annotated[User, Depends(get_current_user)]):
return current_user

0 comments on commit 44f5195

Please sign in to comment.