update the repo
This commit is contained in:
43
AGENT_SKILL/secrets_and_phi_safety/CHECKLIST.md
Normal file
43
AGENT_SKILL/secrets_and_phi_safety/CHECKLIST.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Checklist: secrets_and_phi_safety
|
||||
|
||||
## Secret Handling
|
||||
- [ ] No hard-coded secrets (API keys, passwords, tokens, keys) in source code
|
||||
- [ ] All secrets loaded via environment variables (`os.environ.get`, `process.env`, etc.)
|
||||
- [ ] No `.env` files containing secrets in the repository
|
||||
- [ ] No `secrets/` directory contents tracked by Git
|
||||
- [ ] No private keys (`*.pem`, `*.key`) or certificates in the repository
|
||||
- [ ] No model weights or training data files in the repository
|
||||
|
||||
## PHI Protection
|
||||
- [ ] No patient names, IDs, MRNs, SSNs, DOBs, addresses, or phone numbers in:
|
||||
- Console output (`print`, `console.log`)
|
||||
- Application logs (any logging level)
|
||||
- Error messages or exception text
|
||||
- HTTP response bodies (including error responses)
|
||||
- Debug output or test output
|
||||
- [ ] Any identifiers used in logs/tests are clearly synthetic (e.g., `SYNTH-*` prefix)
|
||||
- [ ] Image file paths in logs or responses do not contain actual patient identifiers
|
||||
|
||||
## Test Data and Fixtures
|
||||
- [ ] All test data uses synthetic identifiers:
|
||||
- Patient IDs start with `SYNTH-`
|
||||
- Medical record numbers are clearly fake
|
||||
- No real patient data or realistic facsimiles
|
||||
- [ ] Test fixtures do not contain actual PHI
|
||||
|
||||
## Secrets Directory Protection
|
||||
- [ ] The `secrets/` directory is listed in `.gitignore`
|
||||
- [ ] Before writing to `secrets/`, verified that `.gitignore` includes `secrets/`
|
||||
- [ ] No actual secrets stored in `secrets/` directory (use for non-sensitive configs only if at all)
|
||||
|
||||
## Configuration Safety
|
||||
- [ ] Configuration files do not contain plain-text secrets
|
||||
- [ ] Secrets in configs use environment variable substitution (e.g., `${VAR}` or `env.VAR`)
|
||||
- [ ] TLS certificate paths are configured via environment variables, not hard-coded
|
||||
- [ ] No connection strings with embedded credentials in config files
|
||||
|
||||
## Pre-commit Verification
|
||||
- [ ] Reviewed git diff for accidental secret inclusion
|
||||
- [ ] Checked for strings that resemble keys/tokens (long alphanumeric strings)
|
||||
- [ ] Verified no patient-like identifiers appear in changed files
|
||||
- [ ] Ran secret scanning tool if available (e.g., git-secrets, truffleHog)
|
||||
191
AGENT_SKILL/secrets_and_phi_safety/EXAMPLES.md
Normal file
191
AGENT_SKILL/secrets_and_phi_safety/EXAMPLES.md
Normal file
@@ -0,0 +1,191 @@
|
||||
# Examples: secrets_and_phi_safety
|
||||
|
||||
## Correct Examples
|
||||
|
||||
### Secret Loading
|
||||
```python
|
||||
# Good: Loading from environment variables
|
||||
import os
|
||||
|
||||
API_KEY = os.environ.get("EXTERNAL_API_KEY")
|
||||
if not API_KEY:
|
||||
raise ValueError("EXTERNAL_API_KEY environment variable not set")
|
||||
|
||||
DATABASE_URL = os.environ.get("DATABASE_URL")
|
||||
SECRET_KEY = os.environ.get("SECRET_KEY", "default-dev-key-change-in-prod")
|
||||
```
|
||||
|
||||
```javascript
|
||||
// Good: Node.js environment variables
|
||||
const apiKey = process.env.API_KEY;
|
||||
const dbPassword = process.env.DB_PASSWORD;
|
||||
|
||||
if (!apiKey || !dbPassword) {
|
||||
throw new Error('Missing required environment variables');
|
||||
}
|
||||
```
|
||||
|
||||
### PHI Protection in Logs
|
||||
```python
|
||||
# Good: Logging without PHI
|
||||
import logging
|
||||
import hashlib
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def process_patient_record(patient_record):
|
||||
# Log only non-identifying information
|
||||
logger.info(
|
||||
f"Processing record for patient age group: {get_age_group(patient_record.age)}"
|
||||
)
|
||||
|
||||
# If logging an ID is absolutely necessary, use a hash
|
||||
patient_hash = hashlib.sha256(
|
||||
patient_record.medical_record_number.encode()
|
||||
).hexdigest()[:8]
|
||||
logger.debug(f"Processing hashed MRN: {patient_hash}...")
|
||||
|
||||
# Never do this:
|
||||
# logger.info(f"Processing patient {patient_record.name} (MRN: {patient_record.mrn})")
|
||||
# logger.error(f"Failed to process {patient_record.id}: {str(e)}") # if id is PHI
|
||||
```
|
||||
|
||||
### Test Data with Synthetic Identifiers
|
||||
```python
|
||||
# Good: Test fixtures use SYNTH-* prefix
|
||||
TEST_PATIENTS = [
|
||||
{
|
||||
"patient_id": "SYNTH-PAT-0001",
|
||||
"name": "John Doe", # Note: In real tests, even names should be fake/synthetic
|
||||
"mrn": "SYNTH-MRN-0001",
|
||||
"date_of_birth": "1980-01-01",
|
||||
# ... other test fields
|
||||
},
|
||||
{
|
||||
"patient_id": "SYNTH-PAT-0002",
|
||||
"name": "Jane Smith",
|
||||
"mrn": "SYNTH-MRN-0002",
|
||||
"date_of_birth": "1992-05-15",
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Configuration Files
|
||||
```yaml
|
||||
# Good: docker-compose.yml using environment variables
|
||||
version: '3.8'
|
||||
services:
|
||||
api:
|
||||
image: medical-api:latest
|
||||
environment:
|
||||
- DATABASE_URL=${DATABASE_URL}
|
||||
- API_KEY=${API_KEY}
|
||||
- LOG_LEVEL=${LOG_LEVEL:-info}
|
||||
secrets:
|
||||
- db_cert # Reference to external secret store, not file in repo
|
||||
|
||||
# Secrets are NOT stored in the repo
|
||||
# Use Docker secrets or Kubernetes secrets or similar external secret management
|
||||
```
|
||||
|
||||
```ini
|
||||
# Good: config.ini with environment variable substitution
|
||||
[database]
|
||||
url = ${DATABASE_URL}
|
||||
# or using os.path.expandvars equivalent
|
||||
```
|
||||
|
||||
### .gitignore Protection
|
||||
```gitignore
|
||||
# .gitignore at repository root
|
||||
# ... other entries
|
||||
secrets/
|
||||
*.env
|
||||
*.pem
|
||||
*.key
|
||||
```
|
||||
|
||||
### Safe Error Messages
|
||||
```python
|
||||
# Good: Generic error messages that don't leak PHI
|
||||
try:
|
||||
process_claim(claim_data)
|
||||
except ValidationError as e:
|
||||
# Log detailed error internally (without PHI)
|
||||
logger.warning(f"Claim validation failed: {e}")
|
||||
# Return generic message to user
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail="Claim validation failed. Please check the submitted information."
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Unexpected error processing claim: {e}")
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail="Internal server error. Please contact support."
|
||||
)
|
||||
```
|
||||
|
||||
## Incorrect Examples
|
||||
|
||||
### Secret Exposure
|
||||
```python
|
||||
# Bad: Hard-coded secret
|
||||
API_KEY = "sk_live_1234567890abcdef" # VIOLATION: exposed in code
|
||||
|
||||
# Bad: Secret in config file committed to repo
|
||||
# config.yaml
|
||||
# api_key: "actual_secret_key_here" # VIOLATION
|
||||
|
||||
# Bad: Using .env file that gets committed
|
||||
# .env (committed to git)
|
||||
# DATABASE_URL=postgres://user:password@localhost/db
|
||||
```
|
||||
|
||||
### PHI in Logs and Errors
|
||||
```python
|
||||
# Bad: Logging full patient identifier
|
||||
logger.error(f"Failed to update patient {patient.patient_id}: {str(e)}")
|
||||
# If patient_id is MRN or similar, this leaks PHI
|
||||
|
||||
# Bad: Error message with PHI
|
||||
raise ValueError(f"Invalid DOB for patient {patient.name}: {patient.dob}")
|
||||
|
||||
# Bad: Including PHI in HTTP response
|
||||
return {
|
||||
"error": f"Patient {patient.mrn} not found", # MRN is PHI
|
||||
"code": "PATIENT_NOT_FOUND"
|
||||
}
|
||||
```
|
||||
|
||||
### Real Data in Tests
|
||||
```python
|
||||
# Bad: Test using real patient-like data
|
||||
TEST_PATIENT = {
|
||||
"patient_id": "12345678", # Looks like real MRN
|
||||
"name": "John Doe", # Realistic name
|
||||
"ssn": "123-45-6789", # Actual SSN format
|
||||
"dob": "1980-01-01",
|
||||
}
|
||||
```
|
||||
|
||||
### Missing .gitignore Protection
|
||||
```gitignore
|
||||
# .gitmissing: secrets/ directory NOT ignored
|
||||
# This would allow secrets to be committed
|
||||
# (no entry for secrets/ here)
|
||||
```
|
||||
|
||||
### Insecure Configuration
|
||||
```yaml
|
||||
# Bad: Hard-coded secrets in config
|
||||
database:
|
||||
host: localhost
|
||||
port: 5432
|
||||
username: admin
|
||||
password: "super_secret_password" # VIOLATION
|
||||
|
||||
tls:
|
||||
cert_file: "/etc/ssl/certs/real-cert.pem" # Hard-coded path, should be env var
|
||||
key_file: "/etc/ssl/private/real-key.pem"
|
||||
```
|
||||
72
AGENT_SKILL/secrets_and_phi_safety/SKILL.md
Normal file
72
AGENT_SKILL/secrets_and_phi_safety/SKILL.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# Skill: secrets_and_phi_safety
|
||||
|
||||
## Trigger Conditions
|
||||
Any code or configuration change involving:
|
||||
- Environment variable access
|
||||
- File I/O operations
|
||||
- Logging statements
|
||||
- HTTP request/response handling
|
||||
- Exception handling
|
||||
- Configuration loading
|
||||
- Secret management systems
|
||||
|
||||
## Rules
|
||||
|
||||
### 1. Secret Storage and Access
|
||||
- **Never commit** secrets to version control:
|
||||
- `.env` files
|
||||
- `secrets/` directory contents
|
||||
- Private keys (`*.pem`, `*.key`)
|
||||
- API keys, passwords, tokens
|
||||
- Model weights or training data
|
||||
- All secrets must be loaded via environment variables using:
|
||||
- `os.environ.get("KEY_NAME")` in Python
|
||||
- `process.env.KEY_NAME` in Node.js
|
||||
- Equivalent secure methods in other languages
|
||||
- Hard-coded literal secrets in source code are strictly prohibited.
|
||||
- Severity: `[ERROR]`
|
||||
|
||||
### 2. PHI (Protected Health Information) Protection
|
||||
- **Never log, print, or expose** PHI in any form:
|
||||
- Patient names, IDs, medical record numbers
|
||||
- Dates of birth, ages, genders
|
||||
- Addresses, phone numbers, email addresses
|
||||
- Image file paths or URLs that could identify patients
|
||||
- Diagnosis codes, procedure codes, or treatment details
|
||||
- This applies to:
|
||||
- Console logs (`print()`, `console.log()`)
|
||||
- Application logs (any logging framework)
|
||||
- Exception messages and stack traces
|
||||
- HTTP response bodies (including error responses)
|
||||
- Debug output or test output
|
||||
- CI/CD pipeline artifacts and logs
|
||||
- Use only synthetic/test data with `SYNTH-*` prefix for development and testing.
|
||||
- Severity: `[ERROR]`
|
||||
|
||||
### 3. Test Data and Fixtures
|
||||
- All test fixtures, mock data, and sample data must use synthetic identifiers:
|
||||
- Patient IDs must start with `SYNTH-` (e.g., `SYNTH-PAT-0001`)
|
||||
- Medical record numbers must be clearly fake
|
||||
- No real patient data or derivations thereof
|
||||
- Severity: `[ERROR]`
|
||||
|
||||
### 4. Secrets Directory Protection
|
||||
- The `secrets/` directory must be ignored by Git:
|
||||
- `secrets/` must be listed in `.gitignore` at the repository root
|
||||
- Any attempt to write to `secrets/` directory must first verify that `.gitignore` contains `secrets/` (or `/*` negations, but effectively using a `secrets/` directory, verify `.gitignore` inclusion before first use
|
||||
- Never store actual secrets in the repository, even if encrypted or obfuscated.
|
||||
- Severity: `[ERROR]`
|
||||
|
||||
### 5. Configuration and Secrets Injection
|
||||
- Configuration files (e.g., `.yaml`, `.json`, `.ini`) must not contain secrets.
|
||||
- Use environment variable substitution in config files:
|
||||
- Example: `password: ${DB_PASSWORD}` or `password: env.DB_PASSWORD`
|
||||
- TLS/SSL certificate paths must come from environment variables, not be hardcoded.
|
||||
- Severity: `[ERROR]`
|
||||
|
||||
### 6. Audit and Detection
|
||||
- Before committing, run secret scanning tools if available (e.g., git-secrets, truffleHog, git-leaks)
|
||||
- Review diff for accidental inclusion of:
|
||||
- Strings resembling passwords, keys, or tokens
|
||||
- File paths that look like they could contain PHI
|
||||
- Any literal that looks like an ID number, SSN, MRN, etc.
|
||||
Reference in New Issue
Block a user