feat(config): validate clients and scope security
This commit is contained in:
@@ -7,6 +7,14 @@ git.md rules-git Git operations such as commits, branches, or merges
|
||||
microsoft.md rules-microsoft Microsoft 365, Azure DevOps, or Teams operations
|
||||
refactoring.md rules-refactoring refactoring existing code without changing behavior
|
||||
security.md rules-security any software development task: implementing, modifying, debugging, reviewing, testing, or configuring code, scripts, hooks, or infrastructure
|
||||
security-auth.md rules-security-auth authentication, authorization, sessions, tokens, permissions, or tenant-boundary work
|
||||
security-web.md rules-security-web web, browser, frontend, cookie, redirect, or XSS/CSRF work
|
||||
security-api.md rules-security-api HTTP API, request handling, serialization, or endpoint work
|
||||
security-data.md rules-security-data database, query, persistence, sensitive-data, or multi-tenant work
|
||||
security-files.md rules-security-files file, upload, archive, path, process, IPC, or deserialization work
|
||||
security-network.md rules-security-network network, URL fetch, proxy, outbound request, TLS, or SSRF work
|
||||
security-crypto.md rules-security-crypto cryptography, secrets, credentials, key, or token work
|
||||
security-supply-chain.md rules-security-supply-chain dependency, package, plugin, build, deployment, or CI supply-chain work
|
||||
typescript.md rules-typescript TypeScript or modern ECMAScript implementation work
|
||||
ui-ux.md rules-ui-ux UI or UX design and interaction decisions
|
||||
wpf.md rules-wpf WPF, XAML, or MVVM desktop UI work
|
||||
|
||||
|
@@ -8,6 +8,7 @@ status_line = ["model", "reasoning", "project-name", "git-branch", "context-wind
|
||||
[agents]
|
||||
enabled = true
|
||||
max_concurrent_threads_per_session = 5
|
||||
max_depth = 1
|
||||
|
||||
[features]
|
||||
hooks = true
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
# Configuration
|
||||
|
||||
Codex receives a generated global `AGENTS.md`, agent TOML files, skills, rule files, and a `config.toml` adapter with workspace sandboxing, interactive approval boundaries, automatic approval review, enabled sub-agents, and a five-thread concurrency limit (`max_concurrent_threads_per_session`, the current canonical key; the legacy `max_threads` alias is not emitted). Claude Code receives a generated global `CLAUDE.md`, agent Markdown files, skills, and `settings.json` with the `auto` permission mode, explicit `Agent` permission, and a five-operation tool/sub-agent concurrency limit. The exact installed locations are resolved from the user profile at install time; no machine-specific absolute path is stored in the repository.
|
||||
Codex receives a generated global `AGENTS.md`, agent TOML files, skills, rule files, and a `config.toml` adapter. It keeps workspace sandboxing, automatic approval review, `agents.enabled = true`, `agents.max_concurrent_threads_per_session = 5`, and `agents.max_depth = 1`. Claude Code receives a generated global `CLAUDE.md`, agent Markdown files, skills, and `settings.json` with `auto` permissions, explicit `Agent` permission, and five-operation concurrency. Installation resolves user paths at runtime; the repository contains no machine-specific paths.
|
||||
|
||||
Claude's rule loading differs from Codex's by design: `general.md` is the only rule shipped as a plain, always-applied file (its text is also embedded directly in `CLAUDE.md`). Every technology- or situation-specific rule in `shared/rules/` is instead generated as a skill under `skills/rules/`, driven by `adapters/claude/rule-skills.tsv` (rule file, skill name, trigger description). Only a skill's name and description are ever permanently in context; Claude loads the full rule text only when it invokes the skill. Codex is unaffected — it keeps receiving every rule as a plain file and is told to load the matching one by path, exactly as before.
|
||||
Codex keeps rules as files and loads only applicable focused rules. Claude embeds `general.md` and generates the remaining rules as skills from `adapters/claude/rule-skills.tsv`. `security.md` is a short universal baseline; focused security rules load only for authentication, web, API, data, files, network, cryptography, and supply-chain work.
|
||||
|
||||
Codex's current configuration schema has no `agents.max_depth` or other agent-recursion-depth key. The only `max_depth`-shaped setting in the schema is `network_proxy.glob_scan_max_depth`, which bounds glob-pattern expansion for the network proxy feature and is unrelated to agents; Claude Code's settings likewise expose no comparable key. The repository does not emit either as an invented key.
|
||||
`agents.max_depth = 1` limits V1 Codex subagent recursion. `features.multi_agent_v2` is not enabled. If enabled later, V2 takes precedence over `agents.enabled` and ignores `agents.max_depth`.
|
||||
|
||||
`[agents].enabled = true` (set explicitly, matching its own documented default) is the current, documented way to enable Codex's multi-agent tools. A separate `[features].multi_agent` toggle exists in the schema but is not set here, since `[agents].enabled` already covers it and setting both would be redundant. `multi_agent_v2` does not appear in the current documented schema at all — it surfaced only in upstream issue titles describing an internal/experimental flag — so it is deliberately not configured.
|
||||
The build parses TOML with Python's standard-library `tomllib`, validates the emitted Claude settings shape, and uses `codex --strict-config` against an isolated generated configuration when Codex is available. This rejects malformed and unknown Codex configuration keys for the installed CLI version.
|
||||
|
||||
Client settings remain thin adapters. Shared semantics remain in `shared/`.
|
||||
|
||||
User plugins are managed separately through `adapters/plugins.tsv` and the client-native plugin commands. They are not copied into `generated/` because each client owns its plugin cache and authentication state.
|
||||
Client settings remain thin adapters. Shared semantics remain in `shared/`. User plugins are managed separately through `adapters/plugins.tsv` and client-native installation commands.
|
||||
|
||||
+38
-7
@@ -12,7 +12,7 @@ $pluginEntries = @(Import-Csv -LiteralPath $pluginManifest -Delimiter ([char]9))
|
||||
if ($pluginEntries.Count -eq 0) { throw 'Plugin manifest must define at least one plugin.' }
|
||||
$pluginNames = @()
|
||||
foreach ($pluginEntry in $pluginEntries) {
|
||||
foreach ($field in @('name','claude_plugin','codex_plugin')) {
|
||||
foreach ($field in @('name','claude_plugin','codex_method')) {
|
||||
if ([string]::IsNullOrWhiteSpace($pluginEntry.$field)) { throw "Missing $field for plugin $($pluginEntry.name)." }
|
||||
}
|
||||
if ($pluginNames -contains $pluginEntry.name) { throw "Duplicate plugin name in manifest: $($pluginEntry.name)" }
|
||||
@@ -52,6 +52,32 @@ function Read-Field($path, $name) {
|
||||
function Quote-Toml($value) {
|
||||
return ('"' + $value.Replace('\','\\').Replace('"','\"').Replace("`r",'').Replace("`n",'\n') + '"')
|
||||
}
|
||||
function Test-CodexSchema($configPath) {
|
||||
if (-not (Get-Command codex -ErrorAction SilentlyContinue)) {
|
||||
if ($env:REQUIRE_CODEX_SCHEMA -eq 'true') { throw 'Codex CLI is required for schema validation.' }
|
||||
Write-Warning 'Codex CLI unavailable; skipped Codex schema validation.'
|
||||
return
|
||||
}
|
||||
$tempHome = Join-Path ([System.IO.Path]::GetTempPath()) ("codex-schema-" + [Guid]::NewGuid())
|
||||
$previousCodexHome = $env:CODEX_HOME
|
||||
try {
|
||||
New-Item $tempHome -ItemType Directory -Force | Out-Null
|
||||
Copy-Item $configPath (Join-Path $tempHome 'config.toml') -Force
|
||||
$env:CODEX_HOME = $tempHome
|
||||
$previousErrorActionPreference = $ErrorActionPreference
|
||||
try {
|
||||
$ErrorActionPreference = 'Continue'
|
||||
$schemaOutput = @(& codex --strict-config --help 2>&1)
|
||||
$schemaExitCode = $LASTEXITCODE
|
||||
} finally {
|
||||
$ErrorActionPreference = $previousErrorActionPreference
|
||||
}
|
||||
if ($schemaExitCode -ne 0) { throw "Codex schema validation failed: $configPath`n$($schemaOutput -join [Environment]::NewLine)" }
|
||||
} finally {
|
||||
$env:CODEX_HOME = $previousCodexHome
|
||||
Remove-Item $tempHome -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
|
||||
& (Join-Path $root 'shared/hooks/scripts/Test-SessionConfig.ps1') -RepositoryRoot $root
|
||||
|
||||
@@ -75,6 +101,14 @@ Detect the languages, frameworks, tools, and change areas from the repository an
|
||||
|
||||
Load rule files when their subject applies:
|
||||
|
||||
- rules/security-auth.md for authentication, authorization, sessions, tokens, permissions, or tenant boundaries.
|
||||
- rules/security-web.md for browser, frontend, cookie, redirect, XSS, or CSRF work.
|
||||
- rules/security-api.md for HTTP APIs, request handling, serialization, or endpoints.
|
||||
- rules/security-data.md for databases, persistence, sensitive data, or multi-tenancy.
|
||||
- rules/security-files.md for files, uploads, archives, paths, processes, IPC, or deserialization.
|
||||
- rules/security-network.md for network access, URLs, TLS, proxies, or SSRF.
|
||||
- rules/security-crypto.md for cryptography, secrets, credentials, keys, or tokens.
|
||||
- rules/security-supply-chain.md for dependencies, packages, plugins, builds, deployments, or CI.
|
||||
- rules/angular.md for Angular work.
|
||||
- rules/typescript.md for TypeScript work.
|
||||
- rules/csharp.md for C# or .NET work.
|
||||
@@ -154,13 +188,10 @@ foreach ($platform in @('windows','linux')) {
|
||||
}
|
||||
|
||||
$tomlPath = Join-Path $output "codex-$platform/config.toml"
|
||||
$tomlContent = Get-Content -LiteralPath $tomlPath -Raw
|
||||
if (([regex]::Matches($tomlContent, '(?<!\\)"')).Count % 2 -ne 0) { throw "Generated Codex config.toml has unbalanced quotes: $tomlPath" }
|
||||
if (([regex]::Matches($tomlContent, '\[')).Count -ne ([regex]::Matches($tomlContent, '\]')).Count) { throw "Generated Codex config.toml has unbalanced brackets: $tomlPath" }
|
||||
|
||||
$settingsPath = Join-Path $output "claude-$platform/settings.json"
|
||||
try { Get-Content -LiteralPath $settingsPath -Raw | ConvertFrom-Json | Out-Null }
|
||||
catch { throw "Generated Claude settings.json is not valid JSON: $settingsPath" }
|
||||
& python (Join-Path $root 'scripts/validate-config.py') $tomlPath $settingsPath
|
||||
if ($LASTEXITCODE -ne 0) { throw "Generated configuration validation failed for $platform." }
|
||||
Test-CodexSchema $tomlPath
|
||||
}
|
||||
|
||||
$leftoverPlaceholders = @(Get-ChildItem $output -File -Recurse | ForEach-Object {
|
||||
|
||||
+19
-12
@@ -84,6 +84,14 @@ Detect the languages, frameworks, tools, and change areas from the repository an
|
||||
|
||||
Load rule files when their subject applies:
|
||||
|
||||
- rules/security-auth.md for authentication, authorization, sessions, tokens, permissions, or tenant boundaries.
|
||||
- rules/security-web.md for browser, frontend, cookie, redirect, XSS, or CSRF work.
|
||||
- rules/security-api.md for HTTP APIs, request handling, serialization, or endpoints.
|
||||
- rules/security-data.md for databases, persistence, sensitive data, or multi-tenancy.
|
||||
- rules/security-files.md for files, uploads, archives, paths, processes, IPC, or deserialization.
|
||||
- rules/security-network.md for network access, URLs, TLS, proxies, or SSRF.
|
||||
- rules/security-crypto.md for cryptography, secrets, credentials, keys, or tokens.
|
||||
- rules/security-supply-chain.md for dependencies, packages, plugins, builds, deployments, or CI.
|
||||
- rules/angular.md for Angular work.
|
||||
- rules/typescript.md for TypeScript work.
|
||||
- rules/csharp.md for C# or .NET work.
|
||||
@@ -180,19 +188,18 @@ for client in codex claude; do
|
||||
done
|
||||
|
||||
toml_path="$output/codex-$platform/config.toml"
|
||||
quote_count=$(grep -o '"' "$toml_path" | wc -l)
|
||||
[ $((quote_count % 2)) -eq 0 ] || { printf 'Generated Codex config.toml has unbalanced quotes: %s\n' "$toml_path" >&2; exit 1; }
|
||||
open_brackets=$(grep -o '\[' "$toml_path" | wc -l)
|
||||
close_brackets=$(grep -o '\]' "$toml_path" | wc -l)
|
||||
[ "$open_brackets" -eq "$close_brackets" ] || { printf 'Generated Codex config.toml has unbalanced brackets: %s\n' "$toml_path" >&2; exit 1; }
|
||||
|
||||
settings_path="$output/claude-$platform/settings.json"
|
||||
if command -v jq >/dev/null 2>&1; then
|
||||
jq empty "$settings_path" >/dev/null 2>&1 || { printf 'Generated Claude settings.json is not valid JSON: %s\n' "$settings_path" >&2; exit 1; }
|
||||
elif command -v python3 >/dev/null 2>&1 && python3 --version >/dev/null 2>&1; then
|
||||
# On Windows, `python3` can resolve to a non-functional Microsoft Store app-execution
|
||||
# alias that still passes `command -v`; probe it with a real invocation before trusting it.
|
||||
python3 -c 'import json,sys; json.load(open(sys.argv[1], encoding="utf-8"))' "$settings_path" || { printf 'Generated Claude settings.json is not valid JSON: %s\n' "$settings_path" >&2; exit 1; }
|
||||
python3 "$root/scripts/validate-config.py" "$toml_path" "$settings_path"
|
||||
if command -v codex >/dev/null; then
|
||||
schema_home=$(mktemp -d)
|
||||
cp "$toml_path" "$schema_home/config.toml"
|
||||
CODEX_HOME="$schema_home" codex --strict-config --help >/dev/null
|
||||
rm -rf -- "$schema_home"
|
||||
elif [ "${REQUIRE_CODEX_SCHEMA:-false}" = true ]; then
|
||||
printf 'Codex CLI is required for schema validation.\n' >&2
|
||||
exit 1
|
||||
else
|
||||
printf 'WARN Codex CLI unavailable; skipped Codex schema validation.\n' >&2
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
+16
-3
@@ -42,9 +42,16 @@ if (Test-Path -LiteralPath $settingsPath) {
|
||||
}
|
||||
$configTomlPath = Join-Path $homePath '.codex/config.toml'
|
||||
if (Test-Path -LiteralPath $configTomlPath) {
|
||||
$tomlContent = Get-Content -LiteralPath $configTomlPath -Raw
|
||||
$balanced = (([regex]::Matches($tomlContent, '(?<!\\)"')).Count % 2 -eq 0) -and (([regex]::Matches($tomlContent, '\[')).Count -eq ([regex]::Matches($tomlContent, '\]')).Count)
|
||||
if ($balanced) { Result 'PASS' 'installed .codex/config.toml looks structurally valid' } else { Result 'FAIL' 'installed .codex/config.toml has unbalanced quotes or brackets' }
|
||||
$parseResult = & python -c 'import sys,tomllib,pathlib; tomllib.loads(pathlib.Path(sys.argv[1]).read_text(encoding="utf-8-sig"))' $configTomlPath 2>&1
|
||||
if ($LASTEXITCODE -eq 0) { Result 'PASS' 'installed .codex/config.toml parses as TOML' } else { Result 'FAIL' "installed .codex/config.toml is invalid TOML: $parseResult" }
|
||||
if (Get-Command codex -ErrorAction SilentlyContinue) {
|
||||
$previousCodexHome = $env:CODEX_HOME
|
||||
try {
|
||||
$env:CODEX_HOME = Split-Path $configTomlPath -Parent
|
||||
$schemaResult = & codex --strict-config --help 2>&1
|
||||
if ($LASTEXITCODE -eq 0) { Result 'PASS' 'installed .codex/config.toml matches the installed Codex schema' } else { Result 'FAIL' "installed .codex/config.toml has unsupported Codex settings: $schemaResult" }
|
||||
} finally { $env:CODEX_HOME = $previousCodexHome }
|
||||
} else { Result 'WARN' 'Codex CLI unavailable; skipped installed Codex schema validation' }
|
||||
}
|
||||
|
||||
foreach ($destination in @((Join-Path $homePath '.codex'), (Join-Path $homePath '.agents/skills'), (Join-Path $homePath '.claude'))) {
|
||||
@@ -64,6 +71,12 @@ foreach ($destination in @((Join-Path $homePath '.codex'), (Join-Path $homePath
|
||||
|
||||
foreach ($path in @('shared/rules','shared/skills','shared/agents','shared/hooks/scripts')) { if (Test-Path (Join-Path $root $path)) { Result 'PASS' "source $path" } else { Result 'FAIL' "missing $path" } }
|
||||
|
||||
foreach ($client in @('codex','claude')) {
|
||||
$config = if ($client -eq 'codex') { Join-Path $root 'adapters/codex/config/config.toml' } else { Join-Path $root 'adapters/claude/config/settings.json' }
|
||||
$registered = if ($client -eq 'codex') { (Get-Content $config -Raw) -match '\[\[hooks\.Stop\]\]' } else { ((Get-Content $config -Raw | ConvertFrom-Json).hooks.PSObject.Properties.Name -contains 'Stop') }
|
||||
if ($registered) { Result 'PASS' "$client Stop hook is registered" } else { Result 'WARN' "$client ships hook utilities, but no Stop hook is registered" }
|
||||
}
|
||||
|
||||
if ($fail) { exit 1 }
|
||||
Write-Output 'PASS doctor'
|
||||
exit 0
|
||||
|
||||
+6
-6
@@ -55,14 +55,14 @@ if [ -f "$home_path/.claude/settings.json" ]; then
|
||||
fi
|
||||
fi
|
||||
if [ -f "$home_path/.codex/config.toml" ]; then
|
||||
quote_count=$(grep -o '"' "$home_path/.codex/config.toml" | wc -l)
|
||||
open_brackets=$(grep -o '\[' "$home_path/.codex/config.toml" | wc -l)
|
||||
close_brackets=$(grep -o '\]' "$home_path/.codex/config.toml" | wc -l)
|
||||
if [ $((quote_count % 2)) -eq 0 ] && [ "$open_brackets" -eq "$close_brackets" ]; then
|
||||
result PASS 'installed .codex/config.toml looks structurally valid'
|
||||
if python3 -c 'import sys,tomllib,pathlib; tomllib.loads(pathlib.Path(sys.argv[1]).read_text(encoding="utf-8-sig"))' "$home_path/.codex/config.toml"; then
|
||||
result PASS 'installed .codex/config.toml parses as TOML'
|
||||
else
|
||||
result FAIL 'installed .codex/config.toml has unbalanced quotes or brackets'
|
||||
result FAIL 'installed .codex/config.toml is invalid TOML'
|
||||
fi
|
||||
if command -v codex >/dev/null; then
|
||||
if CODEX_HOME="$home_path/.codex" codex --strict-config --help >/dev/null 2>&1; then result PASS 'installed .codex/config.toml matches the installed Codex schema'; else result FAIL 'installed .codex/config.toml has unsupported Codex settings'; fi
|
||||
else result WARN 'Codex CLI unavailable; skipped installed Codex schema validation'; fi
|
||||
fi
|
||||
|
||||
for destination in "$home_path/.codex" "$home_path/.agents/skills" "$home_path/.claude"; do
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Validate the generated configuration formats without third-party packages."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import sys
|
||||
import tomllib
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
CLAUDE_TOP_LEVEL = {"permissions", "env", "statusLine", "hooks"}
|
||||
CLAUDE_PERMISSION_KEYS = {"defaultMode", "allow", "deny"}
|
||||
CLAUDE_STATUS_LINE_KEYS = {"type", "command"}
|
||||
CLAUDE_HOOK_KEYS = {"type", "command", "timeout"}
|
||||
CLAUDE_PERMISSION_MODES = {"acceptEdits", "auto", "bypassPermissions", "default", "dontAsk", "plan"}
|
||||
|
||||
|
||||
def fail(message: str) -> None:
|
||||
raise ValueError(message)
|
||||
|
||||
|
||||
def require_keys(value: object, allowed: set[str], label: str) -> dict[str, object]:
|
||||
if not isinstance(value, dict):
|
||||
fail(f"{label} must be an object")
|
||||
unknown = set(value) - allowed
|
||||
if unknown:
|
||||
fail(f"{label} has unknown keys: {', '.join(sorted(unknown))}")
|
||||
return value
|
||||
|
||||
|
||||
def validate_claude(path: Path) -> None:
|
||||
settings = require_keys(json.loads(path.read_text(encoding="utf-8-sig")), CLAUDE_TOP_LEVEL, str(path))
|
||||
permissions = require_keys(settings.get("permissions"), CLAUDE_PERMISSION_KEYS, "permissions")
|
||||
if permissions.get("defaultMode") not in CLAUDE_PERMISSION_MODES:
|
||||
fail("permissions.defaultMode is unsupported")
|
||||
for key in ("allow", "deny"):
|
||||
if not isinstance(permissions.get(key), list) or not all(isinstance(item, str) for item in permissions[key]):
|
||||
fail(f"permissions.{key} must be an array of strings")
|
||||
env = settings.get("env")
|
||||
if not isinstance(env, dict) or not all(isinstance(key, str) and isinstance(value, str) for key, value in env.items()):
|
||||
fail("env must be an object of string values")
|
||||
status_line = require_keys(settings.get("statusLine"), CLAUDE_STATUS_LINE_KEYS, "statusLine")
|
||||
if status_line.get("type") != "command" or not isinstance(status_line.get("command"), str):
|
||||
fail("statusLine must be a command")
|
||||
hooks = settings.get("hooks")
|
||||
if not isinstance(hooks, dict):
|
||||
fail("hooks must be an object")
|
||||
for event, matchers in hooks.items():
|
||||
if not isinstance(event, str) or not isinstance(matchers, list):
|
||||
fail("hooks must map event names to arrays")
|
||||
for matcher in matchers:
|
||||
if not isinstance(matcher, dict) or not isinstance(matcher.get("hooks"), list):
|
||||
fail(f"hooks.{event} must contain hook arrays")
|
||||
for hook in matcher["hooks"]:
|
||||
hook = require_keys(hook, CLAUDE_HOOK_KEYS, f"hooks.{event}")
|
||||
if hook.get("type") != "command" or not isinstance(hook.get("command"), str) or not isinstance(hook.get("timeout"), int):
|
||||
fail(f"hooks.{event} contains an unsupported command hook")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
if len(sys.argv) != 3:
|
||||
print("usage: validate-config.py <codex-toml> <claude-json>", file=sys.stderr)
|
||||
return 2
|
||||
tomllib.loads(Path(sys.argv[1]).read_text(encoding="utf-8-sig"))
|
||||
validate_claude(Path(sys.argv[2]))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
raise SystemExit(main())
|
||||
except (OSError, ValueError, json.JSONDecodeError, tomllib.TOMLDecodeError) as error:
|
||||
print(f"configuration validation failed: {error}", file=sys.stderr)
|
||||
raise SystemExit(1)
|
||||
@@ -0,0 +1,7 @@
|
||||
# API security
|
||||
|
||||
* Authenticate and authorize protected endpoints; validate every request payload and identifier.
|
||||
* Bound request and response sizes, pagination, query results, and expensive operations.
|
||||
* Apply rate limits where abuse is plausible and keep administrative endpoints separately protected.
|
||||
* Return only authorized data and never expose stack traces, internal models, or implementation details in API errors.
|
||||
* Prefer explicit DTOs and schemas over deserializing arbitrary types or executable objects.
|
||||
@@ -0,0 +1,8 @@
|
||||
# Authentication and authorization security
|
||||
|
||||
* Use established authentication standards and password hashing; never store plaintext or reversibly encrypted passwords.
|
||||
* Enforce authorization server-side for every sensitive operation and verify resource ownership and tenant boundaries.
|
||||
* Use least-privilege roles, short-lived sessions or tokens where supported, and invalidate credentials after sensitive account changes.
|
||||
* Validate token issuer, audience, signature, and expiry before trusting claims.
|
||||
* Protect authentication and privileged actions against brute force and privilege escalation.
|
||||
* Test unauthenticated, unauthorized, cross-user, and cross-tenant access paths.
|
||||
@@ -0,0 +1,6 @@
|
||||
# Cryptography and secrets security
|
||||
|
||||
* Never implement custom cryptographic primitives or use obsolete algorithms.
|
||||
* Use established libraries, authenticated encryption, secure randomness, and verified signatures and certificates.
|
||||
* Treat tokens, private keys, connection strings, and credentials as secrets; keep them out of source, URLs, command lines, logs, fixtures, and frontend code.
|
||||
* Use environment-appropriate secret storage, separate environments, and rotate compromised credentials.
|
||||
@@ -0,0 +1,7 @@
|
||||
# Database and data security
|
||||
|
||||
* Use parameterized queries or ORM parameter binding; never concatenate untrusted input into SQL.
|
||||
* Use least-privilege database accounts and protect connection strings.
|
||||
* Scope tenant-owned queries explicitly and prevent cross-tenant cache, logging, and diagnostic leakage.
|
||||
* Collect and retain only necessary sensitive data; encrypt it in transit and at rest where appropriate.
|
||||
* Avoid raw database errors and use transactions where integrity requires atomicity.
|
||||
@@ -0,0 +1,6 @@
|
||||
# File and process security
|
||||
|
||||
* Validate filenames, content, sizes, and paths; prevent traversal, zip-slip, and unsafe symbolic-link use.
|
||||
* Restrict access to intended directories and do not execute uploaded or untrusted files.
|
||||
* Do not concatenate untrusted input into shell commands; prefer direct APIs and validate process arguments when execution is required.
|
||||
* Treat local files, IPC, and deserialized input as untrusted at relevant boundaries.
|
||||
@@ -0,0 +1,6 @@
|
||||
# Network and SSRF security
|
||||
|
||||
* Use HTTPS and never disable certificate or TLS validation.
|
||||
* Restrict inbound and outbound access to required ports, interfaces, hosts, and protocols.
|
||||
* Treat user-controlled URLs as dangerous: allowlist schemes and hosts, block localhost, metadata, and internal ranges, and revalidate redirects.
|
||||
* Set timeouts, response-size limits, bounded retries, and cancellation for remote operations.
|
||||
@@ -0,0 +1,6 @@
|
||||
# Supply-chain security
|
||||
|
||||
* Keep dependencies minimal, maintained, and from verified sources; respect lockfiles and review identity and compatibility before adding or upgrading packages.
|
||||
* Pin versions where appropriate and remove unused dependencies.
|
||||
* Treat plugins, build scripts, CI actions, and generated artifacts as part of the attack surface.
|
||||
* Use least privilege for build and deployment identities and never expose credentials in pipelines, logs, or artifacts.
|
||||
@@ -0,0 +1,7 @@
|
||||
# Web and frontend security
|
||||
|
||||
* Escape or sanitize untrusted content; never inject untrusted HTML or bypass framework sanitization.
|
||||
* Protect state-changing browser requests from CSRF where applicable.
|
||||
* Use `HttpOnly`, `Secure`, and appropriate `SameSite` cookie settings for sensitive sessions.
|
||||
* Validate redirect targets, avoid sensitive data in URLs, and use CSP and clickjacking protections where applicable.
|
||||
* Treat frontend code and browser storage as visible and never rely on client-side checks for authorization.
|
||||
+9
-402
@@ -1,404 +1,11 @@
|
||||
# Security Guidelines
|
||||
# Security baseline
|
||||
|
||||
Security is a default requirement for all code, architecture, configuration and infrastructure changes.
|
||||
Apply this baseline to every code, configuration, infrastructure, or review task.
|
||||
|
||||
## Core Principles
|
||||
|
||||
* Prefer secure defaults.
|
||||
* Apply least privilege everywhere.
|
||||
* Minimize exposed attack surface.
|
||||
* Treat all external input as untrusted.
|
||||
* Never trust client-side validation alone.
|
||||
* Fail securely.
|
||||
* Prefer deny-by-default over allow-by-default for sensitive operations.
|
||||
* Keep security controls explicit and auditable.
|
||||
* Do not weaken security for convenience.
|
||||
* Do not bypass security mechanisms to make code easier to implement.
|
||||
* Do not introduce insecure temporary solutions.
|
||||
* Prefer simple, well-understood security mechanisms over custom cryptography or clever security logic.
|
||||
|
||||
## Secrets and Credentials
|
||||
|
||||
* Never hardcode passwords, API keys, tokens, connection strings, private keys or secrets.
|
||||
* Never commit secrets to source control.
|
||||
* Never log secrets or credentials.
|
||||
* Never expose secrets in exceptions, diagnostics or UI messages.
|
||||
* Use secure secret storage appropriate to the environment.
|
||||
* Prefer short-lived credentials where supported.
|
||||
* Rotate compromised credentials immediately.
|
||||
* Do not reuse credentials across environments.
|
||||
* Keep development, staging and production credentials separate.
|
||||
* Avoid secrets in URLs, query strings or command-line arguments.
|
||||
* Do not store secrets in frontend code.
|
||||
* Do not include real credentials in examples, tests or fixtures.
|
||||
|
||||
## Authentication
|
||||
|
||||
* Use established authentication standards and framework capabilities.
|
||||
* Do not implement custom authentication protocols without a strong reason.
|
||||
* Store passwords only using modern password hashing algorithms designed for password storage.
|
||||
* Never store plaintext passwords.
|
||||
* Never use reversible encryption for password storage.
|
||||
* Support secure session expiration.
|
||||
* Invalidate sessions or tokens when security-sensitive account state changes.
|
||||
* Protect authentication endpoints against brute-force abuse where applicable.
|
||||
* Avoid exposing whether an account exists unless required.
|
||||
* Require stronger authentication for security-sensitive actions where appropriate.
|
||||
|
||||
## Authorization
|
||||
|
||||
* Enforce authorization on the server side.
|
||||
* Never rely on hidden UI elements, disabled buttons or frontend guards as authorization.
|
||||
* Check authorization for every sensitive operation.
|
||||
* Prefer explicit permission checks.
|
||||
* Use least-privilege roles and permissions.
|
||||
* Avoid broad administrative permissions unless required.
|
||||
* Prevent horizontal privilege escalation between users or tenants.
|
||||
* Prevent vertical privilege escalation between permission levels.
|
||||
* Verify ownership of resources before access or modification.
|
||||
* Do not trust identifiers supplied by the client as proof of authorization.
|
||||
|
||||
## Input Validation
|
||||
|
||||
* Validate all input from users, APIs, files, databases, queues, environment variables and external systems.
|
||||
* Validate type, length, range, format and allowed values.
|
||||
* Prefer allowlists over denylists.
|
||||
* Reject unexpected input.
|
||||
* Normalize input before validation when appropriate.
|
||||
* Do not rely solely on client-side validation.
|
||||
* Validate identifiers before using them for resource access.
|
||||
* Validate uploaded files by content, size and expected type where applicable.
|
||||
* Do not trust file extensions alone.
|
||||
|
||||
## Injection Prevention
|
||||
|
||||
* Never concatenate untrusted input into SQL.
|
||||
* Use parameterized queries or ORM parameter binding.
|
||||
* Never concatenate untrusted input into shell commands.
|
||||
* Avoid executing shell commands when a direct API is available.
|
||||
* Validate and escape command arguments when process execution is required.
|
||||
* Prevent LDAP, XPath, template and expression injection where applicable.
|
||||
* Avoid dynamic code execution.
|
||||
* Avoid `eval`, dynamic compilation and equivalent mechanisms unless strictly required.
|
||||
* Treat template engines and interpreters as security boundaries.
|
||||
|
||||
## Web Security
|
||||
|
||||
* Prevent Cross-Site Scripting by using framework escaping and sanitization.
|
||||
* Never inject untrusted HTML directly.
|
||||
* Avoid bypassing framework sanitization.
|
||||
* Protect state-changing browser requests against CSRF where applicable.
|
||||
* Use secure cookies for sensitive session data.
|
||||
* Use `HttpOnly` for authentication cookies where possible.
|
||||
* Use `Secure` cookies in HTTPS environments.
|
||||
* Configure `SameSite` appropriately.
|
||||
* Use appropriate Content Security Policy where applicable.
|
||||
* Avoid leaking sensitive data through referrers or URLs.
|
||||
* Validate redirect targets to prevent open redirects.
|
||||
* Protect against clickjacking where applicable.
|
||||
|
||||
## API Security
|
||||
|
||||
* Authenticate sensitive endpoints.
|
||||
* Authorize every protected operation.
|
||||
* Validate all request payloads.
|
||||
* Apply reasonable request-size limits.
|
||||
* Apply pagination and bounded queries.
|
||||
* Apply rate limiting where abuse is possible.
|
||||
* Avoid exposing internal models directly when this leaks implementation details.
|
||||
* Return only data the caller is authorized to access.
|
||||
* Do not expose stack traces or internal exception details.
|
||||
* Avoid excessive information in error responses.
|
||||
* Version public APIs intentionally.
|
||||
* Protect administrative endpoints separately where appropriate.
|
||||
|
||||
## Data Protection
|
||||
|
||||
* Collect only data that is actually required.
|
||||
* Minimize storage of sensitive data.
|
||||
* Classify sensitive data explicitly.
|
||||
* Encrypt sensitive data in transit.
|
||||
* Encrypt sensitive data at rest where appropriate.
|
||||
* Do not implement custom encryption algorithms.
|
||||
* Use established cryptographic libraries.
|
||||
* Do not use obsolete cryptographic algorithms.
|
||||
* Do not use hardcoded encryption keys.
|
||||
* Use cryptographically secure random number generation for security-sensitive values.
|
||||
* Avoid exposing personal or sensitive data in logs.
|
||||
* Delete sensitive data when it is no longer required.
|
||||
|
||||
## Cryptography
|
||||
|
||||
* Never design custom cryptographic primitives.
|
||||
* Use current, established cryptographic standards.
|
||||
* Use authenticated encryption when confidentiality and integrity are required.
|
||||
* Verify signatures before trusting signed content.
|
||||
* Validate certificates correctly.
|
||||
* Never disable certificate validation.
|
||||
* Never accept all TLS certificates.
|
||||
* Do not downgrade TLS security.
|
||||
* Use secure randomness for tokens, nonces, identifiers and keys.
|
||||
* Never use predictable random generators for security-sensitive values.
|
||||
|
||||
## Tokens and Sessions
|
||||
|
||||
* Treat tokens as secrets.
|
||||
* Keep token lifetime as short as practical.
|
||||
* Validate issuer, audience, signature and expiration where applicable.
|
||||
* Do not accept unsigned tokens unless explicitly designed and safe.
|
||||
* Do not trust token contents before validation.
|
||||
* Avoid storing long-lived access tokens in insecure browser storage.
|
||||
* Rotate refresh tokens where appropriate.
|
||||
* Revoke compromised tokens where possible.
|
||||
* Prevent replay attacks where the protocol requires it.
|
||||
|
||||
## File Security
|
||||
|
||||
* Validate file names and paths.
|
||||
* Prevent path traversal.
|
||||
* Never concatenate untrusted input directly into filesystem paths.
|
||||
* Restrict file access to intended directories.
|
||||
* Use generated server-side file names where appropriate.
|
||||
* Enforce file size limits.
|
||||
* Validate uploaded content.
|
||||
* Do not execute uploaded files.
|
||||
* Store uploads outside executable web roots where applicable.
|
||||
* Handle archive extraction safely.
|
||||
* Prevent zip-slip and equivalent path traversal attacks.
|
||||
* Avoid following untrusted symbolic links where security-sensitive.
|
||||
|
||||
## Serialization
|
||||
|
||||
* Treat deserialized input as untrusted.
|
||||
* Avoid insecure polymorphic deserialization.
|
||||
* Avoid deserializing arbitrary runtime types.
|
||||
* Use explicit schemas or known DTOs.
|
||||
* Restrict type resolution.
|
||||
* Do not deserialize executable objects or behavior.
|
||||
* Validate deserialized data before use.
|
||||
* Avoid insecure legacy serializers.
|
||||
|
||||
## Database Security
|
||||
|
||||
* Use parameterized queries.
|
||||
* Use least-privilege database accounts.
|
||||
* Do not use administrative database accounts for normal application traffic.
|
||||
* Restrict schema modification permissions in runtime accounts.
|
||||
* Protect connection strings.
|
||||
* Avoid exposing raw database errors.
|
||||
* Limit query size and result sets.
|
||||
* Prevent tenant data leakage.
|
||||
* Verify tenant boundaries in every relevant query.
|
||||
* Use transactions where integrity requires atomicity.
|
||||
|
||||
## Logging and Monitoring
|
||||
|
||||
* Never log secrets.
|
||||
* Never log passwords.
|
||||
* Never log authentication tokens.
|
||||
* Avoid logging sensitive personal data.
|
||||
* Use structured logging.
|
||||
* Include security-relevant context without exposing sensitive values.
|
||||
* Log authentication and authorization failures where appropriate.
|
||||
* Log suspicious or high-risk actions where appropriate.
|
||||
* Avoid log injection by treating user input as data.
|
||||
* Do not let logging failures break critical application behavior.
|
||||
* Ensure logs have appropriate access controls.
|
||||
|
||||
## Error Handling
|
||||
|
||||
* Fail securely.
|
||||
* Do not expose internal stack traces to users.
|
||||
* Do not reveal implementation details unnecessarily.
|
||||
* Preserve diagnostic detail internally where safe.
|
||||
* Avoid different error responses that reveal sensitive existence checks where not required.
|
||||
* Do not swallow security-relevant exceptions.
|
||||
* Do not continue execution after critical validation or authorization failures.
|
||||
|
||||
## Dependencies
|
||||
|
||||
* Keep dependencies minimal.
|
||||
* Prefer maintained and widely used packages.
|
||||
* Avoid abandoned packages.
|
||||
* Avoid unnecessary dependencies for trivial functionality.
|
||||
* Keep dependencies updated with security patches.
|
||||
* Review dependency changes before adoption.
|
||||
* Do not blindly update major versions without compatibility review.
|
||||
* Remove unused dependencies.
|
||||
* Treat transitive dependencies as part of the attack surface.
|
||||
* Verify package identity before installation.
|
||||
* Avoid untrusted package sources.
|
||||
* Respect lockfiles.
|
||||
|
||||
## Supply Chain Security
|
||||
|
||||
* Pin dependency versions where appropriate.
|
||||
* Protect build and deployment pipelines.
|
||||
* Do not expose CI/CD credentials.
|
||||
* Use least privilege for pipeline identities.
|
||||
* Review third-party actions, plugins and build scripts.
|
||||
* Avoid executing untrusted build scripts.
|
||||
* Verify artifacts and sources where practical.
|
||||
* Keep generated artifacts traceable to source.
|
||||
* Do not publish secrets in build logs or artifacts.
|
||||
|
||||
## Configuration
|
||||
|
||||
* Use secure production defaults.
|
||||
* Do not enable debug mode in production.
|
||||
* Do not expose development endpoints in production.
|
||||
* Separate environment-specific configuration.
|
||||
* Validate security-sensitive configuration at startup.
|
||||
* Fail startup when mandatory security configuration is missing.
|
||||
* Do not silently fall back to insecure settings.
|
||||
* Protect configuration files containing sensitive values.
|
||||
|
||||
## Network Security
|
||||
|
||||
* Use HTTPS for sensitive or authenticated communication.
|
||||
* Do not disable TLS validation.
|
||||
* Restrict outbound network access where practical.
|
||||
* Restrict inbound services to required ports and interfaces.
|
||||
* Use timeouts for network operations.
|
||||
* Limit retries to avoid amplification or denial-of-service behavior.
|
||||
* Validate remote endpoints where SSRF is possible.
|
||||
* Do not allow arbitrary user-controlled URLs for privileged server-side requests.
|
||||
* Block access to internal network ranges when handling untrusted remote URLs where applicable.
|
||||
|
||||
## SSRF Prevention
|
||||
|
||||
* Treat user-controlled URLs as dangerous.
|
||||
* Validate schemes.
|
||||
* Prefer allowlisted hosts.
|
||||
* Resolve and verify target addresses where necessary.
|
||||
* Prevent access to localhost, metadata endpoints and internal networks where not explicitly required.
|
||||
* Revalidate after redirects.
|
||||
* Limit redirects.
|
||||
* Apply request timeouts and response-size limits.
|
||||
|
||||
## Concurrency and Resource Abuse
|
||||
|
||||
* Bound concurrency.
|
||||
* Avoid unbounded task creation.
|
||||
* Avoid unbounded queues.
|
||||
* Limit request sizes.
|
||||
* Limit collection sizes when processing external input.
|
||||
* Apply timeouts to external operations.
|
||||
* Apply cancellation where practical.
|
||||
* Prevent expensive operations from being triggered repeatedly without limits.
|
||||
* Protect endpoints against denial-of-service through algorithmic complexity.
|
||||
* Avoid user-controlled regular expressions that may cause catastrophic backtracking.
|
||||
|
||||
## Memory Safety and Resource Management
|
||||
|
||||
* Dispose files, streams, sockets and other resources correctly.
|
||||
* Prevent resource leaks.
|
||||
* Avoid retaining sensitive data in memory longer than necessary.
|
||||
* Avoid unsafe code unless explicitly required.
|
||||
* Review pointer and memory operations carefully.
|
||||
* Avoid exposing raw memory or buffers across trust boundaries.
|
||||
* Clear sensitive buffers where warranted.
|
||||
|
||||
## Multi-Tenant Systems
|
||||
|
||||
* Treat tenant boundaries as security boundaries.
|
||||
* Scope every tenant-owned query explicitly.
|
||||
* Never trust tenant identifiers from the client without authorization.
|
||||
* Prevent cross-tenant cache leakage.
|
||||
* Prevent cross-tenant logging or diagnostics leakage.
|
||||
* Keep tenant-specific secrets isolated.
|
||||
* Test horizontal privilege escalation explicitly.
|
||||
|
||||
## Frontend Security
|
||||
|
||||
* Assume frontend code and data are visible to the user.
|
||||
* Never embed secrets in frontend applications.
|
||||
* Never rely on frontend checks for authorization.
|
||||
* Treat browser storage as potentially accessible to malicious scripts.
|
||||
* Avoid storing sensitive long-lived tokens unnecessarily.
|
||||
* Escape or sanitize untrusted content.
|
||||
* Do not bypass framework security controls without explicit justification.
|
||||
|
||||
## Desktop Application Security
|
||||
|
||||
* Treat local files and IPC input as untrusted where applicable.
|
||||
* Do not assume local users or processes are trusted.
|
||||
* Avoid storing secrets in plaintext configuration.
|
||||
* Protect locally cached sensitive data.
|
||||
* Validate update packages and downloaded executables.
|
||||
* Do not execute arbitrary files or commands from untrusted input.
|
||||
* Use least privilege and avoid unnecessary elevation.
|
||||
|
||||
## Security-Sensitive Changes
|
||||
|
||||
Changes affecting any of the following require additional scrutiny:
|
||||
|
||||
* Authentication
|
||||
* Authorization
|
||||
* Cryptography
|
||||
* Secrets
|
||||
* User permissions
|
||||
* File access
|
||||
* Process execution
|
||||
* Network access
|
||||
* Input validation
|
||||
* Serialization
|
||||
* Database access
|
||||
* Payment or financial data
|
||||
* Personal or confidential data
|
||||
* Admin functionality
|
||||
* Deployment or infrastructure security
|
||||
|
||||
For security-sensitive changes:
|
||||
|
||||
* Prefer established framework functionality.
|
||||
* Review trust boundaries.
|
||||
* Review failure behavior.
|
||||
* Review privilege requirements.
|
||||
* Review input validation.
|
||||
* Review logging for data leakage.
|
||||
* Review backward compatibility for security implications.
|
||||
* Add or update relevant security tests.
|
||||
|
||||
## Security Testing
|
||||
|
||||
* Test authorization failures.
|
||||
* Test invalid and malicious input.
|
||||
* Test boundary values.
|
||||
* Test unauthenticated access.
|
||||
* Test unauthorized resource access.
|
||||
* Test cross-user and cross-tenant access where applicable.
|
||||
* Test expired and invalid credentials.
|
||||
* Test malformed payloads.
|
||||
* Test path traversal where files are involved.
|
||||
* Test injection risks where interpreters or databases are involved.
|
||||
* Test rate and resource limits where abuse is realistic.
|
||||
* Preserve regression tests for discovered security issues.
|
||||
|
||||
## Agent Rules
|
||||
|
||||
* Never intentionally weaken security controls without explicit user instruction.
|
||||
* Never disable certificate validation, authentication, authorization, validation or security middleware to solve a problem.
|
||||
* Never add hardcoded secrets.
|
||||
* Never expose sensitive data for debugging convenience.
|
||||
* Never bypass a security check because it blocks implementation.
|
||||
* Never assume trusted input without a clearly defined trust boundary.
|
||||
* Never silently choose a less secure implementation because it is easier.
|
||||
* If a requested change creates a meaningful security risk, clearly identify the risk before proceeding.
|
||||
* If requirements are ambiguous in a security-sensitive area, ask the user instead of making an autonomous security decision.
|
||||
|
||||
## Priority Order
|
||||
|
||||
Prioritize security decisions in this order:
|
||||
|
||||
* Prevent unauthorized access
|
||||
* Protect sensitive data
|
||||
* Preserve integrity
|
||||
* Minimize privileges
|
||||
* Minimize attack surface
|
||||
* Validate trust boundaries
|
||||
* Maintain availability
|
||||
* Preserve auditability
|
||||
* Optimize usability and performance only within acceptable security constraints
|
||||
|
||||
Security must not be traded away for convenience without an explicit and informed decision.
|
||||
* Treat external input as untrusted and validate at trust boundaries.
|
||||
* Prefer secure defaults, least privilege, explicit authorization, and fail-closed behavior.
|
||||
* Never hardcode, commit, log, expose, or weaken protections for secrets and credentials.
|
||||
* Use established framework and platform security mechanisms; do not invent cryptography or bypass validation, authentication, authorization, or TLS checks.
|
||||
* Keep dependencies minimal and from trusted sources.
|
||||
* Do not disclose sensitive data or internal implementation details in user-facing errors or diagnostics.
|
||||
* Load the applicable focused security rule before changing authentication, web/UI, APIs, databases, files, network access, cryptography, secrets, or supply-chain configuration.
|
||||
|
||||
Reference in New Issue
Block a user