

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
<a name="package-version-age-gating"></a>

**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
<a name="package-version-age-gating-npm"></a>

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"]` retorna`2024-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
<a name="package-version-age-gating-maven"></a>

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
<a name="package-version-age-gating-nuget"></a>

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)
<a name="package-version-age-gating-cargo"></a>

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 retorna`vers`,, `cksum``yanked`, 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
<a name="package-version-age-gating-pypi"></a>

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
<a name="package-version-age-gating-example"></a>

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
<a name="package-version-age-gating-attacks"></a>


| 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
<a name="package-version-age-gating-summary"></a>


| 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) | 