aws / aws/aws-cli

CodeArtifact login: auth token leaked unredacted in CommandFailedError via subprocess stderr

Open Beginner friendly
#10,575 0 comments 0 reactions 0 assignees View on GitHub
codeartifact login investigating p2
Dominant language
Python
Stars
17.3k
Forks
4.6k
Avg merge
1d 7h
Merged PRs (30d)
21

Description

## Summary

`awscli/customizations/codeartifact/login.py`'s `CommandFailedError` is meant to scrub the CodeArtifact authorization token out of error messages before they are shown to the user / logged, but it only redacts the token from `str(called_process_error)` — the decoded `stderr` from the failed subprocess is appended **unredacted**.

```python
class CommandFailedError(Exception):
def __init__(self, called_process_error, auth_token):
msg = str(called_process_error).replace(auth_token, '******')
if called_process_error.stderr is not None:
msg += (
f' Stderr from command:\n'
f'{called_process_error.stderr.decode(get_stderr_encoding())}'
)
Exception.__init__(self, msg)
```

`str(subprocess.CalledProcessError(...))` only ever includes the `cmd` list and return code — it never includes stderr content (verified directly against CPython's `subprocess` module). So the `.replace(auth_token, '******')` call can only ever redact the token if it appears inside the invoked `cmd` list; it can never redact anything appearing in `stderr`, which is concatenated onto the message afterward with no scrubbing at all.

## Why this is exploitable

For `NuGetLogin`/`DotNetLogin` (`login.py`), the auth token is passed as a literal CLI argument to the underlying tool:

```python
# NuGetLogin._get_configure_command
return [
'nuget', 'sources', operation,
'-name', source_name,
'-source', nuget_index_url,
'-username', 'aws',
'-password', self.auth_token
]
```

```python
# DotNetLogin._get_configure_command
command += [
'--username', 'aws',
'--password', self.auth_token
]
```

Both `nuget.exe` and `dotnet nuget` are known to echo the full failing command line (including all passed arguments) into stderr/output when a `sources add`/`nuget add source` operation fails — e.g. an invalid/duplicate source name, a malformed URL, or a permissions error. `PipLogin` similarly embeds the token directly in a URL (`https://aws:{auth_token}@{netloc}...`) passed to `pip config`, and pip/curl-style tools commonly print the failing URL (credentials included) on error.

## Impact

Running `aws codeartifact login --tool nuget|dotnet|pip` (etc.) in a scenario where the underlying tool invocation fails causes `CommandFailedError` to be raised with the live, unexpired CodeArtifact repository authorization token embedded in its message — printed to the user's terminal and captured by anything logging CLI output (CI logs, terminal scrollback capture, support tickets/bug reports). This defeats the explicit intent of the `.replace(auth_token, '******')` redaction in the same function.

## Suggested fix

Redact `auth_token` from the decoded `stderr` (and `stdout`, if present) before appending it to the message, not just from `str(called_process_error)`:

```python
class CommandFailedError(Exception):
def __init__(self, called_process_error, auth_token):
msg = str(called_process_error).replace(auth_token, '******')
if called_process_error.stderr is not None:
stderr = called_process_error.stderr.decode(get_stderr_encoding())
stderr = stderr.replace(auth_token, '******')
msg += f' Stderr from command:\n{stderr}'
Exception.__init__(self, msg)
```

## Environment

Reviewed against the current `aws-cli` source (vendored botocore confirmed unmodified/upstream; this bug is in aws-cli-specific customization code, not botocore).

Contributor guide

Open the contributing guide

Research direction

Start in awscli/customizations/codeartifact/login.py at CommandFailedError and inspect the NuGetLogin, DotNetLogin, and PipLogin failure paths. Verify how CalledProcessError stderr and any stdout are decoded and appended. Done means the auth token is redacted from the complete error message before it can be displayed or logged.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, python
Domain
cli, security
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
85/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.