`EventScrubber` doesn't scrub a request body that's a top level JSON array

Abierto Apto para principiantes
#7,543 1 comentario 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
2/5
Tiempo estimado
1-3 horas
Aptitud para principiantes
78/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
flask, python
Área
security

Línea de trabajo

Reproduce el problema con el repro.py proporcionado y, después, inspecciona EventScrubber.scrub_request, scrub_dict y scrub_list para rastrear cómo se manejan los datos de la solicitud. Usa las pruebas existentes del scrubber o añade cobertura para un array de nivel superior; el trabajo estará terminado cuando los valores anidados de password o api_key se filtren en los cuerpos de array igual que en los cuerpos de objeto.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

Waiting for: Product Owner
How do you use Sentry?

Sentry Saas (sentry.io)

Version

2.69.2 (also on master at 494ecb3)

Steps to Reproduce

When a request body parses to a top level JSON array, nothing in it gets scrubbed. The same secrets in an object body are filtered normally. No event_scrubber argument, no _experiments data collection config, default max_request_body_size. The integration and the transport in the snippet are only there to catch the event.

A top level array is the usual shape for a bulk endpoint, something like POST /api/v1/users/bulk with a list of records. If those records carry a password or an api_key, they leave the process in the clear. A team that spot checks a single object endpoint sees scrubbing work fine, so there's nothing to tip them off.

Python 3.13.15, Flask 3.1.3, sentry-sdk 2.69.2. Save this as repro.py and run it.

import json
import logging

import sentry_sdk
from flask import Flask
from sentry_sdk.integrations.flask import FlaskIntegration

events = []


class Capture(sentry_sdk.transport.Transport):
    def capture_envelope(self, envelope):
        for item in envelope.items:
            if item.headers.get("type") == "event":
                events.append(item.payload.json)


sentry_sdk.init(
    dsn="https://public@example.com/1",
    integrations=[FlaskIntegration()],
    transport=Capture(),
)

app = Flask(__name__)
app.logger.disabled = True
logging.getLogger("werkzeug").disabled = True


@app.route("/bulk", methods=["POST"])
def bulk():
    raise ValueError("boom")


@app.route("/single", methods=["POST"])
def single():
    raise ValueError("boom")


client = app.test_client()
client.post("/bulk", json=[{"user": "a", "password": "hunter2"}])
client.post("/single", json={"user": "a", "password": "hunter2"})
sentry_sdk.get_client().close()

print("array body :", json.dumps(events[0]["request"]["data"]))
print("object body:", json.dumps(events[1]["request"]["data"]))
Expected Result

The array body should come out filtered the same way the object body does:

array body : [{"password": "[Filtered]", "user": "a"}]
object body: {"password": "[Filtered]", "user": "a"}
Actual Result
array body : [{"password": "hunter2", "user": "a"}]
object body: {"password": "[Filtered]", "user": "a"}

EventScrubber.scrub_request calls scrub_dict on event["request"]["data"], and scrub_dict returns immediately when what it's given isn't a dict, so a list body stops scrubbing before it starts. The class already ships scrub_list, whose docstring says it walks a list and any nested lists and calls scrub_dict on every dictionary it finds, but it's never called on the request body.

This is separate from #7542, which is about how denylist keys are matched. Here the keys never get looked at at all. I have a fix and tests ready if you want a PR.

Lenguaje dominante
Python
Estrellas
2.2k
Forks
672
Merge medio
1 d 13 min
PR fusionados (30 d)
212

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de getsentry/sentry-python

Todos los issues de getsentry/sentry-python

Issues similares

Más issues de Python

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.