Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.
Bloquear paquetes en la antigüedad de la versión
importante
El límite de antigüedad de las versiones no protege contra las vulnerabilidades descubiertas en las versiones existentes que ya han pasado el período de cuarentena. CodeArtifact Utilícelo con Amazon Inspector para escanear las vulnerabilidades de los paquetes establecidos.
Cuando la versión de un paquete se publica en un registro público, el registro registra la fecha y hora de publicación. CodeArtifact conserva estas marcas de tiempo originales cuando almacena en caché los paquetes de conexiones externas. Puedes leer estas marcas de tiempo en tu CI/CD proceso y rechazar las versiones que se hayan publicado demasiado recientemente.
La mayoría de los paquetes maliciosos se detectan y eliminan a las pocas horas de su publicación. Un período de cuarentena de 3 a 7 días bloquea la mayoría de los ataques a la cadena de suministro, como la confusión de dependencias, la apropiación de cuentas por parte de los mantenedores y los errores tipográficos.
nota
Los ejemplos de este tema consultan la URL del CodeArtifact repositorio, que es el mismo punto final que utiliza el administrador de paquetes para descargar los paquetes. Todas las solicitudes requieren autenticación. Pase un token de CodeArtifact autorización válido en el Authorization: Bearer encabezado. Para obtener un token, ejecute aws codeartifact get-authorization-token (consulte el CI/CD ejemplo que aparece más adelante en este tema para ver la invocación completa con --domain y--domain-owner).
No utilice el publishedTime campo devuelto por aws codeartifact describe-package-version para determinar la edad. Este campo se rellena en el momento de la ingesta. En el caso de los registros en los que no se capturó la hora de publicación inicial original (incluidos los paquetes ingeridos antes de que se introdujera la captura de la marca de tiempo por artefacto y determinadas rutas de ingesta), vuelve silenciosamente a la hora de la última actualización del registro. La respuesta de la API no indica cuál de los dos valores está leyendo, por lo que no puede confiar en que sea la fecha de publicación inicial. En su lugar, utilice los campos por formato que se describen en este tema.
Los detalles por formato son diferentes, pero el patrón de selección es el mismo para todos los formatos: lee la fecha de publicación inicial de cada versión resuelta, compárala con el límite de cuarentena (la hora actual menos la ventana que hayas elegido) y no apruebes la compilación si alguna versión es más reciente que el límite. Si utilizas más de un formato de paquete, aplicas el mismo patrón con el campo específico del formato que se muestra a continuación.
npm
CodeArtifact devuelve la marca de tiempo de publicación original de npmjs.org para cada versión del campo npm packument. time Muchos gestores de paquetes y herramientas de seguridad leen este campo de forma nativa. Estas incluyen la npmMinimalAgeGate opción Yarn 4, la minimumReleaseAge configuración Renovate y la minimumReleaseAge configuración pnpm, todas las cuales funcionan sin CodeArtifact modificaciones.
Solicitud:
curl -H "Authorization: Bearer $CODEARTIFACT_AUTH_TOKEN" \ https://my-domain-111122223333.d.codeartifact.us-east-1.amazonaws.com/npm/my-repo/axios
Respuesta (abreviada):
{ "name": "axios", "time": { "1.6.0": "2023-10-26T21:15:55.685Z", "1.6.5": "2024-01-05T19:52:15.051Z", "1.7.0": "2024-05-19T20:25:03.615Z", "1.7.1": "2024-05-20T13:32:52.757Z", "1.7.2": "2024-05-21T16:58:04.163Z" } }
Campo clave: time["<version>"] — el valor es la fecha de publicación original de npmjs.org. Por ejemplo, time["1.7.2"] devuelve2024-05-21T16:58:04.163Z, que es la marca de tiempo exacta registrada por npmjs.org cuando se publicó esa versión. Para determinar la edad, compare este valor con la hora actual menos el período de cuarentena.
Maven
En el caso de los artefactos de Maven, CodeArtifact devuelve la marca de tiempo de publicación original de Maven Central en el encabezado de respuesta Last-Modified HTTP al descargar un archivo (JAR, POM u otro artefacto).
Solicitud:
curl -I -H "Authorization: Bearer $CODEARTIFACT_AUTH_TOKEN" \ https://my-domain-111122223333.d.codeartifact.us-east-1.amazonaws.com/maven/my-repo/\ org/apache/commons/commons-lang3/3.12.0/commons-lang3-3.12.0.pom
Encabezados de respuesta:
HTTP/2 200 content-type: application/xml Last-Modified: Fri, 26 Feb 2021 20:40:52 GMT content-length: 22672
Campo clave: Last-Modified encabezado: esta es la fecha de publicación original de Maven Central. Compáralo con el límite de cuarentena para determinar si el artefacto es demasiado nuevo.
nota
El <lastUpdated> campo interior maven-metadata.xml refleja cuándo se actualizó CodeArtifact por última vez su caché, no la fecha de publicación anterior. No utilices maven-metadata.xml marcas de tiempo para establecer límites de edad.
NuGet
En el caso de NuGet los paquetes, CodeArtifact devuelve la marca de tiempo de publicación original de nuget.org en el published campo de la respuesta de registro de la versión 3.
Solicitud:
curl -H "Authorization: Bearer $CODEARTIFACT_AUTH_TOKEN" \ https://my-domain-111122223333.d.codeartifact.us-east-1.amazonaws.com/nuget/my-repo/\ v3/registration4/newtonsoft.json/index.json
Respuesta (abreviada, que muestra una versión):
{ "items": [{ "items": [{ "catalogEntry": { "id": "Newtonsoft.Json", "version": "13.0.3", "published": "2023-03-08T07:42:54.647+00:00", "listed": true } }] }] }
Campo clave: catalogEntry.published — esta es la fecha de publicación original de nuget.org. Por ejemplo, "2023-03-08T07:42:54.647+00:00" significa que la versión Newtonsoft.Json 13.0.3 se publicó el 8 de marzo de 2023.
Carga (Rust)
En el caso de las cajas de carga extraídas de crates.io, CodeArtifact conserva la fecha de publicación original en la respuesta de la API V1 de crates.io. versions Consulta el punto final de la API V1 de una caja para leer la marca de tiempo de cada versión. created_at
Solicitud:
curl -H "Authorization: Bearer $CODEARTIFACT_AUTH_TOKEN" \ https://my-domain-111122223333.d.codeartifact.us-east-1.amazonaws.com/cargo/my-repo/\ api/v1/crates/serde/versions
Campo clave: la created_at marca de tiempo por versión de la versions respuesta de la versión 1 es la fecha de publicación original de crates.io.
nota
Cargo usa el protocolo de índice disperso () para una resolución de dependencias normal. <prefix>/<crate> El índice disperso devuelvevers, cksumyanked, y features para cada versión, pero no incluye una marca de tiempo de publicación. Para determinar las dependencias de Cargo en función de la antigüedad, consulta la API V1 que se muestra arriba en un paso independiente de tu proceso. El estándar cargo build y cargo update los comandos no llaman a la API V1.
PyPI
Para los paquetes de Python, CodeArtifact admite PEP 691 (API simple de JSON) y PEP 700, que incluyen el upload-time campo para cada archivo de distribución.
Solicitud:
curl -H "Authorization: Bearer $CODEARTIFACT_AUTH_TOKEN" \ -H "Accept: application/vnd.pypi.simple.v1+json" \ https://my-domain-111122223333.d.codeartifact.us-east-1.amazonaws.com/pypi/my-repo/simple/requests/
Respuesta (abreviada):
{ "files": [{ "filename": "requests-2.31.0-py3-none-any.whl", "upload-time": "2023-05-22T15:12:42.313790Z", "size": 62574, "url": "../../packages/requests/2.31.0/requests-2.31.0-py3-none-any.whl" }] }
Campo clave: upload-time — esta es la fecha de publicación original de PyPI. Herramientas como estas uv admiten esto de forma nativa:
# Only install versions published before a specific date uv pip install --exclude-newer 2026-05-01T00:00:00Z -r requirements.txt
nota
La API JSON del PEP 691 requiere el Accept: application/vnd.pypi.simple.v1+json encabezado. La API HTML Simple predeterminada no incluye marcas de tiempo.
En el caso de los archivos de distribución ingresados antes de que se introdujera la captura del tiempo de carga por artefacto (registros antiguos), es posible que el upload-time campo no aparezca en las entradas. files[] Tu lógica de bloqueo debe tratar la versión que falta upload-time como una versión que no se puede verificar y decidir si la permites o bloquea según tu política.
Ejemplo: bloquear paquetes npm en CI/CD
La siguiente secuencia de comandos de Python lee un package-lock.json archivo, consulta CodeArtifact la marca de tiempo de publicación de cada dependencia y sale con un estado distinto de cero si se publicó alguna versión dentro de la ventana de cuarentena.
#!/usr/bin/env python3 """ gate_package_age.py - Block npm packages published too recently. Reads package-lock.json, queries CodeArtifact for each dependency's publish timestamp, and rejects versions newer than QUARANTINE_HOURS. Environment variables: CODEARTIFACT_AUTH_TOKEN - from `aws codeartifact get-authorization-token` CODEARTIFACT_NPM_ENDPOINT - from `aws codeartifact get-repository-endpoint` QUARANTINE_HOURS - minimum version age in hours (default: 72) """ import json, os, sys, urllib.request from datetime import datetime, timezone, timedelta def get_publish_time(endpoint, token, package, version): """Fetch the publish timestamp for a specific version from CodeArtifact.""" url = f"{endpoint.rstrip('/')}/{package}" req = urllib.request.Request(url, headers={"Authorization": f"Bearer {token}"}) data = json.loads(urllib.request.urlopen(req, timeout=30).read()) time_str = data.get("time", {}).get(version) if not time_str: return None return datetime.fromisoformat(time_str.replace("Z", "+00:00")) token = os.environ["CODEARTIFACT_AUTH_TOKEN"] endpoint = os.environ["CODEARTIFACT_NPM_ENDPOINT"] quarantine_hours = int(os.environ.get("QUARANTINE_HOURS", "72")) cutoff = datetime.now(timezone.utc) - timedelta(hours=quarantine_hours) with open("package-lock.json") as f: lockfile = json.load(f) blocked = [] checked = 0 for path, info in lockfile.get("packages", {}).items(): if not path.startswith("node_modules/"): continue name = path.replace("node_modules/", "", 1) version = info.get("version") if not name or not version: continue checked += 1 pub_time = get_publish_time(endpoint, token, name, version) if pub_time and pub_time > cutoff: age_h = (datetime.now(timezone.utc) - pub_time).total_seconds() / 3600 blocked.append(f" {name}@{version} (age: {age_h:.0f}h, published {pub_time.isoformat()})") if blocked: print(f"BLOCKED: {len(blocked)} package(s) newer than {quarantine_hours} hours:") print("\n".join(blocked)) sys.exit(1) print(f"PASSED: all {checked} packages older than {quarantine_hours} hours.")
CI/CD integración:
# Step 1: Authenticate export CODEARTIFACT_AUTH_TOKEN=$(aws codeartifact get-authorization-token \ --domain my-domain --domain-owner 111122223333 \ --query authorizationToken --output text) export CODEARTIFACT_NPM_ENDPOINT=$(aws codeartifact get-repository-endpoint \ --domain my-domain --domain-owner 111122223333 \ --repository my-repo --format npm \ --query repositoryEndpoint --output text) # Step 2: Set quarantine window (72 hours = 3 days) export QUARANTINE_HOURS=72 # Step 3: Generate lockfile without installing npm install --package-lock-only # Step 4: Gate on age — fails if any dependency is too new python3 gate_package_age.py # Step 5: If gate passes, install npm ci
Ejemplo de salida cuando un paquete está bloqueado:
BLOCKED: 1 package(s) newer than 72 hours: evil-package@1.0.0 (age: 2h, published 2026-06-03T08:30:00+00:00)
Ejemplo de salida cuando se aprueban todos los paquetes:
PASSED: all 847 packages older than 72 hours.
Ataques mitigados
| Tipo de ataque | Funcionamiento | Cómo ayuda el control de edad |
|---|---|---|
| Confusión de dependencia | El atacante publica un paquete de versión alta con el mismo nombre que un paquete interno en un registro público. | La versión maliciosa es completamente nueva. Bloqueada por la ventana de cuarentena. |
| Adquisición de cuentas | El atacante pone en peligro las credenciales de un responsable y publica una actualización maliciosa (por ejemplo, una secuencia de eventos). | La nueva versión está disponible. La comunidad la detecta y la revierte dentro del período de cuarentena. |
| Tiposquateo | El atacante publica un paquete con un nombre similar al de un paquete popular (por ejemplo, lodashs en lugar de). lodash |
Todas las versiones del paquete typosquat son nuevas. Todas las versiones están bloqueadas. |
| Star-jacking | El atacante inyecta malware en una versión de parche de un paquete legítimo que controla. | El parche malicioso es una versión recién publicada. Bloqueado hasta que pase el período de cuarentena. |
Resumen de los formatos admitidos
| Formato | ¿Dónde leer la marca de tiempo de publicación | Campo clave | Status |
|---|---|---|---|
| npm | Respuesta de paquete () GET /<package> |
time["<version>"] |
Disponible |
| Maven | Encabezado de respuesta HTTP al descargar el artefacto | Last-Modified |
Disponible |
| NuGet | Índice de registro V3 | catalogEntry.published |
Disponible |
| Carga | Respuesta a las versiones de la API V1 | created_at |
Disponible |
| PyPI | API simple PEP 691 JSON | upload-time |
Disponible |