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

# Credential Linting

> Automatic detection of hardcoded credentials and sensitive data in agent-generated code

FTL's credential linter scans all agent-generated code changes for hardcoded secrets and dangerous operations before merge. The linter runs automatically as part of the diff review process.

## How It Works

Before you review changes, FTL computes a diff of all modified files and scans added lines for:

1. **Hardcoded shadow credentials** — the `ftl_shadow_*` values injected into the sandbox
2. **Known credential patterns** — API keys, access tokens, and other secrets
3. **Dangerous SQL operations** — destructive database commands
4. **Dangerous shell commands** — destructive filesystem operations

The linter only scans **added lines** (lines starting with `+` in the diff) and skips non-code files like `.lock`, `.json`, `.yaml`, `.yml`, `.toml`, `.cfg`, and `.ini`.

## Detected Patterns

### Shadow Credentials

FTL generates shadow credential values using the pattern `ftl_shadow_<name>_<hex>`. The linter flags any code that hardcodes these values:

```python theme={null}
# BLOCKED: hardcoded shadow value
api_key = "ftl_shadow_stripe_secret_key_7f8a2b3c"
```

It also detects exact matches of the shadow values themselves, even if they don't follow the naming pattern.

> [!WARNING]
>
> If the agent hardcodes a shadow credential, it means the code is not reading from environment variables correctly. This will break when the code runs outside the sandbox with real credentials.

### Known Credential Patterns

The linter detects common API key and token formats:

| Pattern | Description | Example |
| - | - | - |
| `sk_live_*` | Stripe live keys | `sk_live_abc123...` |
| `sk_test_*` | Stripe test keys | `sk_test_xyz789...` |
| `sk-ant-*` | Anthropic API keys | `sk-ant-api03-...` |
| `AKIA*` | AWS access keys | `AKIAIOSFODNN7EXAMPLE` |
| `ghp_*` | GitHub Personal Access Tokens | `ghp_abcd1234...` |
| `gho_*` | GitHub OAuth tokens | `gho_xyz9876...` |
| `glpat-*` | GitLab Personal Access Tokens | `glpat-abc123...` |
| `xoxb-*` | Slack bot tokens | `xoxb-123-456...` |
| `xoxp-*` | Slack user tokens | `xoxp-123-456...` |
| `SG.*` | SendGrid API keys | `SG.abc123...def456` |

All patterns require the value to be quoted (single or double quotes) to reduce false positives.

### Dangerous SQL Operations

The linter flags destructive SQL commands:

* `DROP TABLE`
* `DROP DATABASE`
* `DROP SCHEMA`
* `TRUNCATE TABLE`
* `TRUNCATE` (without TABLE)
* `DELETE FROM` without `WHERE` clause

These are **advisory warnings**, not hard blocks. The linter reminds you to verify the operation is intentional.

```sql theme={null}
-- FLAGGED: no WHERE clause
DELETE FROM users;

-- OK: has WHERE clause
DELETE FROM users WHERE id = 123;
```

### Dangerous Shell Commands

The linter flags destructive shell operations:

| Pattern | Description |
| - | - |
| `rm -rf` or `rm -fr` | Recursive force deletion |
| `shred` | Secure file deletion |
| `dd if=` | Disk write operations |
| `: > /dev/*` | Truncating device files |
| `chmod -R 777` | Overly permissive recursive permissions |

Like SQL warnings, these are advisory — the linter displays them separately from credential violations.

## Lint Output

When violations are detected, FTL displays them before the diff review:

```
Credential lint: 2 violation(s)

  src/payment.py:15 — Possible hardcoded credential
    api_key = "sk_live_abc123xyz789"

  src/auth.py:42 — Hardcoded shadow credential value
    token = "ftl_shadow_openai_api_key_4d9e2a1f"

The agent wrote code that references credentials directly.
Review carefully before merging.

Dangerous operations: 1 warning(s)

  src/migrate.py:8 — Dangerous SQL: DROP TABLE
    cursor.execute("DROP TABLE old_users")

The agent wrote destructive operations (DROP, DELETE, rm -rf, etc.).
Verify this is intentional before merging.
```

Violations are **advisory only** — you can still approve the merge. However, you should carefully review the flagged code to ensure:

1. Credentials are loaded from environment variables, not hardcoded
2. Destructive operations are intentional and safe

> [!WARNING]
>
> Credential violations indicate the code will not work correctly outside the sandbox. Fix the code to read from `os.environ` or `process.env` before merging.

## Bedrock Guardrails Alternative

For hard-blocking enforcement instead of advisory warnings, configure [Bedrock Guardrails](https://vvennela-ftl-18-95.mintlify.site/security/guardrails.md). When a guardrail is active, it replaces the local linter and **blocks merge** if credentials or PII are detected.

## Implementation Details

The linter is implemented in `ftl/lint.py` using regex patterns. It scans the unified diff format output from the container's internal diff computation.

Key functions:

* `lint_diffs(diffs, shadow_env)` — scans added lines and returns violations
* `display_violations(violations)` — pretty-prints violations to the terminal

The linter runs automatically during `ftl code` and before the interactive `merge` command in the FTL shell. You cannot disable it — it's a core safety layer.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.