A private package repository decides which code your builds trust, so its access policies, the routes by which packages enter it and the tokens that build systems use to reach it are supply chain controls in their own right. AWS CodeArtifact provides the customer-side settings to manage all three: resource-based domain and repository policies, package origin controls and package group origin controls that govern publishing and upstream ingestion, upstream repositories and external connections to public registries, short-lived authorisation tokens, interface VPC endpoints and KMS encryption of domain assets. This guide explains how each control works, how to design a domain and repository layout that resists dependency substitution, and what to monitor. It is for platform and DevOps engineers, AppSec teams and AWS administrators who run package repositories for builds. The wider discipline is covered in the Malicious Package and Dependency Confusion Guide; this guide focuses on the CodeArtifact settings.
This is an independent guide from NHI Mgmt Group, based on AWS's public documentation for CodeArtifact as of November 2026. It is not sponsored or reviewed by AWS. Product features change, so confirm settings against AWS's current documentation.
Key takeaways
- Origin controls are the core defence against dependency substitution. Each package has Publish and Upstream settings, and a package first published internally defaults to Publish ALLOW and Upstream BLOCK, so a public package with the same name cannot be pulled in.
- Package groups set policy at scale. Package group origin controls (PUBLISH, EXTERNAL_UPSTREAM, INTERNAL_UPSTREAM) apply to whole namespaces, and a BLOCK always overrides an ALLOW.
- Domain and repository policies combine. An action is allowed if either policy allows it and nothing explicitly denies it, so review both together and use explicit denies for hard limits.
- Keep authorisation tokens short-lived. Tokens default to 12 hours; set durationSeconds as low as 900, or 0 in an assumed-role session to match the session's remaining time, and keep them in an environment variable, not a file.
- CloudTrail records package reads. Every request, including ReadFromRepository from package managers, is logged with the package name and version, giving a full download audit trail.
How identity and access work in AWS CodeArtifact
CodeArtifact organises packages into domains, which hold repositories, which hold packages. Access is decided by IAM identity-based policies together with two resource-based policies: a domain policy and a repository policy. AWS documents the evaluation rules:
- An explicit Deny in any domain or repository policy overrides an Allow elsewhere.
- An action does not need to be allowed in every resource policy; one Allow (with no Deny) is enough.
- A principal in another account needs at least one resource policy Allow and at least one identity-based policy Allow.
- The domain owner and repository administrator can be granted access through identity-based policy alone.
- PutDomainPermissionsPolicy and PutRepositoryPermissionsPolicy do not evaluate the existing policy on that resource, which prevents owners locking themselves out.
| Policy | Scope | Typical use | Key actions |
|---|---|---|---|
| Domain policy | The domain and every resource in it | Cross-account access to the domain, who can create repositories and obtain tokens | codeartifact:GetAuthorizationToken, codeartifact:CreateRepository, codeartifact:ListRepositoriesInDomain, codeartifact:DescribeDomain |
| Repository policy | One repository | Who can read from or publish to that repository | codeartifact:ReadFromRepository, codeartifact:PublishPackageVersion, codeartifact:PutPackageMetadata |
| IAM identity policy | The user or role | Developers, build roles, administrators | All of the above, plus sts:GetServiceBearerToken for tokens |
| VPC endpoint policy | Requests through one endpoint | Limiting which principals and actions use the private path | Any CodeArtifact action |
By default only the owning account can create and access repositories in a domain, and AWS notes that a domain policy is not needed when the domain and all its repositories are owned and used by a single account. Two scoping details matter for least privilege: ReadFromRepository cannot be scoped to a package ARN (a principal reads all packages in a repository or none), while PublishPackageVersion takes a package ARN of the form arn:aws:codeartifact:region:account:package/domain/repository/format/namespace/name, so publishing can be limited to specific packages or namespaces. Maven publishing also needs PutPackageMetadata, and NuGet publishing also needs ReadFromRepository on the repository.
Decision guidance: because read access is per repository, use repository boundaries to separate audiences: for example, a repository for released internal packages that all builds read, and team repositories that only their owners publish to. A single shared domain gives one place, the domain policy, to control cross-account access for the whole organisation. Separate domains make sense where business units need fully independent administration or encryption keys.
Admin roles and privileged access
- Domain policy administration: PutDomainPermissionsPolicy changes who in other accounts can reach the domain. AWS states you cannot grant another account permission to update the domain's resource policy through a resource policy, so keep this action with a small administrator role in the owning account. Use the revision value returned by the put command with --policy-revision so you overwrite the version you expect.
- Repository policy and origin configuration: PutRepositoryPermissionsPolicy, PutPackageOriginConfiguration and UpdatePackageGroupOriginConfiguration change who can publish and where packages can come from. Treat them as privileged and route changes through infrastructure as code with review.
- Upstream and external connection changes: adding an upstream requires AssociateWithDownstreamRepository on the upstream repository; adding an external connection opens a path to a public registry. Restrict both to platform administrators.
- Package deletion and disposal: actions that delete or dispose of package versions affect build reproducibility. Grant them to release managers only.
- KMS key administration: domain assets are encrypted with a KMS key, so key policy changes or key disablement affect every repository in the domain. Keep key administration separate; see the AWS KMS Security Guide.
Root users cannot call GetAuthorizationToken, which keeps day-to-day package access on IAM identities. Administrators should use roles through IAM Identity Center or federation.
Integrations, API tokens and service accounts
Authorisation tokens
Package managers authenticate with a CodeArtifact authorisation token obtained through GetAuthorizationToken, either via aws codeartifact login (supported for dotnet, npm, nuget, pip, swift and twine) or aws codeartifact get-authorization-token for other clients. The caller needs both codeartifact:GetAuthorizationToken and sts:GetServiceBearerToken; AWS notes that sts:GetServiceBearerToken has no effect in a domain resource policy, so it belongs in the IAM user or role policy.
| Property | Documented value | Recommendation |
|---|---|---|
| Default lifetime | 12 hours (43,200 seconds) | Shorten for CI jobs and shared runners |
| durationSeconds range | 900 to 43,200 seconds | Match the job length, for example 900 to 3,600 seconds |
| Assumed-role sessions | Token lifetime is independent of the session by default; 0 ties it to the remaining session time | Use --duration-seconds 0 in pipelines that assume roles |
| Storage | AWS recommends the CODEARTIFACT_AUTH_TOKEN environment variable rather than a file | Avoid writing tokens to .npmrc, pip.conf or settings files that may be committed or cached |
| Early revocation | Tokens stay valid until expiry; deny access in IAM policy (temporary credentials) or modify or delete the IAM user | Keep a tested deny procedure for build roles |
| Logging | GetAuthorizationToken is logged with the token value hidden | Alert on token requests from unexpected principals |
A token carries the permissions of the identity that requested it, so the token's power is the build role's power. Give each pipeline its own role, scoped to ReadFromRepository on the repositories it consumes and PublishPackageVersion only on the package ARNs it releases. Prefer roles from your CI system's OIDC federation over IAM users with long-lived access keys. See the AWS CodeBuild and CodePipeline Security guide and the AWS Access Keys Security Guide.
Upstreams and external connections
A repository can have up to 10 upstream repositories and one external connection to a supported public registry. Packages requested through an upstream are retained in that upstream, and a downstream repository can reach a public registry transitively through an upstream that has the external connection. This makes the upstream graph part of your access model: anyone who can read the downstream repository can cause public packages to be fetched and retained through the chain. A common, documented pattern is a single repository holding the external connection, with internal repositories listing it as an upstream, combined with package group rules that allow external ingestion only through named repositories.
Package origin controls
Per-package origin controls have two settings that must be set together:
| How the package first entered the repository | Default Publish | Default Upstream | Effect |
|---|---|---|---|
| Published directly (internal package) | ALLOW | BLOCK | Public versions with the same name cannot be ingested |
| Ingested from a public source | BLOCK | ALLOW | Nobody can publish over the public package internally |
| Package group has a BLOCK or ALLOW_SPECIFIC_REPOSITORIES restriction | ALLOW | ALLOW | Package defers to the group's settings |
| Packages created before about May 2022 | ALLOW | ALLOW | Set origin controls manually |
A package with both settings ALLOW defers to its package group, and a BLOCK at either level wins. Set controls with put-package-origin-configuration or in the console under Origin controls. Review older packages first, since they may still have both settings ALLOW.
The CodeArtifact security documentation also describes dependency substitution attacks and gating packages on version age, which can add a delay before newly published public versions are used; review the current documentation for the settings available in your Region.
Package group origin controls
Package groups apply origin rules to a namespace pattern, for example /npm/space/anycompany~ in AWS's example. Three restriction types (PUBLISH, EXTERNAL_UPSTREAM, INTERNAL_UPSTREAM) each take ALLOW, BLOCK, ALLOW_SPECIFIC_REPOSITORIES or INHERIT, with an allowed repository list for each restriction set to ALLOW_SPECIFIC_REPOSITORIES. For your organisation's internal scopes or prefixes, set EXTERNAL_UPSTREAM to BLOCK, so no public package can ever enter under those names, and set PUBLISH to ALLOW_SPECIFIC_REPOSITORIES so only release repositories accept new versions. For public ecosystems, allow EXTERNAL_UPSTREAM only through the repository that holds the external connection. Confirm pattern syntax and matching behaviour in AWS's current package group documentation before rollout.
Network path and encryption
CodeArtifact supports interface VPC endpoints through AWS PrivateLink, so builds in private subnets can reach it without an internet gateway or NAT device. Endpoints are Region-specific, support Amazon-provided DNS (use conditional forwarding for your own DNS), and need a security group allowing inbound TCP 443 from the private subnets. AWS's VPC documentation also covers creating an S3 gateway endpoint and a VPC endpoint policy; follow it when building the private path. See the Amazon VPC Security Guide. Every domain encrypts its assets with a KMS key, either an AWS managed key or a customer managed key chosen at creation; AWS's example key policy grants kms:CreateGrant and kms:DescribeKey limited by kms:CallerAccount and kms:ViaService for CodeArtifact.
Logging and detection
CloudTrail captures all CodeArtifact API calls with event source codeartifact.amazonaws.com, including requests from package manager clients; a single client command often produces several events. Package fetches appear as ReadFromRepository with the domain, repository, format, package and version in requestParameters, and the HTTP method and URI in additionalEventData. For GetAuthorizationToken, the token in the response is recorded as HIDDEN_DUE_TO_SECURITY_REASONS. Up to three accounts receive an event: the caller's, the repository administrator's and the domain owner's, which lets a central platform account see cross-account use.
| Signal | Events | Why it matters |
|---|---|---|
| Policy changes | PutDomainPermissionsPolicy, PutRepositoryPermissionsPolicy, delete variants | New cross-account or publish access |
| Origin control changes | PutPackageOriginConfiguration, UpdatePackageGroupOriginConfiguration | Reopening a path for dependency substitution |
| Upstream changes | UpdateRepository, AssociateExternalConnection | New routes from public registries |
| Token requests | GetAuthorizationToken | Unexpected principals, accounts or volumes |
| Publishing | PublishPackageVersion | Releases outside the release pipeline |
| Package reads | ReadFromRepository | Download audit: which builds consumed a version later found to be malicious |
Keep ReadFromRepository events long enough to answer "which builds pulled this version" during an incident. See the AWS CloudTrail Guide. These controls address compromise of software dependencies (MITRE ATT&CK T1195.001) and misuse of valid cloud accounts (T1078.004).
Metrics:
- Percentage of internal package names covered by a package group with EXTERNAL_UPSTREAM set to BLOCK.
- Number of packages with both Publish and Upstream set to ALLOW, trending down.
- Number of repositories with an external connection (target: one per ecosystem).
- Median token lifetime requested by CI roles.
- Number of principals with PublishPackageVersion on wildcard package ARNs.
- Percentage of build traffic using VPC endpoints.
Hardening baseline
- Inventory: list domains, repositories, upstream graphs, external connections, domain and repository policies, and packages with both origin settings ALLOW.
- Layout: one repository per ecosystem holding the external connection; internal and release repositories use it as an upstream.
- Package groups: create groups for internal scopes and prefixes with EXTERNAL_UPSTREAM BLOCK and PUBLISH limited to release repositories. Pilot on one namespace, confirm builds resolve, then extend. Roll back by setting the restriction to INHERIT.
- Per-package review: fix packages created before about May 2022 and any package with both settings ALLOW that should be internal only.
- Policies: grant cross-account access in the domain policy with aws:PrincipalOrgID for your organisation, grant ReadFromRepository per repository, and scope PublishPackageVersion to package ARNs.
- Tokens: move CI to role-based credentials with short token lifetimes or --duration-seconds 0, and keep tokens in environment variables.
- Network and encryption: add interface VPC endpoints for private builds; choose a customer managed KMS key for new domains where your policy requires one.
- Monitoring: alerts on policy, origin, upstream and publishing changes, with ReadFromRepository retained for investigations.
Small and large organisations: a single team can run one domain, one external-connection repository and one internal repository, with package origin defaults and short tokens. Larger organisations add package groups per business unit, a central domain shared through aws:PrincipalOrgID, and policy changes managed as code with review.
Framework mapping
| Control | CodeArtifact setting | NIST SP 800-53 Rev 5 | NIST CSF 2.0 |
|---|---|---|---|
| Supply chain controls | Origin controls, package groups, upstream design | SR-3, SR-11 | GV.SC-05 |
| Least privilege | Repository policies, package ARN scoping | AC-6 | PR.AA-05 |
| Access enforcement | Domain and repository policy evaluation | AC-3 | PR.AA-05 |
| Authenticator management | Short-lived authorisation tokens | IA-5 | PR.AA-05 |
| Boundary protection | Interface VPC endpoints | SC-7 | PR.DS-02 |
| Data at rest | KMS-encrypted domain assets | SC-28 | PR.DS-01 |
| Audit | CloudTrail, including ReadFromRepository | AU-2, AU-12 | DE.CM-01 |
Common misconfigurations
- Internal packages with Upstream ALLOW: a public package with the same name can be ingested. Set Upstream BLOCK or cover the namespace with a package group.
- External connections on many repositories: every one is a path from a public registry. Centralise on one repository per ecosystem.
- Tokens written to configuration files: they can be committed or cached on shared runners. Use the environment variable and short lifetimes.
- 12-hour tokens from 15-minute role sessions: the token outlives the session. Use --duration-seconds 0.
- Wildcard publish rights: PublishPackageVersion on repository/* for every build role. Scope to the packages each pipeline releases.
- Reviewing repository policies alone: the domain policy may grant the same action. Review both, and use explicit denies for hard limits.
Practitioner checklist
- Create package groups for internal namespaces with EXTERNAL_UPSTREAM BLOCK.
- Check origin controls on packages created before about May 2022.
- Hold each ecosystem's external connection in one repository used as an upstream.
- Restrict AssociateWithDownstreamRepository and external connection changes to administrators.
- Grant cross-account access in the domain policy with aws:PrincipalOrgID.
- Scope PublishPackageVersion to package ARNs per pipeline.
- Issue tokens to roles, not users, with short durationSeconds or 0 in role sessions.
- Keep tokens in CODEARTIFACT_AUTH_TOKEN, never in committed configuration files.
- Use interface VPC endpoints for builds in private subnets.
- Alert on policy, origin, upstream and publishing changes; retain ReadFromRepository events.
Standards and references
- AWS: Security in AWS CodeArtifact
- AWS: Editing package origin controls
- AWS: Package group origin controls
- AWS: Domain policies
- AWS: Repository policies
- AWS: AWS CodeArtifact authentication and tokens
- AWS: Working with upstream repositories
- AWS: CodeArtifact information in CloudTrail
Related NHI Mgmt Group resources: Malicious Package and Dependency Confusion Guide · Software Supply Chain Security Guide · AWS CodeBuild and CodePipeline Security · AWS KMS Security Guide