Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
49 changes: 49 additions & 0 deletions .github/workflows/idor-audit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Auditoria IDOR
on: [pull_request]

jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }

- name: Auditar arquivos alterados no PR
env:
API_URL: ${{ secrets.IDOR_API_URL }}
API_TOKEN: ${{ secrets.IDOR_API_TOKEN }}
run: |
set -euo pipefail
if ! git fetch --no-tags --depth=1 origin "${{ github.base_ref }}"; then
echo "::error::Falha ao buscar a base; abortando."; exit 1
fi
diff_out=$(git diff --name-only --diff-filter=ACMR "origin/${{ github.base_ref }}...")
mapfile -t files < <(printf '%s\n' "$diff_out" | grep -E '\.(py|js|ts)$' || true)
if [ "${#files[@]}" -eq 0 ]; then
echo "Nenhum arquivo .py/.js/.ts alterado. Nada a auditar."; exit 0
fi
status=0
for f in "${files[@]}"; do
[ -f "$f" ] || continue
case "$f" in
*.py) lang=python;; *.js) lang=javascript;; *.ts) lang=typescript;; *) continue;;
esac
echo "::group::Auditando $f"
code=$(jq -Rs . < "$f")
payload=$(jq -n --arg lang "$lang" --argjson code "$code" \
--arg repo "$GITHUB_REPOSITORY" --arg sha "${{ github.event.pull_request.head.sha }}" \
'{language:$lang, code:$code, source:"github_action", repo_full_name:$repo, commit_sha:$sha}')
resp=$(curl -sS -X POST "$API_URL/audits" -H "X-API-Key: $API_TOKEN" -H "Content-Type: application/json" -d "$payload")
echo "$resp" | jq -r '.findings[]? | " - [\(.severity)] \(.vuln_type) (\(.owasp_id) / \(.cwe_id)) na linha \(.line_start)\n \(.explanation)"'
n=$(echo "$resp" | jq -r '.n_findings // 0')
maxsev=$(echo "$resp" | jq -r '.max_severity // "nenhuma"')
echo "→ $n achado(s); severidade maxima: $maxsev"
if echo "$resp" | jq -e '.findings[]? | select(.severity=="critica")' >/dev/null; then
status=1
fi
echo "::endgroup::"
done
if [ "$status" -ne 0 ]; then
echo "::error::Achado(s) 'critica' encontrado(s) — merge bloqueado."
fi
exit $status
18 changes: 18 additions & 0 deletions exemplo_vuln_idor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"""Endpoint de DEMONSTRACAO — versao VULNERAVEL (IDOR / BOLA).

Busca o objeto somente pelo ID vindo da URL, sem checar se ele pertence ao
usuario autenticado. Qualquer pessoa logada troca o `item_id` na URL e le o
item de outro usuario.

Falha: IDOR / BOLA — OWASP API1:2023, CWE-639.
"""
from fastapi import Depends, FastAPI

app = FastAPI()


@app.get("/api/itens/{item_id}")
def get_item(item_id: int, current_user=Depends(get_current_user)):
# VULNERAVEL: filtra so por id e ignora o dono. Sem `Item.user_id ==
# current_user.id`, qualquer item de qualquer usuario e acessivel.
return db.query(Item).filter(Item.id == item_id).first()
Loading