View a markdown version of this page

Pacotes de bloqueio na página da versão - CodeArtifact

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Pacotes de bloqueio na página da versão

Importante

O controle de idade de versões não protege contra vulnerabilidades descobertas em versões existentes que já passaram pela janela de quarentena. Use CodeArtifact com o Amazon Inspector para verificação de vulnerabilidades de pacotes estabelecidos.

Quando uma versão do pacote é publicada em um registro público, o registro registra o timestamp de publicação. CodeArtifact preserva esses carimbos de data/hora originais do upstream quando armazena em cache pacotes de conexões externas. Você pode ler esses carimbos de data/hora em seu CI/CD funil e rejeitar versões que foram publicadas muito recentemente.

A maioria dos pacotes maliciosos é detectada e removida poucas horas após a publicação. Uma janela de quarentena de 3 a 7 dias bloqueia a maioria dos ataques à cadeia de suprimentos, incluindo confusão de dependências, invasão da conta do mantenedor e typosquatting.

nota

Os exemplos neste tópico consultam a URL do CodeArtifact repositório, que é o mesmo endpoint que seu gerenciador de pacotes usa para baixar pacotes. Todas as solicitações exigem autenticação. Passe um token de CodeArtifact autorização válido no Authorization: Bearer cabeçalho. Para obter um token, execute aws codeartifact get-authorization-token (veja o CI/CD exemplo mais adiante neste tópico para ver a invocação completa com --domain e--domain-owner).

Não use o publishedTime campo retornado por aws codeartifact describe-package-version para restrição de idade. Esse campo é preenchido no momento da ingestão. Para registros em que o horário de publicação original do upstream não foi capturado (incluindo pacotes ingeridos antes da introdução da captura de timestamp por artefato e determinados caminhos de ingestão), ele volta silenciosamente para o horário da última atualização do registro. A resposta da API não indica qual dos dois valores você está lendo, então você não pode confiar nela como a data de publicação inicial. Em vez disso, use os campos por formato descritos neste tópico.

Os detalhes por formato são diferentes, mas o padrão de controle é o mesmo para todos os formatos: leia o timestamp de publicação upstream de cada versão resolvida, compare-o com o limite de quarentena (a hora atual menos a janela escolhida) e falhe na compilação se alguma versão for mais recente que o limite. Se você usar mais de um formato de pacote, aplique o mesmo padrão com o campo específico do formato mostrado abaixo.

npm

CodeArtifact retorna o timestamp de publicação original do npmjs.org para cada versão no campo npm packument. time Muitos gerenciadores de pacotes e ferramentas de segurança leem esse campo nativamente. Isso inclui a npmMinimalAgeGate opção Yarn 4, a minimumReleaseAge configuração Renovate e a minimumReleaseAge configuração pnpm, todas as quais funcionam sem CodeArtifact modificação.

Solicitação:

curl -H "Authorization: Bearer $CODEARTIFACT_AUTH_TOKEN" \ https://my-domain-111122223333.d.codeartifact.us-east-1.amazonaws.com/npm/my-repo/axios

Resposta (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-chave: time["<version>"] — o valor é a data de publicação original em npmjs.org. Por exemplo, time["1.7.2"] retorna2024-05-21T16:58:04.163Z, que é o registro de data e hora exato registrado pelo npmjs.org quando essa versão foi publicada. Para determinar a idade, compare esse valor com a hora atual menos a janela de quarentena.

Maven

Para artefatos do Maven, CodeArtifact retorna o timestamp de publicação original do Maven Central no cabeçalho da resposta Last-Modified HTTP quando você baixa um arquivo (JAR, POM ou outro artefato).

Solicitação:

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

Cabeçalhos de resposta:

HTTP/2 200 content-type: application/xml Last-Modified: Fri, 26 Feb 2021 20:40:52 GMT content-length: 22672

Campo-chave: Last-Modified cabeçalho — esta é a data de publicação original do Maven Central. Compare-o com o limite de quarentena para determinar se o artefato é muito novo.

nota

O <lastUpdated> campo interno maven-metadata.xml reflete quando seu cache CodeArtifact foi atualizado pela última vez, não a data de publicação inicial. Não use maven-metadata.xml carimbos de data/hora para definir a idade.

NuGet

Para NuGet pacotes, CodeArtifact retorna o timestamp de publicação original do nuget.org no published campo da resposta de registro V3.

Solicitação:

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

Resposta (abreviada, mostrando uma versão):

{ "items": [{ "items": [{ "catalogEntry": { "id": "Newtonsoft.Json", "version": "13.0.3", "published": "2023-03-08T07:42:54.647+00:00", "listed": true } }] }] }

Campo-chave: catalogEntry.published — esta é a data de publicação original do nuget.org. Por exemplo, "2023-03-08T07:42:54.647+00:00" significa que Newtonsoft.Json 13.0.3 foi publicado em 8 de março de 2023.

Carga (Ferrugem)

Para caixas de carga retiradas de crates.io, CodeArtifact preserva o carimbo de data/hora de publicação original na resposta da API crates.io V1. versions Consulte o endpoint da API V1 para obter uma caixa para ler o carimbo de data/hora por versão. created_at

Solicitação:

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-chave: O registro de created_at data e hora por versão na versions resposta V1 é a data de publicação original do crates.io.

nota

O Cargo usa o protocolo de índice esparso (<prefix>/<crate>) para resolução normal de dependências. O índice esparso retornavers,, cksumyanked, e features para cada versão, mas não inclui um carimbo de data e hora de publicação. Para limitar a idade das dependências do Cargo, consulte a API V1 mostrada acima em uma etapa separada do seu pipeline. O padrão cargo build e cargo update os comandos não chamam a API V1.

PyPI

Para pacotes Python, CodeArtifact suporta PEP 691 (JSON Simple API) e PEP 700, que incluem o upload-time campo para cada arquivo de distribuição.

Solicitação:

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/

Resposta (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-chave: upload-time — esta é a data de publicação original do PyPI. Ferramentas como uv oferecem suporte nativo a isso:

# Only install versions published before a specific date uv pip install --exclude-newer 2026-05-01T00:00:00Z -r requirements.txt
nota

A API JSON PEP 691 requer o cabeçalho. Accept: application/vnd.pypi.simple.v1+json A API HTML Simple padrão não inclui carimbos de data/hora.

Para arquivos de distribuição ingeridos antes da introdução da captura no momento do upload por artefato (registros legados), o upload-time campo pode estar ausente das entradas. files[] Sua lógica de bloqueio deve tratar uma versão ausente upload-time como uma versão que ela não pode verificar e decidir se deseja permiti-la ou bloqueá-la de acordo com sua política.

Exemplo: bloqueio de pacotes npm em CI/CD

O script Python a seguir lê um package-lock.json arquivo, consulta o timestamp CodeArtifact de publicação de cada dependência e sai com um status diferente de zero se alguma versão for publicada na janela de quarentena.

#!/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 integração:

# 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

Exemplo de saída quando um pacote é bloqueado:

BLOCKED: 1 package(s) newer than 72 hours: evil-package@1.0.0 (age: 2h, published 2026-06-03T08:30:00+00:00)

Exemplo de saída quando todos os pacotes são aprovados:

PASSED: all 847 packages older than 72 hours.

Ataques mitigados

Tipo de ataque Como funciona Como a restrição de idade ajuda
Confusão de dependência O atacante publica um pacote de alta versão com o mesmo nome de um pacote interno em um registro público. A versão maliciosa é totalmente nova. Bloqueado pela janela de quarentena.
Aquisição de conta O atacante compromete as credenciais do mantenedor e publica uma atualização maliciosa (por exemplo, fluxo de eventos). A nova versão está em vigor. A comunidade o detecta e o reverte dentro do período de quarentena.
Typosquatting O atacante publica um pacote com um nome semelhante ao de um pacote popular (por exemplo, lodashs em vez delodash). Todas as versões do pacote typosquat são novas. Todas as versões estão bloqueadas.
Star-jacking O atacante injeta malware em uma versão de patch de um pacote legítimo que ele controla. O patch malicioso é uma versão recém-publicada. Bloqueado até passar da janela de quarentena.

Resumo dos formatos suportados

Formato Onde ler o carimbo de data/hora de publicação Campo-chave Status
npm Resposta do pacote () GET /<package> time["<version>"] Available (Disponível)
Maven Cabeçalho de resposta HTTP no download do artefato Last-Modified Available (Disponível)
NuGet Índice de registro V3 catalogEntry.published Available (Disponível)
Carga Resposta às versões da API V1 created_at Available (Disponível)
PyPI API simples JSON PEP 691 upload-time Available (Disponível)