> For the complete documentation index, see [llms.txt](https://docs.stepsecurity.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.stepsecurity.io/developer-machines/credentials.md).

# Credentials

The **Credentials** page shows which credential sources are in use across your developer machines, how many devices each one affects, and how much of that material is sitting in plaintext.

Credential files are what supply chain malware goes looking for. A malicious npm postinstall script or a compromised IDE extension does not need to break anything: it sweeps a known list of locations, reads `~/.aws/credentials`, `~/.npmrc`, and `~/.docker/config.json`, and sends what it finds to a remote server. That list is public, short, and the same on every machine.

This page gives you the same list for your own fleet, ahead of time. When the next compromised package is disclosed, you already know which sources are in play, how far each one spreads, and which machines hold the material.

{% hint style="info" %}
Credential-bearing files are read locally, using bounded reads, only far enough to determine whether concrete credential material is present and whether it is protected. No credential value, fragment, hash, fingerprint, or parser output is ever stored, logged, displayed, or sent off the device.
{% endhint %}

<figure><img src="/files/jHZA2IZLcM4bQ6mTqQth" alt=""><figcaption></figcaption></figure>

### How the page is organised

Three terms run through the page, and they count different things:

* A **source** is a tool that keeps credentials, such as AWS credentials or kubeconfig. There are thirteen, listed under Covered sources.
* A **location** is one credential file on one device. A developer with three SSH keys has three locations for that source.
* An **entry** is one credential inside a location. An AWS credentials file with two named profiles holds two entries.

So a source with 7 affected devices, 16 locations, and 16 entries is one tool, holding sixteen credential entries, spread across seven machines. Entries are counted as found. They are not validated against the provider, checked for expiry, or deduplicated across devices.

{% hint style="info" %}
Findings show where credential material was found during each device's latest scan. They do not tell you whether a credential is still active or valid, and the same credential present on two machines is counted on each of them rather than recognised as one credential. Read the counts as a map of where material sits, not as a count of distinct secrets.
{% endhint %}

### Where to start

* **The Plaintext devices column.** It is called out in red for a reason: on those devices the credential material for that source is stored without encryption or passphrase protection, so any process that can read the file can read it directly.
* **Sources that spread widest.** The list is a picture of blast radius. A source on most of your fleet is one where a single credential-stealing package reaches nearly everyone.
* **Filter by category.** **Cloud** and **Package registries** are where production keys and publishing tokens live. Not every developer needs either, and this is the view that shows who has them.

### Filters

**Category chips** scope the list to one of the five families, each showing how many sources in that family were observed:

* **Cloud**
* **Source control**
* **Package registries**
* **Containers**
* **Infrastructure**

The page also supports **Search sources** for free-text search across source names, and **Export CSV** to export the current view.

### The sources list

| Column                  | What it shows                                                                                                      |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------ |
| **Source**              | The tool that keeps the credentials, with its category beneath.                                                    |
| **Affected Devices**    | How many devices hold this source at all.                                                                          |
| **Plaintext devices**   | How many of those devices hold at least one entry stored without encryption or passphrase protection. Shown in red |
| **Locations**           | How many credential files were found across the fleet for this source.                                             |
| **Credential entries**  | How many reported credential entries those files hold                                                              |
| **Last observed (GMT)** | When a device last reported this source.                                                                           |

Where **Locations** exceeds **Affected devices**, some machines hold more than one file for that source, which is normal for SSH keys and for developers juggling several kubeconfigs. Where **Credential entries** exceeds **Locations**, some files hold several credentials, which is normal for an AWS credentials file with multiple profiles or a `.netrc` covering several hosts.

### Source details

Select any source to open its detail panel.

<figure><img src="/files/PcgyNcbZXjB7dRwLiY9J" alt=""><figcaption></figcaption></figure>

Six figures summarise the source across the fleet:

| Figure                 | What it counts                                                                        |
| ---------------------- | ------------------------------------------------------------------------------------- |
| **Affected**           | Devices holding this source.                                                          |
| **Plaintext**          | Devices holding at least one entry stored without encryption or passphrase protection |
| **Protected**          | Devices holding at least one encrypted entry.                                         |
| **Locations**          | Credential files found across those devices.                                          |
| **Credential entries** | Individual credentials in those files.                                                |
| **In plaintext**       | How many of those entries are stored without encryption or passphrase protection.     |

The Plaintext and Protected device counts can overlap, and often do. A developer with one passphrase-protected SSH key and one without counts on both sides, which is exactly the machine worth looking at.

**Affected devices** lists every device holding the source, searchable by name. Each row shows the device, whether its entries are **Plaintext**, **Protected**, or both, the user account, platform, and device identifier, and a summary in the form `3 locations · 3 entries (2 plaintext)` with when it was last seen. **View device** opens that machine.

### Protection

| State         | What it means                                                                                                                            |
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| **Plaintext** | The material is stored without encryption or passphrase protection, so a process that can read the file can read the credential directly |
| **Protected** | The material is present but not readable as stored, because it is encrypted, passphrase-protected, or hardware-backed                    |

Protection describes how the material is guarded, not how sensitive it is. A plaintext registry token and a plaintext cloud key are both readable by anything running as that user, which on a developer machine includes every package postinstall script, every IDE extension, and every AI agent with shell access.

{% hint style="info" %}
**Protected** currently applies to encrypted, passphrase-protected, or hardware-backed private-key material. That is most often an SSH private key, and it also covers supported private keys embedded in a kubeconfig `client-key-data` field. Sources that store credentials in a form their tool reads directly are reported as Plaintext.
{% endhint %}

### What counts as an entry

An entry means credential material is in the file: a concrete value in a field the tool consumes as authentication, or a structurally valid private key. A Docker configuration holding a registry auth token counts. So does an AWS credentials file with a key in it, and an `.npmrc` carrying a publish token.

A file that only names a credential kept somewhere else does not. That includes a field whose whole value is an environment variable reference the tool expands at read time, a configuration that defers to a credential helper or the system keychain, and a file a tool wrote as an empty placeholder. These are not omissions. The credential genuinely is not in that file.

A file that could not be read, or that this version of the agent could not interpret, is recorded as incomplete rather than as clean. An unreadable credential file never resolves to "this machine holds nothing".

### Covered sources

Thirteen sources across five categories.

| Source                                       | Category           | macOS and Linux                                                 | Windows                                                                 |
| -------------------------------------------- | ------------------ | --------------------------------------------------------------- | ----------------------------------------------------------------------- |
| AWS credentials                              | Cloud              | `$HOME/.aws/credentials`                                        | `%USERPROFILE%\.aws\credentials`                                        |
| AWS config                                   | Cloud              | `$HOME/.aws/config`                                             | `%USERPROFILE%\.aws\config`                                             |
| Google Cloud application default credentials | Cloud              | `$HOME/.config/gcloud/application_default_credentials.json`     | `%APPDATA%\gcloud\application_default_credentials.json`                 |
| SSH private keys                             | Source control     | `$HOME/.ssh`                                                    | `%USERPROFILE%\.ssh`                                                    |
| Git credential store                         | Source control     | `$HOME/.git-credentials` and `$XDG_CONFIG_HOME/git/credentials` | *(same, with `$XDG_CONFIG_HOME` defaulting to `%USERPROFILE%\.config`)* |
| netrc                                        | Source control     | `$HOME/.netrc`                                                  | `%USERPROFILE%\_netrc`                                                  |
| GitHub CLI hosts                             | Source control     | `$HOME/.config/gh/hosts.yml`                                    | `%APPDATA%\GitHub CLI\hosts.yml`                                        |
| npm configuration                            | Package registries | `$HOME/.npmrc`                                                  | `%USERPROFILE%\.npmrc`                                                  |
| PyPI configuration                           | Package registries | `$HOME/.pypirc`                                                 | `%USERPROFILE%\.pypirc`                                                 |
| Docker configuration                         | Containers         | `$HOME/.docker/config.json`                                     | `%USERPROFILE%\.docker\config.json`                                     |
| kubeconfig                                   | Containers         | `$HOME/.kube/config`                                            | `%USERPROFILE%\.kube\config`                                            |
| Terraform credentials                        | Infrastructure     | `$HOME/.terraform.d/credentials.tfrc.json`                      | `%APPDATA%\terraform.d\credentials.tfrc.json`                           |
| Vault token                                  | Infrastructure     | `$HOME/.vault-token`                                            | `%USERPROFILE%\.vault-token`                                            |

The Terraform credentials file is the one HCP Terraform and the Terraform CLI write their tokens to. `$XDG_CONFIG_HOME` defaults to `.config` under the developer's home on every platform, including Windows, and follows the variable where a developer has set one.

SSH private keys are counted one location per key file rather than one for the directory, because protection differs between keys and a key committed to a repository has to be identifiable on its own.

Where a tool reads several files at once, every location containing concrete credential material is counted. That applies to the git credential store, which reads both of its paths, and to kubeconfig, where each entry in a `KUBECONFIG` path list is its own location. For every other source, the highest-precedence location the tool would actually read is counted, because counting a superseded file would claim a credential is in use when the tool never looks at it.

#### Relocated credential files

Developers move these files, and probing only the default path would report such a machine as holding no credentials at all. Where a tool supports an environment variable that relocates its credential file, that variable is resolved from the developer's own session and searched ahead of the default path:

| Variable                      | Relocates                                                               |
| ----------------------------- | ----------------------------------------------------------------------- |
| `AWS_SHARED_CREDENTIALS_FILE` | AWS credentials                                                         |
| `AWS_CONFIG_FILE`             | AWS config                                                              |
| `GH_CONFIG_DIR`               | GitHub CLI hosts                                                        |
| `NPM_CONFIG_USERCONFIG`       | npm configuration                                                       |
| `DOCKER_CONFIG`               | Docker configuration                                                    |
| `KUBECONFIG`                  | kubeconfig, as a path list where every entry is read                    |
| `XDG_CONFIG_HOME`             | The git credential store and GitHub CLI hosts, for tools that honour it |

Paths are resolved from the signed-in developer's environment, read from their login shell on macOS and Linux and from their user environment on Windows, not from the agent's own environment, which belongs to the root or SYSTEM account the agent runs as.

### Requirements

Credential inventory requires Dev Machine Guard agent **v1.16.0 or later**. Devices on earlier agents keep reporting everything else and contribute nothing to this page.

{% hint style="info" %}
**macOS:** several of these locations are TCC protected, so the agent needs Full Disk Access to read them. Without it, those sources cannot be read and will be missing from this page. See MDM Deployment.
{% endhint %}

A scan that resolves no signed-in developer account reports no credential inventory rather than reporting the sources as absent.

### What is collected

Every location is an exact path rather than a directory to walk, and each one is a single size-capped read. No directory tree is traversed. The one exception is `.ssh`, which is listed a single level deep so that candidate private-key files can be inspected individually. Known public-key files, `config`, `known_hosts`, and other non-key files in that directory are skipped.

Never collected, from any source:

* The credential value
* Any fragment of a credential value
* A hash, digest, or fingerprint of a credential
* Any classification derived from the characters of a secret


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.stepsecurity.io/developer-machines/credentials.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
