CodeArtifact login: auth token leaked unredacted in CommandFailedError via subprocess stderr
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 85/100
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.
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.
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:
# NuGetLogin._get_configure_command
return [
'nuget', 'sources', operation,
'-name', source_name,
'-source', nuget_index_url,
'-username', 'aws',
'-password', self.auth_token
]
# 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):
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).
- Dominant language
- Python
- Stars
- 17.3k
- Forks
- 4.7k
- Avg merge
- 1d 23h
- Merged PRs (30d)
- 25
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from aws/aws-cli
-
bug needs-triage
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
-
needs-triage
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
needs-triage
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
-
needs-triage
Difficulty 1/5 Under an hour Newbie friendliness 90/100
-
needs-triage
Difficulty 1/5 Under an hour Newbie friendliness 90/100
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100