> ## Documentation Index
> Fetch the complete documentation index at: https://tashfiq.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# AE-SEC-002

> No raw secret patterns in MCP or adjacent config files — .mcp.json, .mcp.yml, .cursor/mcp.json, .claude/settings.json, claude_desktop_config.json, cline_mcp_settings.json, and any `*.pkl` file with path containing `mcp` or `config`.

**Rule ID:** AE-SEC-002 · **Severity:** <Badge color="red">Blocker</Badge> · **Category:** Secrets · **Auto-fixable:** No

<Warning>
  Charter never auto-fixes secret findings. Removing the literal value is not a complete fix — rotate the credential externally first. Assume it was exposed the moment it was committed.
</Warning>

## Why this rule

MCP configurations are read by the agent runtime before tools execute. Unlike source code that may only be read occasionally, MCP configs are intentionally agent-visible by design — every tool invocation passes through them (see the [MCP safety model](/docs/concepts/mcp-safety-model)). A raw credential here is exposed to every model, every session, and every tool-call log that processes this context.

## What triggers it

Charter scans tracked MCP configuration files for the same high-confidence credential patterns as AE-SEC-001:

| Pattern                      | Example prefix                    | Min length    |
| ---------------------------- | --------------------------------- | ------------- |
| OpenAI API token             | `sk-`                             | 20 characters |
| GitHub personal access token | `ghp_`                            | 30 characters |
| AWS access key ID            | `AKIA`                            | 16 characters |
| Slack bot token              | `xoxb-`                           | 20 characters |
| PEM private key              | `-----BEGIN ... PRIVATE KEY-----` | —             |

**Scanned files:** `.mcp.json`, `mcp.json`, `.cursor/mcp.json`, `.vscode/mcp.json`, `.claude/settings.json`, `claude_desktop_config.json`, `cline_mcp_settings.json`, and any `*.pkl` file whose path contains `mcp` or `config`.

Only literal credential values trigger the finding. Detected values are redacted in Charter output (first 4 characters followed by `…`).

## Examples

<Tabs>
  <Tab title="Failing">
    ```json .mcp.json theme={null}
    {
      "mcpServers": {
        "my-server": {
          "type": "http",
          "url": "https://my-mcp-server.example.com",
          "headers": {
            "Authorization": "Bearer sk-proj-abc123T3BlbkFJXxyzABCDEF"
          }
        }
      }
    }
    ```

    ```
    # Charter detects: sk-p… (redacted) in .mcp.json — fires Blocker
    ```
  </Tab>

  <Tab title="Passing">
    ```json .mcp.json theme={null}
    {
      "mcpServers": {
        "my-server": {
          "type": "http",
          "url": "https://my-mcp-server.example.com",
          "headers": {
            "Authorization": "Bearer ${MCP_API_KEY}"
          }
        }
      }
    }
    ```
  </Tab>
</Tabs>

## How to fix

<Steps>
  <Step title="Rotate the credential externally">
    Revoke and regenerate the secret in the provider's dashboard before touching any files. The commit that introduced the literal value exposed it.
  </Step>

  <Step title="Remove the literal value from the MCP config">
    Delete the raw credential from the header value in the config file.
  </Step>

  <Step title="Replace with an environment variable reference">
    Use `${MCP_API_KEY}` or `$MCP_API_KEY` in place of the literal value. Most MCP runtimes (`npx`, `uvx`) resolve environment variables at tool invocation time.
  </Step>

  <Step title="Commit the fix">
    Commit the updated config file. Charter re-scans on next run and clears the finding once no literal credential is detected.
  </Step>

  <Step title="If the secret is already in git history">
    The credential is compromised. Rotate first, then consider a history rewrite (`git filter-repo`) — coordinate with all collaborators before rewriting shared history.
  </Step>
</Steps>

## Score impact

<Warning>
  `Blocker` (−20 per finding) with a raw-secret cap: the final [score](/docs/concepts/scoring-and-caps) is held at **≤49** while AE-SEC-001 or AE-SEC-002 is active. This overrides the base formula. Caps are reserved for raw-secret and Blocker findings.
</Warning>

<Tip>
  Use env var references in MCP auth headers. Most MCP runtimes resolve environment variables at tool invocation time — the credential never needs to live in the config file itself.
</Tip>

## Edge cases

Environment variable references (`${VAR}`, `$VAR`) and placeholder strings (`your-api-key-here`) are explicitly excluded — only literal credential values trigger the finding. Only git-tracked files are in scope.

## Related rules

<CardGroup cols={2}>
  <Card title="AE-SEC-001" icon="lock" href="/rules/AE-SEC-001">
    Same patterns applied to agent context files.
  </Card>

  <Card title="AE-MCP-001" icon="shield" href="/rules/AE-MCP-001">
    MCP servers must be pinned to exact versions.
  </Card>

  <Card title="AE-MCP-003" icon="shield" href="/rules/AE-MCP-003">
    Remote MCP servers must declare auth.
  </Card>
</CardGroup>

## CLI

```bash theme={null}
charter explain AE-SEC-002
```
