# Security

Source: https://getanalog.io/docs/security/

How Analog protects credentials and blocks unintended private-network access.

## Credential storage and scope

Your API key lives in an owner-only local file — the
`~/.aws/credentials` posture. Any process running as you can read it,
including the agent driving your session. A leaked key is bounded by
**server-side revocation** (`analog logout` asks the server to revoke it and
warns with a manual remedy if that request fails), **origin binding** (the key
refuses to travel to any host but the one it was minted against), and
**product scope** (extraction, feedback, and the shipped key-listing and
key-revocation commands).

## Network address guard

`browse` and `assess` accept only `http` and `https` top-level URLs. Every
fetcher declines `localhost` and literal IP addresses that are not global
unicast by default. Paginated sweeps follow only links on the page's own host
and apply the same guard before each hop.

The local Playwright browser also checks each HTTP, HTTPS, and WebSocket
destination made by the rendered page before connecting. This includes
redirect hops, client-side navigation, and subresources. It resolves a
hostname once per page fetch and requires every returned address to be
public. A non-public answer, a failed lookup, or any refused page request
fails the whole fetch rather than returning a silently incomplete page.

Reaching a trusted dev server or intranet host on purpose is an explicit
opt-in: `--allow-private` (`allow_private=True`). That opt-in disables the
browser boundary for the page, including its subresources.

This is a request guard, not DNS pinning or operating-system egress
isolation. Python evaluates the hostname first, then Chromium resolves it
independently when making an allowed request. A hostname that changes
between those operations can still select a different address. Do not
treat the local browser as a complete sandbox for hostile pages.