Los archivos TAR se utilizan en copias de seguridad, distribución de software, canalizaciones de datos, contenedores y procesos de despliegue. El módulo tarfile de Python permite leerlos y extraerlos con facilidad, pero una extracción procedente de una fuente externa no debe tratarse como una simple copia de archivos. Un TAR manipulado puede intentar escribir fuera del directorio de destino, crear enlaces peligrosos, conservar permisos no deseados o sobrescribir archivos sensibles. La función extraction_filter permite definir una política explícita para decidir qué miembros son aceptables.
En esta guía aprenderás a usar los filtros integrados, crear reglas personalizadas, limitar recursos, trabajar en un directorio temporal y probar los casos de riesgo más importantes.
Por qué un TAR necesita validación
Cada miembro contiene nombre, ruta, tipo, permisos, propietario, grupo, tamaño y, en algunos casos, destino de enlace. Esos valores provienen del propio archivo. Un nombre como ../../config.py intenta salir de la carpeta prevista. Una ruta absoluta puede apuntar a una ubicación del sistema. Un enlace simbólico puede redirigir una escritura posterior a otro lugar.
Por eso, un TAR desconocido debe considerarse una entrada estructurada que necesita validación. El flujo seguro requiere un destino aislado, comprobación de rutas, límites de tamaño, lista de tipos permitidos y una respuesta clara cuando una entrada se rechaza.
Usar el filtro data
Para archivos que contienen datos comunes, la política data suele ser el mejor punto de partida.
from pathlib import Path
import tarfile
archivo = Path("copia.tar.gz")
destino = Path("datos_extraidos")
destino.mkdir(parents=True, exist_ok=True)
with tarfile.open(archivo, "r:gz") as tar:
tar.extractall(destino, filter="data")
El filtro se aplica mientras se evalúa cada miembro. Puede rechazar entradas inseguras o normalizar metadatos que no deberían conservarse en una importación de datos.
data, tar y fully_trusted
La política data favorece una extracción orientada a archivos de datos. La política tar conserva más características tradicionales del formato. fully_trusted es permisiva y solo debe usarse cuando el archivo sea realmente confiable, se haya generado en un entorno controlado y necesite mantener semántica avanzada del TAR.
Para cargas de usuarios, descargas, integraciones y copias recibidas de terceros, conviene elegir data. Una opción más permisiva debe ser una decisión técnica documentada, no un atajo.
Crear un filtro personalizado
Una aplicación puede necesitar reglas más estrictas. Por ejemplo, aceptar únicamente CSV, JSON y TXT, rechazar enlaces y archivos especiales, limitar el tamaño y normalizar permisos.
from pathlib import Path
import tarfile
EXTENSIONES = {".csv", ".json", ".txt"}
MAX_ARCHIVO = 20 * 1024 * 1024
def filtro_importacion(member, path):
nombre = Path(member.name)
if member.isdir():
return member
if not member.isfile():
return None
if nombre.suffix.lower() not in EXTENSIONES:
return None
if member.size > MAX_ARCHIVO:
return None
return member.replace(mode=0o600)
with tarfile.open("entrada.tar") as tar:
tar.extractall("temporal", filter=filtro_importacion)
Devolver None omite un miembro. Devolver el miembro lo acepta, opcionalmente con metadatos modificados. De esta forma, la política queda centralizada y es más fácil de revisar.
Rechazar enlaces innecesarios
Los enlaces simbólicos y los enlaces duros son útiles en archivos de sistema, pero la mayoría de las importaciones de datos no los necesita. Rechazarlos elimina una clase importante de redirecciones de ruta.
def sin_enlaces(member, path):
if member.issym() or member.islnk():
return None
return tarfile.data_filter(member, path)
La función reutiliza la protección del filtro estándar y añade una regla específica del proyecto. Es preferible componer reglas que reimplementar toda la lógica desde cero.
Limitar cantidad y tamaño total
Un archivo puede agotar recursos aunque cada elemento sea pequeño. Puede incluir cientos de miles de entradas o declarar un tamaño descomprimido enorme. Comprueba la cantidad de miembros y la suma total antes de extraer.
MAX_MIEMBROS = 5000
MAX_TOTAL = 500 * 1024 * 1024
with tarfile.open("entrada.tar") as tar:
miembros = tar.getmembers()
if len(miembros) > MAX_MIEMBROS:
raise ValueError("Demasiados miembros")
total = sum(m.size for m in miembros if m.isfile())
if total > MAX_TOTAL:
raise ValueError("Tamaño total excedido")
tar.extractall("temporal", members=miembros, filter="data")
Los límites deben adaptarse al espacio disponible, al volumen esperado y a los tiempos máximos de la aplicación.
Extraer en una zona temporal
No extraigas un TAR no confiable directamente en una carpeta activa. Crea un directorio nuevo, realiza la extracción, valida los resultados y mueve solamente los archivos aprobados al destino final.
Este diseño también facilita la limpieza. Si algo falla, se elimina todo el árbol temporal. Los datos activos permanecen intactos y el usuario no observa un resultado parcial.
Validar el contenido después
La validación del archivo es solo la primera capa. Un fichero con extensión .json puede contener datos inválidos. Analiza los formatos estructurados, valida esquemas, controla filas, codificación y campos obligatorios.
En el caso de plantillas, configuraciones o formatos ejecutables, aplica revisiones adicionales. La extensión del nombre no equivale a una validación real del contenido.
Errores y limpieza
No ignores las excepciones. Registra el identificador de la operación, el origen del TAR, el miembro rechazado y la razón de la política. Evita mostrar rutas internas o detalles sensibles al usuario final.
import tarfile
try:
with tarfile.open("entrada.tar") as tar:
tar.extractall("temporal", filter="data")
except tarfile.TarError as error:
raise RuntimeError("Archivo TAR inválido o inseguro") from error
Elimina siempre el directorio temporal cuando la operación no termina correctamente. En servicios continuos, los residuos pueden ocupar disco y complicar el diagnóstico.
Privilegios mínimos
El proceso de extracción debe ejecutarse con un usuario que no pueda modificar el sistema, el código de la aplicación, secretos ni datos de otros clientes. Los permisos del sistema de archivos son una segunda barrera importante.
Para cargas especialmente riesgosas, usa un contenedor, sandbox, proceso desechable o worker con límites de CPU, memoria, disco y tiempo.
Compatibilidad entre versiones
Si una biblioteca admite varias versiones de Python, comprueba la disponibilidad y el comportamiento del parámetro filter. No hagas una degradación silenciosa hacia una extracción insegura. Cuando esta protección sea un requisito, establece una versión mínima del intérprete.
Pruebas recomendadas
Crea archivos de prueba con rutas normales, segmentos .., rutas absolutas, enlaces simbólicos, enlaces duros, archivos grandes, demasiados miembros, extensiones prohibidas, permisos extraños y cabeceras dañadas. Verifica que las entradas inseguras se rechacen y que el destino final permanezca sin cambios.
También prueba archivos válidos generados por cada sistema compatible. Una política segura debe ser estricta, pero predecible y bien documentada.
Observabilidad
Registra miembros aceptados y rechazados, tamaño declarado, duración, errores de limpieza y nombre de la política. Estas métricas ayudan a detectar abuso, integraciones rotas o cambios inesperados en el productor del archivo.
Lecturas relacionadas
Consulta también zipfile.Path en Python, os.path.splitroot en Python, pathlib.Path.info en Python y sqlite3 autocommit en Python. Para detalles oficiales, revisa la documentación de tarfile y la documentación de pathlib.
Conclusión
tarfile extraction_filter convierte la extracción en una operación gobernada por una política. Para archivos externos, empieza con filter="data", rechaza enlaces y tipos innecesarios, impone límites, utiliza una carpeta temporal, valida el contenido y ejecuta el proceso con privilegios mínimos. Estas capas crean un flujo TAR mucho más seguro y mantenible en Python.







