feat(05-02): add LEGAL.md, embed it, and wire keyhunter legal command
- Add LEGAL.md at repo root (109 lines) covering CFAA, Computer Misuse Act, EU Directive 2013/40/EU, responsible use, disclosure, and disclaimer. - Mirror to pkg/legal/LEGAL.md for go:embed (Go cannot traverse parents). - Add pkg/legal package exposing Text() for the embedded markdown. - Add cmd/legal.go registering keyhunter legal subcommand to print it.
This commit is contained in:
109
pkg/legal/LEGAL.md
Normal file
109
pkg/legal/LEGAL.md
Normal file
@@ -0,0 +1,109 @@
|
||||
# KeyHunter — Legal Disclaimer for Active Key Verification
|
||||
|
||||
This document describes the legal considerations for using KeyHunter's active
|
||||
verification feature (`keyhunter scan --verify` and related flags). Read it
|
||||
carefully before enabling verification.
|
||||
|
||||
## Purpose
|
||||
|
||||
KeyHunter's verification feature makes outbound HTTP calls to third-party
|
||||
provider APIs (OpenAI, Anthropic, Google, Cohere, and 100+ other LLM/AI
|
||||
services) in order to determine whether an API key discovered during a scan is
|
||||
currently live. Verification is **opt-in**: it runs only when you explicitly
|
||||
pass `--verify`. Passive scanning (the default) never contacts a third party.
|
||||
|
||||
## What --verify Does
|
||||
|
||||
- Sends a single lightweight HTTP request per discovered key to that provider's
|
||||
documented verify endpoint (for example, `GET /v1/models` for OpenAI-style
|
||||
APIs).
|
||||
- Uses only the HTTP methods and bodies documented in the provider's public
|
||||
API reference.
|
||||
- Does **not** modify, create, delete, or otherwise mutate any account or data
|
||||
on the provider's side.
|
||||
- Reads only the metadata the provider voluntarily returns in the response
|
||||
(organization name, rate limit tier, available models).
|
||||
- Masks keys in all logs and output by default; the raw key is never written
|
||||
to disk unless you explicitly pass `--unmask`.
|
||||
|
||||
## Legal Considerations
|
||||
|
||||
Verifying an API key that you do not own or do not have explicit permission to
|
||||
test may constitute unauthorized access under computer-crime statutes in many
|
||||
jurisdictions, including but not limited to:
|
||||
|
||||
- **United States** — Computer Fraud and Abuse Act, 18 U.S.C. § 1030 (CFAA).
|
||||
Unauthorized access to a "protected computer" (broadly interpreted to
|
||||
include any internet-connected server) can result in civil and criminal
|
||||
liability.
|
||||
- **United Kingdom** — Computer Misuse Act 1990, sections 1–3. Unauthorized
|
||||
access, unauthorized access with intent, and unauthorized acts with intent
|
||||
to impair are all criminal offences.
|
||||
- **European Union** — Directive 2013/40/EU on attacks against information
|
||||
systems, transposed into national law by each member state.
|
||||
- **Provider Terms of Service** — In addition to statutory law, every provider
|
||||
imposes contractual terms that typically forbid using credentials you are
|
||||
not authorized to use. Violations can result in account termination and
|
||||
civil claims for damages.
|
||||
|
||||
Making an API call with a stolen or leaked key, **even a single request that
|
||||
does nothing**, may legally qualify as "access without authorization" in these
|
||||
frameworks.
|
||||
|
||||
## Responsible Use
|
||||
|
||||
You should only use `--verify` in the following scenarios:
|
||||
|
||||
- **Your own keys** — keys that belong to accounts you personally own and
|
||||
operate.
|
||||
- **Authorized engagements** — penetration tests, red-team exercises, or bug
|
||||
bounty programs where the scope document **explicitly authorizes** active
|
||||
verification of credentials belonging to the target.
|
||||
- **Your own CI/CD pipelines** — scanning your own source code, your
|
||||
organization's source code (with employer authorization), or container
|
||||
images you are responsible for.
|
||||
|
||||
Do **not** run `--verify` against keys you found in random public
|
||||
repositories, pastes, or leak dumps belonging to third parties without first
|
||||
obtaining the owner's consent.
|
||||
|
||||
## Responsible Disclosure
|
||||
|
||||
If you discover a leaked API key that belongs to someone else:
|
||||
|
||||
1. Do **not** verify it, use it, or publish it.
|
||||
2. Contact the key owner directly. Look for a `security.txt` file at
|
||||
`https://<domain>/.well-known/security.txt`, a security contact on their
|
||||
website, or an entry in a vulnerability disclosure platform.
|
||||
3. Provide enough detail for them to rotate the key (where you found it, what
|
||||
provider it targets, the masked prefix) without exposing the raw secret in
|
||||
your disclosure channel.
|
||||
4. Give the owner reasonable time to respond and rotate before any public
|
||||
disclosure.
|
||||
|
||||
## Disclaimer
|
||||
|
||||
KeyHunter is provided "as is", without warranty of any kind, express or
|
||||
implied, including but not limited to the warranties of merchantability,
|
||||
fitness for a particular purpose, and non-infringement. The authors and
|
||||
contributors of KeyHunter disclaim all liability for any damages, direct or
|
||||
indirect, arising from the use or misuse of this tool. **You, the user, are
|
||||
solely responsible** for ensuring that your use of KeyHunter complies with all
|
||||
applicable laws, regulations, contracts, and terms of service in your
|
||||
jurisdiction and the jurisdiction of any service you interact with.
|
||||
|
||||
## Consent Record
|
||||
|
||||
The first time you run `keyhunter scan --verify`, KeyHunter displays an
|
||||
interactive consent prompt summarizing this disclaimer. You must type `yes`
|
||||
(case-insensitive) to proceed. Your decision is persisted in the local SQLite
|
||||
settings table under the key `verify.consent`. Granted consent is sticky
|
||||
across runs; declined consent is not, so you will be re-prompted next time
|
||||
(in case you change your mind or run in a different environment).
|
||||
|
||||
To review this document at any time, run:
|
||||
|
||||
keyhunter legal
|
||||
|
||||
To reset consent and force a re-prompt, clear the `verify.consent` setting
|
||||
from your KeyHunter database.
|
||||
17
pkg/legal/legal.go
Normal file
17
pkg/legal/legal.go
Normal file
@@ -0,0 +1,17 @@
|
||||
// Package legal exposes the KeyHunter legal disclaimer as a compile-time
|
||||
// embedded string.
|
||||
//
|
||||
// Note: Go's //go:embed directive cannot traverse parent directories, so the
|
||||
// canonical LEGAL.md lives at the repo root (for user visibility) AND a
|
||||
// byte-identical copy lives at pkg/legal/LEGAL.md (for embedding). This
|
||||
// mirrors the dual-location pattern used in Phase 1 for provider YAML files
|
||||
// (providers/*.yaml vs pkg/providers/definitions/*.yaml).
|
||||
package legal
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed LEGAL.md
|
||||
var legalMarkdown string
|
||||
|
||||
// Text returns the embedded LEGAL.md contents.
|
||||
func Text() string { return legalMarkdown }
|
||||
22
pkg/legal/legal_test.go
Normal file
22
pkg/legal/legal_test.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package legal
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestText_NonEmpty(t *testing.T) {
|
||||
got := Text()
|
||||
if len(got) < 500 {
|
||||
t.Fatalf("Text() too short: got %d bytes, want > 500", len(got))
|
||||
}
|
||||
}
|
||||
|
||||
func TestText_ContainsKeyPhrases(t *testing.T) {
|
||||
got := Text()
|
||||
for _, phrase := range []string{"CFAA", "Responsible Use", "Disclaimer"} {
|
||||
if !strings.Contains(got, phrase) {
|
||||
t.Errorf("Text() missing required phrase %q", phrase)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user