

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

# Pacchetti di controllo sulla pagina della versione
<a name="package-version-age-gating"></a>

**Importante**  
Il version age gating non protegge dalle vulnerabilità rilevate nelle versioni esistenti che hanno già superato la finestra di quarantena. Utilizzalo CodeArtifact con Amazon Inspector per la scansione delle vulnerabilità di pacchetti consolidati.

Quando una versione del pacchetto viene pubblicata in un registro pubblico, il registro registra il timestamp di pubblicazione. CodeArtifact conserva questi timestamp originali originali quando memorizza nella cache i pacchetti da connessioni esterne. Puoi leggere questi timestamp nella tua CI/CD pipeline e rifiutare le versioni pubblicate troppo di recente.

La maggior parte dei pacchetti dannosi viene rilevata e rimossa entro poche ore dalla pubblicazione. Una finestra di quarantena da 3 a 7 giorni blocca la maggior parte degli attacchi alla catena di fornitura, tra cui la confusione legata alle dipendenze, l'acquisizione dell'account del manutentore e gli errori di battitura.

**Nota**  
Gli esempi in questo argomento interrogano l'URL del CodeArtifact repository, che è lo stesso endpoint utilizzato dal gestore di pacchetti per scaricare i pacchetti. Tutte le richieste richiedono l'autenticazione. Passa un token di CodeArtifact autorizzazione valido nell'`Authorization: Bearer`intestazione. Per ottenere un token, esegui `aws codeartifact get-authorization-token` (vedi l' CI/CD esempio più avanti in questo argomento per la chiamata completa con `--domain` and). `--domain-owner`  
Non utilizzare il `publishedTime` campo restituito da `aws codeartifact describe-package-version` for age gating. Questo campo viene compilato al momento dell'inserimento. Per i record in cui non è stata rilevata l'ora di pubblicazione originale (compresi i pacchetti importati prima dell'introduzione dell'acquisizione del timestamp per elemento e determinati percorsi di inserimento), torna silenziosamente all'ora dell'ultimo aggiornamento del record. La risposta dell'API non indica quale dei due valori stai leggendo, quindi non puoi fare affidamento su di essa come data di pubblicazione iniziale. Utilizzate invece i campi per formato descritti in questo argomento.

I dettagli in base al formato variano, ma lo schema di limitazione è lo stesso per tutti i formati: leggete il timestamp di pubblicazione originale per ogni versione risolta, confrontatelo con il limite di quarantena (l'ora corrente meno la finestra scelta) e fallite la compilazione se una versione è più recente del limite. Se utilizzi più di un formato di pacchetto, applichi lo stesso modello con il campo specifico del formato mostrato di seguito.

## npm
<a name="package-version-age-gating-npm"></a>

CodeArtifact restituisce il timestamp di pubblicazione originale di npmjs.org per ogni versione nel campo npm packument. `time` Molti gestori di pacchetti e strumenti di sicurezza leggono questo campo in modo nativo. Questi includono l'`npmMinimalAgeGate`opzione Yarn 4, l'`minimumReleaseAge`impostazione Renovate e l'`minimumReleaseAge`impostazione pnpm, che funzionano tutte senza modifiche. CodeArtifact 

**Richiesta:**

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

**Risposta (abbreviata):**

```
{
  "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 chiave:** `time["<version>"]` — il valore è la data di pubblicazione originale da npmjs.org. Ad esempio, `time["1.7.2"]` return`2024-05-21T16:58:04.163Z`, che è il timestamp esatto registrato da npmjs.org quando quella versione è stata pubblicata. Per limitare l'età, confronta questo valore con l'ora corrente, escludendo la finestra di quarantena.

## Maven
<a name="package-version-age-gating-maven"></a>

Per gli artefatti di Maven, CodeArtifact restituisce il timestamp di pubblicazione originale di Maven Central nell'intestazione di risposta `Last-Modified` HTTP quando scarichi un file (JAR, POM o altro elemento).

**Richiesta:**

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

**Intestazioni di risposta:**

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

**Campo chiave:** `Last-Modified` intestazione: questa è la data di pubblicazione originale di Maven Central. Confrontalo con il limite di quarantena per determinare se l'artefatto è troppo nuovo.

**Nota**  
Il `<lastUpdated>` campo interno `maven-metadata.xml` riflette l' CodeArtifact ultima data di aggiornamento della cache, non la data di pubblicazione originaria. Non utilizzare `maven-metadata.xml` timestamp per determinare l'età.

## NuGet
<a name="package-version-age-gating-nuget"></a>

Per NuGet i pacchetti, CodeArtifact restituisce il timestamp di pubblicazione originale di nuget.org nel campo della risposta di registrazione V3. `published`

**Richiesta:**

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

**Risposta (abbreviata, che mostra una versione):**

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

**Campo chiave:** `catalogEntry.published` — questa è la data di pubblicazione originale di nuget.org. Ad esempio, `"2023-03-08T07:42:54.647+00:00"` significa che Newtonsoft.Json 13.0.3 è stato pubblicato l'8 marzo 2023.

## Cargo (ruggine)
<a name="package-version-age-gating-cargo"></a>

Per le casse Cargo estratte da crates.io, CodeArtifact conserva il timestamp di pubblicazione originale nella risposta dell'API crates.io V1. `versions` Interroga l'endpoint dell'API V1 per cercare una cassa per leggere il timestamp per versione. `created_at`

**Richiesta:**

```
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 chiave:** il `created_at` timestamp per versione nella risposta V1 è la data di pubblicazione originale di crates.io. `versions`

**Nota**  
Cargo utilizza il protocollo sparse index () per la normale risoluzione delle dipendenze. `<prefix>/<crate>` L'indice sparse restituisce`vers`, `cksum``yanked`, e `features` per ogni versione, ma non include un timestamp di pubblicazione. Per eliminare le dipendenze di Cargo dall'età, interroga l'API V1 mostrata sopra in un passaggio separato della pipeline. Lo standard `cargo build` e `cargo update` i comandi non chiamano l'API V1.

## PyPI
<a name="package-version-age-gating-pypi"></a>

Per i pacchetti Python, CodeArtifact supporta PEP 691 (JSON Simple API) e PEP 700, che includono il `upload-time` campo per ogni file di distribuzione.

**Richiesta:**

```
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/
```

**Risposta (abbreviata):**

```
{
  "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 chiave:** `upload-time` — questa è la data di pubblicazione originale di PyPI. Strumenti come lo `uv` supportano in modo nativo:

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

**Nota**  
L'API JSON PEP 691 richiede l'intestazione. `Accept: application/vnd.pypi.simple.v1+json` L'API HTML Simple predefinita non include i timestamp.  
Per i file di distribuzione importati prima dell'introduzione dell'acquisizione del tempo di caricamento per elemento (record precedenti), il campo potrebbe non essere presente nelle voci in. `upload-time` `files[]` La vostra logica di controllo dovrebbe considerare una versione mancante `upload-time` come una versione che non può verificare e decidere se consentirla o bloccarla in base alla vostra politica.

## Esempio: Gating dei pacchetti npm in CI/CD
<a name="package-version-age-gating-example"></a>

Il seguente script Python legge un `package-lock.json` file, richiede il timestamp di CodeArtifact pubblicazione di ogni dipendenza ed esce con uno stato diverso da zero se una versione è stata pubblicata nella finestra di quarantena.

```
#!/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 integrazione:**

```
# 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
```

**Esempio di output quando un pacchetto è bloccato:**

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

**Esempio di output quando tutti i pacchetti passano:**

```
PASSED: all 847 packages older than 72 hours.
```

## Attacchi mitigati
<a name="package-version-age-gating-attacks"></a>


| Tipo di attacco | Come funziona | In che modo l'age gating aiuta | 
| --- | --- | --- | 
| Confusione di dipendenza | Attacker pubblica un pacchetto ad alta versione con lo stesso nome di un pacchetto interno in un registro pubblico. | La versione dannosa è nuova di zecca. Bloccato dalla finestra di quarantena. | 
| Acquisizione dell'account | L'aggressore compromette le credenziali del manutentore e pubblica un aggiornamento dannoso (ad esempio, event-stream). | La nuova versione è disponibile. La comunità lo rileva e lo ripristina entro il periodo di quarantena. | 
| Errore di battitura | Attacker pubblica un pacchetto con un nome simile a un pacchetto popolare (ad esempio, invece di). lodashs lodash | Tutte le versioni del pacchetto typosquat sono nuove. Tutte le versioni sono bloccate. | 
| Star-jacking | L'aggressore inserisce malware in una versione di patch di un pacchetto legittimo da lui controllato. | La patch dannosa è una versione appena pubblicata. Bloccato fino a quando non supera la finestra di quarantena. | 

## Riepilogo dei formati supportati
<a name="package-version-age-gating-summary"></a>


| Formato | Dove leggere il timestamp di pubblicazione | Campo chiave | Stato | 
| --- | --- | --- | --- | 
| npm | Risposta del pacchetto () GET /<package> | time["<version>"] | Disponibilità | 
| Maven | Intestazione di risposta HTTP durante il download degli artefatti | Last-Modified | Disponibilità | 
| NuGet | Indice di registrazione V3 | catalogEntry.published | Disponibilità | 
| Cargo | Risposta alle versioni dell'API V1 | created\_at | Disponibilità | 
| PyPI | API JSON semplice PEP 691 | upload-time | Disponibilità | 